声明:本文内容及源代码只能作为学习参考用,转载请注明本声明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();
}
随便下载一个模型渲染出来效果图:
编码请看:http://www.maidoupig.cn