OpenGL入门06.绘制模型

Posted stq_wyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL入门06.绘制模型相关的知识,希望对你有一定的参考价值。

这篇文章来记录一下在OpenGL中是如何绘制模型的,首先我们准备几个模型,obj的文件使用txt打开之后信息如下:

我们仅需要v,vt,vn,以及f开头的数据,v代表vertex,vt代表vertextexcoord,vn代表vertexnormal。首先我们将工程中的光源和材质设置全都注释掉。添加objmodel.cpp和objmodel.h以及vertexdata.cpp和vertexdata.h文件。

objmodel.h:

#pragma once
#include "vertexdata.h"

class ObjModel

public:
	VertexData* mVertexes;
	int* mIndices;
	int mIndexCount;
	void Init(const char* ObjModel);
	void Draw();
;

objmodel.cpp:

#include "objmodel.h"
#include "Utils.h"
#include <string>
#include <sstream>
#include <vector>

void ObjModel::Init(const char* ObjModel)

	struct FloatData
	
		float v[3];
	;

	struct VerticeDefine
	
		int posIndex;
		int texcoordIndex;
		int normalIndex;
	;

	std::vector<FloatData> positions, texcoords, normals;
	std::vector<VerticeDefine> vertexes;
	std::vector<int> indexes;

	unsigned char* filecontent = LoadFileContent(ObjModel);
	std::stringstream ssFileContent((char*)filecontent);
	std::string temp;
	char szOneLine[256];
	while (!ssFileContent.eof())
	
		memset(szOneLine, 0, 256);
		ssFileContent.getline(szOneLine, 256);
		if (strlen(szOneLine) > 0)
		
			if (szOneLine[0] == 'v')
			
				std::stringstream ssOneLine(szOneLine);

				if (szOneLine[1] == 't')
				
					//纹理坐标
					ssOneLine >> temp;
					FloatData floatData;
					ssOneLine >> floatData.v[0];
					ssOneLine >> floatData.v[1];
					texcoords.push_back(floatData);
				
				else if (szOneLine[1] == 'n')
				
					//法线
					ssOneLine >> temp;
					FloatData floatData;
					ssOneLine >> floatData.v[0];
					ssOneLine >> floatData.v[1];
					ssOneLine >> floatData.v[2];
					normals.push_back(floatData);
				
				else
				
					//坐标点
					ssOneLine >> temp;
					FloatData floatData;
					ssOneLine >> floatData.v[0];
					ssOneLine >> floatData.v[1];
					ssOneLine >> floatData.v[2];
					positions.push_back(floatData);
				
			
			else if (szOneLine[0] == 'f')
			
				std::stringstream ssOneLine(szOneLine);
				ssOneLine >> temp;
				std::string vertexStr;
				for (int i = 0; i < 3; i++)
				
					ssOneLine >> vertexStr;
					size_t pos = vertexStr.find_first_of('/');
					std::string posIndexStr = vertexStr.substr(0, pos);
					size_t pos2 = vertexStr.find_first_of('/', pos + 1);
					std::string texcoordIndeStr = vertexStr.substr(pos + 1, pos2 - 1 - pos);
					std::string normalIndexStr = vertexStr.substr(pos2 + 1, vertexStr.length() - 1 - pos2);
					VerticeDefine vd;
					vd.posIndex = atoi(posIndexStr.c_str());
					vd.texcoordIndex = atoi(texcoordIndeStr.c_str());
					vd.normalIndex = atoi(normalIndexStr.c_str());
					//去重
					int nCurrentVertexIndex = -1;
					int nCurrentVertexCount = (int)vertexes.size();
					for (int j = 0; j < nCurrentVertexCount; ++j)
					
						if (vertexes[j].posIndex == vd.posIndex && vertexes[j].normalIndex == vd.normalIndex && vertexes[j].texcoordIndex == vd.texcoordIndex)
						
							nCurrentVertexIndex = j;
							break;
						
					
					if (nCurrentVertexIndex == -1)
					
						nCurrentVertexIndex = (int)vertexes.size();
						vertexes.push_back(vd);
					
					indexes.push_back(nCurrentVertexIndex);
				
			
		
	

	mIndexCount = (int)indexes.size();
	mIndices = new int[mIndexCount];

	for (int i = 0; i < mIndexCount; ++i)
	
		mIndices[i] = indexes[i];
	

	int vertexCount = (int)vertexes.size();
	mVertexes = new VertexData[vertexCount];
 
	for (int i = 0; i < vertexCount; ++i)
	
		memcpy(mVertexes[i].position, positions[vertexes[i].posIndex - 1].v, sizeof(float) * 3);
		memcpy(mVertexes[i].texcoord, texcoords[vertexes[i].texcoordIndex - 1].v, sizeof(float) * 2);
		memcpy(mVertexes[i].normal, normals[vertexes[i].normalIndex - 1].v, sizeof(float) * 3);
	
	delete filecontent;


void ObjModel::Draw()

	//关闭背面渲染,提高效率
	glEnable(GL_CULL_FACE);

	//glPolygonMode(GL_FRONT, GL_LINE);
	glPopMatrix();
	glTranslatef(0.0f, 0.0f, -3.0f);
	glRotatef(30.0f, 0.0f, 1.0f, 0.0f);
	glBegin(GL_TRIANGLES);

	for (int i = 0; i < mIndexCount; ++i)
	
		glTexCoord2fv(mVertexes[mIndices[i]].texcoord);
		glNormal3fv(mVertexes[mIndices[i]].normal);
		glVertex3fv(mVertexes[mIndices[i]].position);
	
	glEnd();
	glPopMatrix();

objmodel.cpp中,我们在Init函数中取到上边所讲到的v,vt,vn以及f开头的数据并保存下来,在Draw()函数中去绘制模型。

vertexdata.h:

#include <windows.h>
#include <gl/GL.h>

class VertexData

public:	
	float position[3];
	float texcoord[2];
	float normal[3];
;

vertexdata.cpp里没有代码。接下来我们在main.cpp里声明ObjModel:

ObjModel model;
model.Init("res/Sphere.obj");

然后调用model.Draw();方法绘制模型,为了让模型好看一些,上篇文章的设置贴图的代码我们保留了,最终效果:

太挫了,不过能看出来是绘制了一个模型出来,接下来再慢慢优化它的显示效果吧

以上是关于OpenGL入门06.绘制模型的主要内容,如果未能解决你的问题,请参考以下文章

由于OpenGL可以执行内置的背面剔除,因此它必须计算顶点法线;可以访问这些而不是将其作为属性发送吗?

什么是openGL中的顺时针面

Linux OpenGL 实践篇-9 模型

在 OpenGL 中平滑面部边缘的技术

OpenGL ES 2.0 卷绕和背面剪裁

OpenGL在显示多个对象时显示白屏