opengl解析obj模型文件

来源:互联网 发布:端口查询命令 编辑:程序博客网 时间:2024/05/17 23:54

obj模型文件格式

# This file uses centimeters as units for non-parametric coordinates.mtllib Cube.mtlg defaultv -0.500000 -0.500000 0.500000  #顶点坐标v 0.500000 -0.500000 0.500000v -0.500000 0.500000 0.500000v 0.500000 0.500000 0.500000v -0.500000 0.500000 -0.500000v 0.500000 0.500000 -0.500000v -0.500000 -0.500000 -0.500000v 0.500000 -0.500000 -0.500000vt 0.375000 0.000000            #纹理坐标vt 0.625000 0.000000vt 0.375000 0.250000vt 0.625000 0.250000vt 0.375000 0.500000vt 0.625000 0.500000vt 0.375000 0.750000vt 0.625000 0.750000vt 0.375000 1.000000vt 0.625000 1.000000vt 0.875000 0.000000vt 0.875000 0.250000vt 0.125000 0.000000vt 0.125000 0.250000vn 0.000000 0.000000 1.000000     #法线坐标 vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000s 1g Cubeusemtl initialShadingGroupf 1/1/1 2/2/2 3/3/3   #f 顶点索引/uv点索引/法线索引f 3/3/3 2/2/2 4/4/4s 2f 3/3/5 4/4/6 5/5/7f 5/5/7 4/4/6 6/6/8s 3f 5/5/9 6/6/10 7/7/11f 7/7/11 6/6/10 8/8/12s 4f 7/7/13 8/8/14 1/9/15f 1/9/15 8/8/14 2/10/16s 5f 2/2/17 8/11/18 4/4/19f 4/4/19 8/11/18 6/12/20s 6f 7/13/21 1/1/22 5/14/23f 5/14/23 1/1/22 3/3/24
模型解析头文件

#pragma once#include "glew.h"struct VertexData{float position[3];float texcoord[2];float normal[3];};class ObjModel{public:GLuint mVBO, mIBO;unsigned int mIndexCount;public:void Init(const char*modelFilePath);void Bind(GLint posLoc,GLint texcoordLoc,GLint normalLoc);void Draw();};

模型解析实现类

