Opengl读取及渲染Obj三维模型

声明:本文内容及源代码只能作为学习参考用,转载请注明本声明blog.csdn.net/t163ang。

最近为了测试我的碰撞检测代码,需要使用Opengl来导入模型及渲染出来做碰撞,之前我发表一篇文章是对斯坦福模型ply文件渲染的,ply模型资源有限,所以今天看了其它三维模型,发现Obj模型网上有丰富的资源,且表达能力更强,但解析其就相对来讲复杂一些,我看网上一些代码,不是过于简单就是过于复杂,于是自己写了一个,上网下载了几个模型效果可以。渲染调用很简单直接调用RenderObj函数即可。当然如果你要应用到你的项目中,这个代码需要稍微改一改就行罗。另外如果是四边形将会拆成两个三角形,网上好多代码都没这个功能。

 

#define MAXN 1024*1024
#define MAXTEX 32
map ObjMp;
size_t vn,vtn,vnn,fn;
float V[MAXN][3];
float VT[MAXN][2];
float VN[MAXN][3];
size_t F[MAXN][3][3];
size_t TexFacCnt[MAXTEX],TexFacID[MAXTEX],tfn;
#pragma comment( lib, "glaux.lib")
void _InitMtl(const char *filename){
	ifstream in(filename);
	assert(in);
	ObjMp.clear();
	char buffer[300],word[300];
	while(in.getline(buffer,300)){
		if(strncmp("newmtl",buffer,strlen("newmtl"))==0){
			sscanf(buffer,"%*s%s",word);
		}else if(strncmp("map_Kd",buffer+1,strlen("map_Kd"))==0){
			GLuint texName;
			glGenTextures(1,&texName);
			AUX_RGBImageRec *aux = auxDIBImageLoadA(buffer+strlen("\tmap_Kd "));
			glBindTexture(GL_TEXTURE_2D,texName);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexImage2D(GL_TEXTURE_2D,0,3,aux->sizeX,aux->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,aux->data);
			ObjMp.insert(make_pair(word,texName));
			delete aux;
		}
	}
	in.close();
}
void ReadObj(const char *filename){
	ifstream in(filename);
	assert(in);
	char buffer[300];
	vn=1;vnn=1;vtn=1;tfn=0;
	while(in.getline(buffer,300)){
		if(buffer[0] == 'v'){
			if(buffer[1]==' '){
				//v
				sscanf(buffer,"%*s %f %f %f",&V[vn][0],&V[vn][1],&V[vn][2]);
				++vn;
			}else if(buffer[1]=='n' && buffer[2] == ' '){
				//vn
				sscanf(buffer,"%*s %f %f %f",&VN[vnn][0],&VN[vnn][1],&VN[vnn][2]);
				++vnn;
			}else if(buffer[1]=='t' && buffer[2] == ' '){
				//vt
				sscanf(buffer,"%*s %f %f",&VT[vtn][0],&VT[vtn][1]);
				++vtn;
			}
		}else if(buffer[0]=='f'){
			//f
			if(buffer[1] == ' '){
				char str[4][32];
				int sn = sscanf(buffer,"%*s %s %s %s %s",str[0],str[1],str[2],str[3]);
				if(sn == 3){					
					for(size_t i = 0; i < 3; ++i){
						sscanf(str[i],"%d/%d/%d",&F[fn][i][0],&F[fn][i][1],&F[fn][i][2]);
					}
					++fn;
					/*
					直接渲染,但是当模型很大时,速度将很慢
					glBegin(GL_TRIANGLES);
					{
						size_t iv,it,in;
						for(size_t i = 0; i < 3; ++i){
							sscanf(str[i],"%d/%d/%d",&iv,&it,&in);
							glNormal3fv(VN[in]);
							glTexCoord2fv(VT[it]);
							glVertex3fv(V[iv]);
						}
					}
					glEnd();*/
				}else if(sn == 4){
					//拆分成两个三角形,四边形0123分成Tri012和Tri023
					for(size_t i = 0; i < 3; ++i){
						sscanf(str[i],"%d/%d/%d",&F[fn][i][0],&F[fn][i][1],&F[fn][i][2]);
					}
					++fn;
					for(size_t i = 0; i < 3; ++i){
						sscanf(str[i!=0?i+1:0],"%d/%d/%d",&F[fn][i][0],&F[fn][i][1],&F[fn][i][2]);
					}
					++fn;
					/*
					glBegin(GL_TRIANGLES);
					{
						size_t iv,it,in;
						for(size_t i = 0; i < 3; ++i){
							sscanf(str[i],"%d/%d/%d",&iv,&it,&in);
							glNormal3fv(VN[in]);
							glTexCoord2fv(VT[it]);
							glVertex3fv(V[iv]);
						}
						for(size_t i = 0; i < 3; ++i){
							sscanf(str[i!=0?i+1:0],"%d/%d/%d",&iv,&it,&in);
							glNormal3fv(VN[in]);
							glTexCoord2fv(VT[it]);
							glVertex3fv(V[iv]);
						}
					}
					glEnd();
					*/
				}else{
					assert(false);
				}
			}
		}else if(buffer[0]=='m'){
			//mtllib
			if(buffer[1]=='t' && buffer[2]=='l' && buffer[3]=='l'
				&&buffer[4]=='i' && buffer[5] == 'b' && buffer[6] == ' '){
					_InitMtl(buffer+strlen("mtllib "));
					
			}
		}else if(buffer[0]=='u'){
			//usemtl
			if(buffer[1]=='s' && buffer[2]=='e' && buffer[3]=='m'
				&&buffer[4]=='t' && buffer[5] == 'l' && buffer[6] == ' '){
					string key = string(buffer+strlen("usemtl "));
					TexFacCnt[tfn]=fn;//记录信息,以后渲染使用
					if(ObjMp.find(key) != ObjMp.end()){
						//直接在读文件时渲染,处理很方便,但渲染更新速度慢
						//glBindTexture(GL_TEXTURE_2D,ObjMp[key]);
						TexFacID[tfn] = ObjMp[key];
					}else{
						//glBindTexture(GL_TEXTURE_2D,0);
						TexFacID[tfn] = 0;
					}
					++tfn;
			}
		}
	}
}

void RenderObj(const char* filename){
	static bool firstRender = true;
	if(firstRender){
		ReadObj(filename);
		firstRender = false;
	}
	glBegin(GL_TRIANGLES);
	{
		for(size_t i =0,j = 0; i < fn; ++i){
			if(j < tfn && i == TexFacCnt[j]){
				glBindTexture(GL_TEXTURE_2D,TexFacID[j]);
				++j;
			}
			glNormal3fv(VN[F[i][0][2]]);
			glTexCoord2fv(VT[F[i][0][1]]);
			glVertex3fv(V[F[i][0][0]]);

			glNormal3fv(VN[F[i][1][2]]);
			glTexCoord2fv(VT[F[i][1][1]]);
			glVertex3fv(V[F[i][1][0]]);

			glNormal3fv(VN[F[i][2][2]]);
			glTexCoord2fv(VT[F[i][2][1]]);
			glVertex3fv(V[F[i][2][0]]);
		}
	}
	glEnd();
}


随便下载一个模型渲染出来效果图:

 

Opengl读取及渲染Obj三维模型_第1张图片

编码请看:http://www.maidoupig.cn

你可能感兴趣的:(碰撞检测)