obj文件的理解请参考:http://foolog.net/?p=941
要注意一点,obj文件中面的保存,有的是按照三角形(也就是只有三个点),有的是按照空间四边形保存(包含四个点),这里是按照四个点来的,注释中已经给出。
#ifndef GLUT_DISABLE_ATEXIT_HACK
#define GLUT_DISABLE_ATEXIT_HACK
#endif #define GLEW_STATIC
#include <GL/glew.h>
#include <GL/wglew.h>
#include <GL/freeglut.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> //for matrices
#include <glm/gtc/type_ptr.hpp>
//undefine if u want to use the default bending constraint of pbd
#include<sstream>
#include <fstream>
#include<iostream>
using namespace std;
GLfloat rtx = 0.0f, rty = 0.0f, rtz = 0.0;
GLfloat step = 0.1;
//float exp1 = 1e-3;
const int GRID_SIZE = 10;
GLint viewport[4];
GLdouble PP[16];
int v_num; //记录点的数量
int vn_num;//记录法线的数量
int vt_num;//
int f_num; //记录面的数量
GLfloat **vArr; //存放点的二维数组
GLfloat **vnArr;//存放法线的二维数组
int **fvArr; //存放面顶点的二维数组
int **fnArr; //存放面法线的二维数组
int readfile(string addrstr) //将文件内容读到数组中去
{
int i;
string s1;
float f2,f3,f4;
vArr=new GLfloat*[v_num];
for (i=0; i<v_num; i++)
{
vArr[i]=new GLfloat[3];
}
vnArr=new GLfloat*[vn_num];
for (i=0; i<vn_num; i++)
{
vnArr[i]=new GLfloat[3];
}
fvArr=new int*[f_num];
fnArr=new int*[f_num];
for (i=0; i<f_num; i++)
{
fvArr[i]=new int[4];
fnArr[i]=new int[3];
}
ifstream infile(addrstr.c_str());
string sline;//每一行
int ii=0,jj=0,kk=0;
while(getline(infile,sline))
{
if(sline[0]=='v')
{
if(sline[1]=='n')//vn
{
istringstream sin(sline);
sin>>s1>>f2>>f3>>f4;
vnArr[ii][0]=f2;
vnArr[ii][1]=f3;
vnArr[ii][2]=f4;
ii++;
}
else if(sline[1] == 't'){}
else//v
{
istringstream sin(sline);
sin>>s1>>f2>>f3>>f4;
vArr[jj][0]=f2;
vArr[jj][1]=f3;
vArr[jj][2]=f4;
jj++;
}
}
if (sline[0]=='f') //读取面
{
istringstream in(sline);
GLfloat a;
in>>s1;//去掉前缀f
int i,k;
//点数改这里
for(i=0; i<4; i++)
{
in>>s1;
// cout<<s1<<endl;
printf("%s\n",s1.c_str());
//取得顶点索引和法线索引
a=0;
for(k=0; s1[k]!='/'; k++)
{
a=a*10+(s1[k]-48);
}
fvArr[kk][i]=a;
a=0;
for(k=k+2; s1[k]; k++)
{
a=a*10+(s1[k]-48);;
}
fnArr[kk][i]=a;
}
kk++;
}
}
return 0;
}
void getLineNum(string addrstr){ //获取点数以及面数
// cout<<addrstr.c_str()<<endl;
v_num = vn_num = f_num = vt_num = 0;
ifstream infile(addrstr.c_str());
string sline;//每一行
while(getline(infile, sline)){
// cout<<sline<<endl;
printf("%s\n",sline.c_str());
if(sline[0]=='v'){
if(sline[1] == 'n'){
vn_num ++;
}else if(sline[1] =='t'){ //vt
vt_num ++;
}else{
v_num ++;
}
}else{
if(sline[0] == 'f'){
f_num ++;
}
}
}
}
string s1;
GLfloat f2,f3,f4;
void DrawGrid()
{
glBegin(GL_LINES);
glColor3f(0.5f, 0.5f, 0.5f);
for(int i=-GRID_SIZE;i<=GRID_SIZE;i++)
{
glVertex3f((float)i,0,(float)-GRID_SIZE);
glVertex3f((float)i,0,(float)GRID_SIZE);
glVertex3f((float)-GRID_SIZE,0,(float)i);
glVertex3f((float)GRID_SIZE,0,(float)i);
}
glEnd();
}
void draw(void)
{
cout<<f_num;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0,0,-10);
glRotatef(15,1,0,0);
DrawGrid();
glBegin(GL_LINES);
glColor3f(1, 1, 1);
for(int i = 0; i < f_num; i++){
int a0,a1,a2,a3;
a0 = fvArr[i][0]-1;
a1 = fvArr[i][1]-1;
a2 = fvArr[i][2]-1;
//点数改这里
a3 = fvArr[i][3]-1;
glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]);
glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]);
cout<<vArr[a0][0]<<" line "<<vArr[a1][0]<<endl;
glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]);
glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]);
cout<<vArr[a1][0]<<" line "<<vArr[a2][0]<<endl;
glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]);
//点数改这里
glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]);
glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]);
cout<<vArr[a2][0]<<" line "<<vArr[a0][0]<<endl;
glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]);
}
glEnd();
glutSwapBuffers();
}
void OnReshape(int nw, int nh) {
glViewport(0,0,nw, nh);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)nw / (GLfloat)nh, 1.f, 100.0f);
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, PP);
glMatrixMode(GL_MODELVIEW);
}
//float step = 0.001;
int main(int argc, char * argv[])
{
getLineNum("yifu.obj");
readfile("yifu.obj");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(1024, 1024);
glutCreateWindow("Hello OpenGL");
// init();
glutDisplayFunc(draw);
// glutIdleFunc(draw); //指定程序空闲时调用函数
glutReshapeFunc(OnReshape); //指定窗口形状变化时的回调函数
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}