研究開発日誌

CG研究・開発のちょっとしたメモ書き

OpenMesh

2015-04-10

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

メッシュデータの作成

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

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

#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
typedef OpenMesh::PolyMesh_ArrayKernelT<>  MeshType;

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

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で頂点を参照し,面を作成していきます.

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します.

mesh.request_vertex_normals();
mesh.update_normals();

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

メッシュの走査

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

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

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メソッドでプロパティを保存できるようになります.

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型).