OpenMesh学习笔记5 OpenMesh+OpenGL的一个例子

OpenMesh+OpenGL的一个例子

    这篇文章主要给一个OpenMesh的例子,其中Mesh数据是从文件中读取的,关于OpenMesh中的Mesh IO,会在后面的博文中给出,这部分代码可以忽略,反正需要知道的就是,经过IO之后,数据就存在一个MyMesh mesh变量中了。然后重点可以看一下其中的点,线,面是怎么遍历的,还有就是点的三维坐标是怎么通过函数返回的。下面直接上代码,后面再做一点简单分析。
#include <iostream>
 ------------------- OpenMesh
#include <OpenMesh\\Core\\IO\\MeshIO.hh>
#include <OpenMesh\\Core\\Mesh\\TriMesh_ArrayKernelT.hh>

 --------------------OpenGL
#include <GL\\freeglut.h>

using namespace std;
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;

MyMesh mesh;
// 
float xRotate = 0.0f;
float yRotate = 0.0f;
float zRotate = 0.0f;
float scale = 1.0;
GLuint showFaceList, showWireList, showPointList;

bool showFace = true;
bool showWire = false;
bool showPoint = false;
// 
void initGL()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	// ------------------- Lighting
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	// ------------------- Display List
	showFaceList = glGenLists(1);
	showWireList = glGenLists(1);
	showPointList = glGenLists(1);
	int temp = mesh.n_edges();
	// SHOW WIRE
	glNewList(showWireList, GL_COMPILE);
	glDisable(GL_LIGHTING);
	glLineWidth(1.0f);
	glColor3f(0.5f, 0.5f, 0.5f);
	glBegin(GL_LINES);
	for (MyMesh::HalfedgeIter he_it = mesh.halfedges_begin(); he_it != mesh.halfedges_end(); ++he_it) {
		glVertex3fv(mesh.point(mesh.from_vertex_handle(*he_it)).data());
		glVertex3fv(mesh.point(mesh.to_vertex_handle(*he_it)).data());
	}
	glEnd();
	glEnable(GL_LIGHTING);
	glEndList();
	// SHOW POINT
	glNewList(showPointList, GL_COMPILE);
	glDisable(GL_LIGHTING);
	glLineWidth(1.0f);
	glColor3f(0.5f, 0.5f, 0.5f);
	glBegin(GL_POINTS);
	for (MyMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) {
		glVertex3fv(mesh.point(*v_it).data());
	}
	glEnd();
	glEnable(GL_LIGHTING);
	glEndList();
	// SHOW FACE
	glNewList(showFaceList, GL_COMPILE);
	for (MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) {
		glBegin(GL_TRIANGLES);
		for (MyMesh::FaceVertexIter fv_it = mesh.fv_iter(*f_it); fv_it.is_valid(); ++fv_it) {
			glNormal3fv(mesh.normal(*fv_it).data());
			glVertex3fv(mesh.point(*fv_it).data());
			//glVertex3f(mesh.point(*fv_it)[0], mesh.point(*fv_it)[1], mesh.point(*fv_it)[2]);
		}
		glEnd();
	}
	glEndList();
}
//
void myReshape(GLint w, GLint h)
{
	glViewport(0, 0, static_cast<GLsizei>(w), static_cast<GLsizei>(h));
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w > h)
		glOrtho(-static_cast<GLdouble>(w) / h, static_cast<GLdouble>(w) / h, -1.0, 1.0, -1.0, 1.0);
	else
		glOrtho(-1.0, 1.0, -static_cast<GLdouble>(h) / w, static_cast<GLdouble>(h) / w, -1.0, 1.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
//
void myIdle()
{
	xRotate += 0.5f;
	yRotate += 1.0f;
	zRotate += 1.5f;
	if (xRotate >= 360.0f)
		xRotate -= 360.0f;
	if (yRotate >= 360.0f)
		yRotate -= 360.0f;
	if (zRotate >= 360.0f)
		zRotate -= 360.0f;
	glutPostRedisplay();
}
// 
void mySpecial(int key, int x, int y) {
	switch (key) {
	case GLUT_KEY_UP:
		xRotate += 5.0f;
		break;
	case GLUT_KEY_DOWN:
		xRotate -= 5.0f;
		break;
	case GLUT_KEY_LEFT:
		yRotate += 5.0f;
		break;
	case GLUT_KEY_RIGHT:
		yRotate -= 5.0f;
		break;
	case GLUT_KEY_PAGE_UP:
		scale = scale + 0.02;
		break;
	case GLUT_KEY_PAGE_DOWN:
		scale = scale - 0.02;
		break;
	default:
		break;
	}
	glutPostRedisplay();
}
//
void myKeyboard(unsigned char key, int x, int y)
{
	switch (key) {
	case '1':
		showFace = !showFace;
		break;
	case '2':
		showPoint = !showWire;
		break;
	case '3':
		showWire = !showPoint;
		break;
	default:
		break;
	}
	glutPostRedisplay();
}
// 
void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glRotatef(xRotate, 1.0f, 0.0f, 0.0f);
	glRotatef(yRotate, 0.0f, 1.0f, 0.0f);
	glRotatef(zRotate, 0.0f, 0.0f, 1.0f);
	glScalef(scale, scale, scale);

	if (showFace)
		glCallList(showFaceList);
	if (showPoint)
		glCallList(showPointList);
	if (showWire)
		glCallList(showWireList);
	glutSwapBuffers();
}