#include "ObjModel.h"#include "utils.h"#include <stdio.h>#include <sstream>#include <string>#include <vector>void ObjModel::Init(const char*modelFilePath){struct VertexInfo{float v[3];VertexInfo(){memset(v,0,sizeof(float)*3);}};struct VertexDefine{int positionIndex;int texcoordIndex;int normalIndex;};/*C++中,iostream类重载了运算符>>和<<>>用于cin对象,表示从标准输入,输入数据到变量中<<用于cout对象,表示将变量数据,输出到标准输出中*/std::vector<VertexInfo> positions;//顶点坐标std::vector<VertexInfo> texcoords;//纹理坐标std::vector<VertexInfo> normals;//法线std::vector<VertexDefine> vertices;std::vector<unsigned int> faces;//加载模型文件char* fileContent = LoadFileContent(modelFilePath);//解析模型文件//stringstream是字符串流 ,它将流与存储在内存中的string对象绑定起来std::stringstream ssFileContent(fileContent);char szOneLine[256];std::string temp;while (!ssFileContent.eof()){memset(szOneLine,0,256);ssFileContent.getline(szOneLine,256);if (strlen(szOneLine)>0){std::stringstream ssOneLine(szOneLine);if (szOneLine[0]=='v')//解析顶点信息{  if (szOneLine[1] == 't')//解析纹理坐标{  VertexInfo vi;  ssOneLine >> temp;//vt  ssOneLine >> vi.v[0];  ssOneLine >> vi.v[1];  texcoords.push_back(vi);}else if (szOneLine[1] == 'n')//解析法线坐标{VertexInfo vi;ssOneLine >> temp;//vnssOneLine >> vi.v[0];ssOneLine >> vi.v[1];ssOneLine >> vi.v[2];normals.push_back(vi);}else //解析顶点信息{VertexInfo vi;ssOneLine >> temp;//vssOneLine >> vi.v[0];ssOneLine >> vi.v[1];ssOneLine >> vi.v[2];positions.push_back(vi);}}else if (szOneLine[0]=='f') //解析面信息{ssOneLine >> temp;//fstd::string vertexStr;for (int i = 0; i < 3; ++i){ssOneLine >> vertexStr;size_t pos = vertexStr.find_first_of('/');std::string positionIndexStr = vertexStr.substr(0, pos);size_t pos2 = vertexStr.find_first_of('/', pos + 1);std::string texcoordIndexStr = vertexStr.substr(pos + 1, pos2 - pos - 1);std::string normalIndexStr = vertexStr.substr(pos2 + 1, vertexStr.length() - pos2 - 1);VertexDefine vd;vd.positionIndex = atoi(positionIndexStr.c_str()) - 1;vd.texcoordIndex = atoi(texcoordIndexStr.c_str()) - 1;vd.normalIndex = atoi(normalIndexStr.c_str()) - 1;//trim the same verticeint nCurrentVertexIndex = -1;size_t nCurrentVerticeCount = vertices.size();for (int j = 0; j<nCurrentVerticeCount; ++j){if (vertices[j].positionIndex == vd.positionIndex&&vertices[j].texcoordIndex == vd.texcoordIndex&&vertices[j].normalIndex == vd.normalIndex){nCurrentVertexIndex = j;break;}}if (nCurrentVertexIndex == -1){nCurrentVertexIndex = (int)vertices.size();vertices.push_back(vd);}faces.push_back(nCurrentVertexIndex);}}}}int vertexCount = (int)vertices.size();VertexData*vertexes = new VertexData[vertexCount];for (int  i = 0; i < vertexCount; ++i){memcpy(vertexes[i].position,positions[vertices[i].positionIndex].v,sizeof(float)*3);memcpy(vertexes[i].texcoord, texcoords[vertices[i].texcoordIndex].v, sizeof(float) * 2);memcpy(vertexes[i].normal, normals[vertices[i].normalIndex].v, sizeof(float) * 3);}//创建VBOglGenBuffers(1,&mVBO);//创建一个bufferglBindBuffer(GL_ARRAY_BUFFER,mVBO);//指定BUFFER类型//将顶点数据上传至GPUglBufferData(GL_ARRAY_BUFFER,sizeof(VertexData)*vertexCount,vertexes,GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER,0);delete vertexes;//创建ibomIndexCount = (int)faces.size();unsigned int *indexes = new unsigned int[mIndexCount];for (int  i = 0; i < mIndexCount; ++i){indexes[i] = faces[i];}glGenBuffers(1,&mIBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mIBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(unsigned int)*mIndexCount,indexes,GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);delete indexes;delete fileContent;}void ObjModel::Bind(GLint posLoc, GLint texcoordLoc, GLint normalLoc){glBindBuffer(GL_ARRAY_BUFFER,mVBO);glEnableVertexAttribArray(posLoc);//启用顶点属性/*参数含义:第一个参数:GPU中顶点属性的引用第二个参数:因为顶点是一个向量,表示向量的维度第三个参数:每个维度数据的类型第四个参数:是否归一化第五个参数:每个顶点间的偏移量第六个参数:顶点数据的起始地址,因为用了VBO,所以起始地址为0实际起始地址跟顶点属性在结构体VertexData中的位置有关*/glVertexAttribPointer(posLoc,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),0);glEnableVertexAttribArray(texcoordLoc);//启用纹理属性glVertexAttribPointer(texcoordLoc,2,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)(sizeof(float)*3));//指定纹理坐标的起始地址glEnableVertexAttribArray(normalLoc);//启用法线属性glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 5));//指定法线坐标的起始地址glBindBuffer(GL_ARRAY_BUFFER,0);}void ObjModel::Draw(){glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mIBO);glDrawElements(GL_TRIANGLES,mIndexCount,GL_UNSIGNED_INT,0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);}

解析结果




原创粉丝点击