首先来个简单点的.obj文件(如下图所示):
总体处理伪代码如下:
void GraphicsModel::init(const QString filePath)
{
QFile file(filePath);
if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
qDebug()<<"file open failed ... ";
return;
}
QTextStream in(&file);
while(!in.atEnd()){
QString st=in.readLine();
if(st.contains("v ")){
disposeKeyVP(st.right(st.size()-2),m_positions);
}
else if(st.contains("vt ")){
disposeKeyVT(st.right(st.size()-3),m_texcoords);
}
else if(st.contains("vn ")){
disposeKeyVP(st.right(st.size()-3),m_normals);
}
else if(st.contains("f ")){
disposeKeyF(st.right(st.size()-2),m_vertex);
}
}
file.close();
}
这里面只要关心2个地方,一个地方是:
v开头的数据与f开头的数据:
v开头的数据有3个分别是:
1.v:表示vertexes
2.vt:表示vertexes+textures
3.vn:表示vertexes+normals
分别表示顶点坐标,顶点截图信息,以及点的法线。
另外一个要注意的是f,这个f表示face
如上面的 1/1/1表示一个面,
这个面用到的数据是顶点数据(v)的第一条
顶点贴图(vt)的第一条
顶点发线(vn)的第一条
所以一个面由顶点,法线,贴图构成,关键是如何读取这个数据,
一般采用这样的思路:
重点:把面上的每一条属性(如1/1/1中有3个1表示3个属性),存起来,分别指向对应的顶点、顶点贴图、顶点法线。注意这个1是第一条,如果在计算机里面用容器存的话,容器的下标是1,这个大小为1的偏差是要考虑的!
如下的伪代码:
void GraphicsModel::draw()
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,m_texture);
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(0.0f,0.0f,-4.0f);
glRotatef(m_rotateAng,0.0f,0.1f,0.0f);
glBegin(GL_TRIANGLES);
for(int i=0;i<m_indexes.size();i++){
glTexCoord2fv(m_texcoords[m_vertex[m_indexes[i]].texcoordIndex-1].vertex);
glNormal3fv(m_normals[m_vertex[m_indexes[i]].normalIndex-1].vertex);
glVertex3fv(m_positions[m_vertex[m_indexes[i]].posIndex-1].vertex);
}
glEnd();
glPopMatrix();
}
运行截图如下:
来张动态图吧: