【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();方法绘制模型,为了让模型好看一些,上篇文章的设置贴图的代码我们保留了,最终效果:

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值