第一步——创建立方体
翻译,原文地址
本教程包括:
- 如何定义自己的网格类型
- 如何给网格添加顶点和面
- 如何使用 IO 函数保存网格
对于每一个程序,首先得定义自己的网格类型 MyMesh
. OpenMesh 支持多边形网格(即每个面都是有多边形并且顶点数目也可以各不相同)。在本教程中,我们将利用6个四边形创建一个立方体,因此这里我们选择多边形网格作为基础类型
OpenMesh 支持多种网格核 (Mesh Kernels),不同的核其顶点、边和面的存储方式也是不同的,但是所有的存储方式都必须提供与数组类似的接口。在教程中,我们直接使用 OpenMesh 已有的数组核 (ArrayKernel). 诸如 TriMesh/PolyMesh 等预定义类型已经包括在 /src/OpenMesh/Core/Mesh
中,这里我们用 PolyMesh_ArrayKernelT
.
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
既然我们已经声明的网格类型 MyMesh,接下来就要通过添加8个顶点和6个四边形面来创建立方体。添加顶点的函数为 add_vertex
,它输入参数为待插入顶点的坐标,返回值为该顶点的 handle. 这里我们用数组存放顶点的 handles,以便后续用来创建面.
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
为了给网格增加面,需要创建一个 vector 来保存组成该面顶点的handles,然后将该 vector 作为 add_face
的参数,具体代码如下
std::vector<MyMesh::VertexHandle> face_vhandles;
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
面的方向由顶点的顺序决定,如果从正前方观察该多边形,加入顶点应该呈逆时针顺序。
创建完网格后,可以通过 OpenMesh::IO
中的函数将网格保存到硬盘。
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") )
完整代码如下
#include <iostream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
// ----------------------------------------------------------------------------
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
// ----------------------------------------------------------------------------
// Build a simple cube and write it to std::cout
int main()
{
MyMesh mesh;
// generate vertices
MyMesh::VertexHandle vhandle[8];
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
// generate (quadrilateral) faces
std::vector<MyMesh::VertexHandle> face_vhandles;
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[4]);
face_vhandles.push_back(vhandle[5]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[6]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[7]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
// write mesh to output.obj
try
{
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") )
{
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
return 1;
}
}
catch( std::exception& x )
{
std::cerr << x.what() << std::endl;
return 1;
}
return 0;
}