Opengl读取及渲染斯坦福三维ply模型

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

搞图形学的童鞋经常需要用斯坦福三维模型来做实验的,模型ply文件下载地址:http://www.cc.gatech.edu/projects/large_models/index.html 及 http://graphics.stanford.edu/data/

因此需要将ply文件解析出来,并在opengl渲染,以下提供我的源代码:

 

void _normalize(const float* coord1,const float *coord2, const float *coord3,float *norm){
	/* calculate Vector1 and Vector2 */
	float va[3], vb[3], vr[3], val;
	va[0] = coord1[0] - coord2[0];
	va[1] = coord1[1] - coord2[1];
	va[2] = coord1[2] - coord2[2];
	vb[0] = coord1[0] - coord3[0];
	vb[1] = coord1[1] - coord3[1];
	vb[2] = coord1[2] - coord3[2];
	/* cross product */
	vr[0] = va[1] * vb[2] - vb[1] * va[2];
	vr[1] = vb[0] * va[2] - va[0] * vb[2];
	vr[2] = va[0] * vb[1] - vb[0] * va[1];
	/* normalization factor */
	val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] );
	norm[0] = vr[0]/val;
	norm[1] = vr[1]/val;
	norm[2] = vr[2]/val;
}
/**
*输入:
*	filename:ply文件名 
*返回:
*	verts:顶点数组
*	icnt,tir_index:三角形索引数组
*	norm:返表面单位法向量,若无须返回,则置为null
*/

bool LoadPly(char* filename,vector *&verts, vector *&tri_index,vector *&norms){
	if(!verts || !tri_index) return false;
	ifstream in(filename);
	if(!in) return false;
	char buffer[300];
	size_t vcnt = 0,fcnt = 0;
	while(in.getline(buffer,300) && strncmp("end_header",buffer,strlen("end_header")) != 0){
		if(strncmp("element vertex",buffer,strlen("element vertex")) == 0){
			sscanf(buffer,"element vertex %d",&vcnt);
		}else if(strncmp("element face",buffer,strlen("element face")) == 0){
			sscanf(buffer,"element face %d",&fcnt);
		}
	}
	if(vcnt == 0 || fcnt == 0) return false;
	for(size_t i = 0; i < vcnt; ++i){
		float v0,v1,v2;
		in.getline(buffer,300);
		sscanf(buffer,"%f %f %f %*s",&v0,&v1,&v2);
		verts->push_back(v0);
		verts->push_back(v1);
		verts->push_back(v2);
	}
	for(size_t i = 0; i < fcnt; ++i){
		in.getline(buffer,300);
		int u0,u1,u2,u3;
		if(buffer[0]=='3'){
			sscanf(buffer,"%*d %d %d %d",&u0,&u1,&u2);
			tri_index->push_back(u0);
			tri_index->push_back(u1);
			tri_index->push_back(u2);
			if(norms){
				float coord0[3]={(*verts)[3*u0],(*verts)[3*u0+1],(*verts)[3*u0+2]};
				float coord1[3]={(*verts)[3*u1],(*verts)[3*u1+1],(*verts)[3*u1+2]};
				float coord2[3]={(*verts)[3*u2],(*verts)[3*u2+1],(*verts)[3*u2+2]};
				float norm[3]; _normalize(coord0,coord1,coord2,norm);
				norms->push_back(norm[0]);
				norms->push_back(norm[1]);
				norms->push_back(norm[2]);
			}
		}else if(buffer[0]=='4'){
			sscanf(buffer,"%*d %d %d %d %d",&u0,&u1,&u2,&u3);
			//四边形拆成两个三角形,不知道这样拆有木有问题的?本人没测试过的。
			tri_index->push_back(u0);
			tri_index->push_back(u1);
			tri_index->push_back(u2);

			tri_index->push_back(u0);
			tri_index->push_back(u2);
			tri_index->push_back(u3);
			if(norms){
				float coord0[3]={(*verts)[3*u0],(*verts)[3*u0+1],(*verts)[3*u0+2]};
				float coord1[3]={(*verts)[3*u1],(*verts)[3*u1+1],(*verts)[3*u1+2]};
				float coord2[3]={(*verts)[3*u2],(*verts)[3*u2+1],(*verts)[3*u2+2]};
				float coord3[3]={(*verts)[3*u3],(*verts)[3*u3+1],(*verts)[3*u3+2]};
				float norm[3]; 
				_normalize(coord0,coord1,coord2,norm);
				norms->push_back(norm[0]);
				norms->push_back(norm[1]);
				norms->push_back(norm[2]);
				_normalize(coord0,coord2,coord3,norm);
				norms->push_back(norm[0]);
				norms->push_back(norm[1]);
				norms->push_back(norm[2]);
			}
		}
	}
	in.close();
	return true;
}

 

你一定见过这只兔子,试一下自己渲染出来吧,效果如图。

Opengl读取及渲染斯坦福三维ply模型_第1张图片

加光照效果:

Opengl读取及渲染斯坦福三维ply模型_第2张图片

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

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