int main(int argc, char** argv)
{
	// request vertex normals, so the mesh reader can use normal information
	// if available
	mesh.request_vertex_normals();
	// assure we have vertex normals
	if (!mesh.has_vertex_normals())
	{
		std::cerr << "ERROR: Standard vertex property 'Normals' not available!\\n";
		return 1;
	}
	// Read mesh
	OpenMesh::IO::Options opt;
	const char* filename = "off/23.off";
	if (!OpenMesh::IO::read_mesh(mesh, filename, opt))
	{
		cerr << "Error: Cannot read mesh from " << filename << endl;
		return 1;
	}
	// If the file did not provide vertex normals, then calculate them
	if (!opt.check(OpenMesh::IO::Options::VertexNormal))
	{
		// we need face normals to update the vertex normals
		mesh.request_face_normals();

		// let the mesh update the normals
		mesh.update_normals();

		// dispose the face normals, as we don't need them anymore
		mesh.release_face_normals();
	}
	// write mesh to output.obj
	try
	{
		if (!OpenMesh::IO::write_mesh(mesh, "output.obj"))
		{
			std::cerr << "Cannot write mesh to file 'output.obj'" << std::endl;
			return 1;
		}
	}
	catch (std::exception& x)
	{
		std::cerr << x.what() << std::endl;
		return 1;
	}

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(800, 500);
	glutCreateWindow("Mesh Viewer");
	initGL();
	glutKeyboardFunc(&myKeyboard);
	glutSpecialFunc(&mySpecial);
	glutReshapeFunc(&myReshape);
	glutDisplayFunc(&myDisplay);
	glutMainLoop();
	return 0;
}
    上面的大部分代码都是用于搭建Opengl环境用的,比如设置一些消息处理函数等。对于mesh的操作,主要要了解的有以下几处:
    1,文件读写,这个日后介绍,OpenMesh已经封装了读写off,obj,ply等文件的功能,并且会存储成半边结构;
    2,法向计算,我所读的这个文件里,是没有法向的,以为在后面渲染时要用到法向,所以先计算了法向,这部分也日后介绍;
    3,边,点,面的遍历,也就是上一节介绍的迭代器和循环器。例如显示点的时候,只需要用迭代器就可以了,得到每个点的坐标就行了,得到点的坐标是通过.data()函数实现的,返回的刚好是3维的数组,刚好对应上了opengl函数中的–3*v函数,然后关于边和面就要同时用到迭代器和循环器了,在initGL可以看到,我这里用了3个显示列表,这是OpenGL中的一个功能吧,目的是让程序在渲染的时候快点,程序运行中,可以通过方向键控制模型旋转,PageUp和PageDown控制模型缩放,然后1,2,3控制显示的元素(点,线,面);
    好了,下面就上运行的一个结果,其中的off文件是我从网上下的,是Mesh Segmentation Benchmark网站上下的,百度下就有,里面有300个off文件的。


    三张图分别是显示面,点,线的,当然任意多少种元素一起显示也是可以的。
   

© 版权声明
THE END
喜欢就支持一下吧
点赞560 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容