继续上篇的内容,根据OBJ文件格式载入模型,并利用OpenGL的Indexed VBO技术进行渲染。本文所在的载入类ZWModelOBJ,如果阁下发现有什么BUG或者有什么好的建议,请多指教。作者地址是——http://www.ZwqXin.com
本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
原文地址:http://www.zwqxin.com/archives/opengl/obj-model-format-import-and-render-2.html
2. OBJ,从读入到渲染
对一个模型来说,初始化的时候调用导入函数进行“读入”,渲染时调用渲染函数进行渲染,这是最基本的步骤了:
- //导入模型
- bool ImportModel(wchar_t *strFileName);
- //渲染模型
- void RenderModel();
其中,导入函数读入obj文件,然后开始存取数据:
- //ImportModel函数part1
- bool ZWModelOBJ::ImportModel(wchar_t *strFileName, GLuint usage)
- {
- ..............
- // 打开文件
- _wfopen_s(&m_FilePointer, szPathFileName, L"rb");
- ...............
- // 读入文件信息
- ProcessFileInfo(&m_ModelOBJ); //m_ModelOBJ即我们的模型对象t3DModel
- m_ModelOBJ.bIsTextured = true;
- // 关闭打开的文件
- fclose(m_FilePointer);
- ....................
在上篇[OBJ模型文件的结构、导入与渲染Ⅰ]末尾放出的对象数据的导入结构体如下:
- // 对象信息结构体
- typedef struct tag3DObject
- {
- int nMaterialID; // 纹理ID
- bool bHasTexture; // 是否具有纹理映射
- bool bHasNormal; // 是否具有法线
- std::vector<Vector3> PosVerts; // 对象的顶点
- std::vector<Vector3> Normals; // 对象的法向量
- std::vector<TexCoord> Texcoords; // 纹理UV坐标
- std::vector<unsigned short> Indexes; // 对象的顶点索引
- unsigned int nNumIndexes; // 索引数目
- GLuint nPosVBO;
- GLuint nNormVBO;
- GLuint nTexcoordVBO;
- GLuint nIndexVBO;
- }t3DObject;
很明显地,对于模型里面的每一个网格对象,分别用三个vector保存它的顶点属性:位置、法线、纹理坐标(注意,如之前所述,只有位置属性是必须的),用一个vector来储存顶点索引,另加一个unsigned int来储存索引总数,另用四个unsigned int来保存vertex-VBO、normal-VBO、texcoord-VBO、Index-VBO对象。这里产生了一串问题:
- 怎么划分这些网格对象(t3DObject)?——在obj文件里用组(g)来划分对象(另外,有时在顶点数据区头部也有一个g,不产生对象,应忽略),这固然是合情合理。但是,想想为什么我们要划分对象,而不是整个模型一次过地放入一个结构体里呢?3DS的话那是按chunk来的没什么问题,可是OBJ呢?忽略组(g)信息,把一个个面按顺序导入效果有什么不一样吗?没有——如果你没有材质信息的话。是的,导入模型之所以要区分对象(object)&