OpenMesh

3次元メッシュデータのライブラリOpenMeshでよく使う機能の備忘録です.

メッシュデータの作成

ここでは,OpenMeshを使って単純なメッシュデータを作成してみます.

まず,使用するMeshの型をtypedefしておきます.ここでは,デフォルトのPolyMesh_ArrayKernelT<>を使います.

MeshTypeの宣言
1
2
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
typedef OpenMesh::PolyMesh_ArrayKernelT<> MeshType;

頂点データの作成は,以下のようにMeshTypeのmeshを宣言し,add_vertexメソッドで追加していきます.

頂点データの作成
1
2
3
4
5
6
MeshType mesh;
std::vector<MeshType::VertexHandle> vHandles ( numVertices );
for ( int vi = 0; vi < numVertices; vi++ )
{
vHandles[vi] = mesh.add_vertex ( MeshType::Point ( p[vi].x, p[vi].y, p[vi].z ) );
}

面データの作成は,頂点データ作成時に保存しておいたvHandlesで頂点を参照し,面を作成していきます.

面データの作成
1
2
3
4
5
6
7
8
9
10
for ( int fi = 0; fi < numFaces; fi++ )
{
std::vector<MeshType::VertexHandle> face_vhandles;
for ( int fvi = 0; fvi < fvs.length(); fvi++ )
{
face_vhandles.push_back ( vHandles[fvs[fvi]] );
}
mesh.add_face ( face_vhandles );
}

メッシュの位相構造を作成した後は,法線情報をOpenMeshにrequestします.

各種情報のrequest
1
2
mesh.request_vertex_normals();
mesh.update_normals();

ここでは,頂点毎の法線情報を使いたいのでrequest_vertex_normalsを呼んでいます.
他にも,request_face_normals,request_vertex_texcoords2D,request_face_colorsといった関数が用意されていて,
利用したいプロパティに合わせて情報を取得することができます.

メッシュの走査

OpenMeshでは,メッシュを走査するのに,Iteratorが用意されています.

頂点毎の処理
1
2
3
4
5
6
7
MeshType::VertexIter v_it, v_end(mesh.vertices_end());
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
{
MeshType::VertexVertexIter vv_it;
for (vv_it=mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
{}
}

この例では,VertexIterにより頂点毎の処理を,VertexVertexIterにより個々の頂点に繋がっている頂点に対する処理を記述することができます

カスタムプロパティ

OpenMeshでは,頂点,エッジ,面等に対してカスタムプロパティを持たせることが出来ます.

頂点毎のプロパティの追加
1
2
3
4
5
6
OpenMesh::VPropHandleT<float> vpI;
if ( !mesh.get_property_handle ( vpI, "I" ) )
{
mesh.add_property ( vpI, "I" );
mesh.property(vpI).set_persistent(true);
}

add_propertyメソッドでプロパティを追加する際に名前を指定しておくことで,get_property_handleでプロパティハンドルを取得できるようになるのと,set_persistentメソッドでプロパティを保存できるようになります.

頂点毎のプロパティの使用
1
2
3
4
5
6
for ( v_it = mesh.vertices_begin(); v_it != v_end; ++v_it )
{
OpenMesh::Vec3f N = mesh.normal ( *v_it );
float I = std::max<float> ( OpenMesh::dot ( L, N ), 0.0f );
mesh.property ( vpI, *v_it ) = I;
}

プロパティを使用する際には,mesh.property ( vpI, v_it )のようにして設定・取得が可能です(v_itは,MeshType::VertexHandle型).