openGL读取obj文件

《代码转自网上》

1.最简单的obj文件的读取

没有采用结构体来储存信息,不过比较有参考意义

 用int **a;来定义二维数组之后需要在使用之前初始化  如:a=new int*[100];

#include <GL/glut.h>
#include <stdio.h>
#include <iostream>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;


int v_num=0; //记录点的数量
int f_num=0; //记录面的数量
int vn_num=0;
GLfloat **vArr; //存放点的二维数组
int **fvArr; //存放面顶点的二维数组
int **fnArr;
GLfloat **vnArr;
string s1,s2,s3,s4;
GLfloat f2,f3,f4;

void getLineNum(string addrstr) //获取点和面的数量
{
	ifstream infile(addrstr.c_str()); //打开指定文件
	string sline;//每一行
	int i=0,j=0;
	
	while(getline(infile,sline)) //从指定文件逐行读取
	{
		if(sline[0]=='v')
		{
			if(sline[1]=='n')
				vn_num++;
			else
				v_num++;
		}
		if(sline[0]=='f')
		{
			f_num++;
		}
	}
}
int readfile(string addrstr) //将文件内容读到数组中去
{
	//getLineNum(addrstr);
	//new二维数组
	vArr=new GLfloat*[v_num];
	for (int 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[3];
		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//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<3;i++)
			{
				in>>s1;
				cout<<s1<<endl;
				//取出第一个顶点和法线索引
				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 init(void)
{
	getLineNum("SHUTTLE.obj");
	readfile("SHUTTLE.obj");
    
	
	GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat mat_shininess[] = {50.0};
    GLfloat light_position[] = {1.0, 1.0f, 1.0, 0.0};
    GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
    glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
	
	  glEnable(GL_LIGHTING);
	  glEnable(GL_LIGHT0);
	  glEnable(GL_DEPTH_TEST);
	

	 /*
	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
	glClearDepth(1.0f);									// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculation
	*/
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glTranslatef(1.0,-0.0,-8.0);
	glScalef(0.1,0.1,0.1);
	
    for (int i=0;i<f_num;i++)
	{
		//	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
		glBegin(GL_TRIANGLES);
		
		glNormal3f(vnArr[fnArr[i][0]-1][0], vnArr[fnArr[i][0]-1][1], vnArr[fnArr[i][0]-1][2]);
		glVertex3f(vArr[fvArr[i][0]-1][0], vArr[fvArr[i][0]-1][1], vArr[fvArr[i][0]-1][2]);
		
		glNormal3f(vnArr[fnArr[i][1]-1][0], vnArr[fnArr[i][1]-1][1], vnArr[fnArr[i][1]-1][2]);
		glVertex3f(vArr[fvArr[i][1]-1][0], vArr[fvArr[i][1]-1][1], vArr[fvArr[i][1]-1][2]);
		
		glNormal3f(vnArr[fnArr[i][2]-1][0], vnArr[fnArr[i][2]-1][1], vnArr[fnArr[i][2]-1][2]);
		glVertex3f(vArr[fvArr[i][2]-1][0], vArr[fvArr[i][2]-1][1], vArr[fvArr[i][2]-1][2]);
		
		glEnd();
	}
	
	glFlush();
	
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(-1.5, 1.5, -1.5 * (GLfloat)h/(GLfloat)w, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);
    else
        glOrtho(-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
	
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

2.通过glm读取obj文件

glm是Nate Miller的obj文件加载类

使用该类需要把glm.c修改为glm.cpp

以下是一些相关操作:

//单位化模型model并返回缩放比例因子
单位化就是把模型通过平移和缩放变换限制到3维坐标系中点为中心的一个单位正方体区域内
GLfloat glmUnitize(GLMmodel* model);
 
//计算模型的宽,高,深尺寸,结果保存在dimensions所指的3元素数组中
GLvoid glmDimensions(GLMmodel* model, GLfloat* dimensions);
 
//按比例参数缩放模型,参数大于1放大,大于0小于1缩小,小于0反射,等于0缩小到0
GLvoid glmScale(GLMmodel* model, GLfloat scale);
 
//反转模型的多边形顶点顺序,同时反转法向量,默认多边形顶点顺序是逆时针的。
GLvoid glmReverseWinding(GLMmodel* model);
 
//计算模型面的法向(假定多边形顶点顺序为逆时针)
GLvoid glmFacetNormals(GLMmodel* model);
 
//计算模型的平滑顶点法向,angle参数为平滑交叉的最大角度(角度制)
GLvoid glmVertexNormals(GLMmodel* model, GLfloat angle);
 
//按线性投影产生纹理坐标,它把顶点线性映射到矩形上
GLvoid glmLinearTexture(GLMmodel* model);
 
//按球形映射产生纹理坐标
GLvoid glmSpheremapTexture(GLMmodel* model);
 
//从内存中释放模型
GLvoid glmDelete(GLMmodel* model);
 
//从Wavefront公司标准的.OBJ文件中读取模型
GLMmodel* glmReadOBJ(char* filename);


代码如下:

<span style="white-space:pre">		</span>GLMmodel *glm_model;
		glm_model = glmReadOBJ("court.obj");
		glmUnitize(glm_model);
		glmScale(glm_model, .1);
		glmFacetNormals(glm_model);
		glmVertexNormals(glm_model, 90);

		list_id = glmList(glm_model, GLM_MATERIAL | GLM_SMOOTH);

		glmDelete(glm_model);
使用时直接调用显示列表就好:glCallList(list_id);

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值