スポンサーリンク

VCG LibのFace-FaceやEdge-Faceなどの関連付け

問題

VCG Libraryでは、FaceがVertexのIteratorを持っていて、FaceからVertexを参照できる。

他の参照が必要な場合、vcg::tri::UpdateTopologyでFace-Edge間のリンクなどを計算できるのだが、例外が出たり、それっぽい変数に何も入っていないなどの現象に遭遇することがある。

例1:

vcg::tri::UpdateTopology< MyMesh >::VertexEdge(mesh);

を実行すると、

Missing Component Exception -VEAdjacency-

などというメッセージと共に例外がthrowされ停止する

例2:

OpenEdgeを表示しようと、faceオブジェクトからエッジオブジェクトを取得するためFEpやcFEpを使おうと、以下のように書くと、

  for (const auto& f : mesh.face) {

    for (size_t i = 0; i < 3; i++) {

      if (vcg::face::IsBorder(f, i)) {
        glVertex3d(
          f.cFEp(i)->cV(0)->P().X(),
          f.cFEp(i)->cV(0)->P().Y(),
          f.cFEp(i)->cV(0)->P().Z());
        glVertex3d(
          f.cFEp(i)->cV(1)->P().X(),
          f.cFEp(i)->cV(1)->P().Y(),
          f.cFEp(i)->cV(1)->P().Z());
      }

    }

  }

abort() has been called

と言って落ちる。恐らくリンク情報が作成されていない。

解決方法

VCGではポリゴンを扱うために

class MyVertex : public vcg::Vertex<>
class MyFace : public vcg::Face<>
class MyEdge : public vcg::Edge<>

と、既存の型を継承したデータ型を使う。この時、vcg::Vertex、vcg::Face,vcg::Edgeに各データ型を関連付ける適切な型をテンプレートで与える必要がある。

vcg::tri::UpdateTopology< MyMesh >::FaceFaceを使いたい場合、MyFace定義時に、vcg::face::FFAdjを指定する。なおテンプレート引数の順序は気にしなくて良い。

class MyFace : public vcg::Face  < 
  MyUsedTypes, 
  vcg::face::VertexRef, 
  vcg::face::Normal3f, 
  vcg::face::FFAdj, 
  vcg::face::EFAdj, 
  vcg::face::Mark, 
  vcg::face::VFAdj, 
  vcg::face::BitFlags > {
};
使用したい関数 指定するテンプレート引数
vcg::tri::UpdateTopology< MyMesh >::FaceFace MyFaceにvcg::face::FFAdj
vcg::tri::UpdateTopology< MyMesh >::VertexFace

MyVertexにvcg::vertex::VFAdj

MyFaceにvcg::face::VFAdj

vcg::tri::UpdateTopology< MyMesh >::VertexEdge

MyVertexにvcg::vertex::VEAdj

MyEdgeにvcg::edge::VEAdj

vcg::tri::UpdateTopology< MyMesh >::EdgeEdge MyEdgeにvcg::edge::EEAdj

例えばcFEp()を使いたい場合、まずエッジ情報を作成するため

vcg::tri::UpdateTopology< MyMesh >::AllocateEdge(mesh);

を実行する。しかしAllocateEdgeが中でFFpを要求するので、先んじて

vcg::tri::UpdateTopology< MyMesh >::FaceFace(mesh);

を実行する。FaceFaceを実行するためにはMyFaceにvcg::face::FFAdjを指定しなければならないので追加する。

するとcFEpでabortするので、MyFaceにvcg::face::FEAdjを指定する。

ここまでで、cFEpを使うコードは、以下のようになる。

※ただし、cFEpに必要な物以外を外してある。

//データ型の定義
class MyFace;
class MyVertex;
class MyEdge;
struct MyUsedTypes : public vcg::UsedTypes<  
  vcg::Use<MyVertex>::AsVertexType,
  vcg::Use<MyFace>::AsFaceType,
  vcg::Use<MyEdge>::AsEdgeType> 
{};
class MyVertex : public vcg::Vertex< 
  MyUsedTypes, 
  vcg::vertex::Coord3f> {
};
class MyFace : public vcg::Face  < 
  MyUsedTypes, 
  vcg::face::VertexRef, 
  vcg::face::FFAdj, 
  vcg::face::FEAdj> {
};
class MyEdge : public vcg::Edge< 
  MyUsedTypes, 
  vcg::edge::VertexRef> {
};
class MyMesh : public vcg::tri::TriMesh< 
  std::vector<MyVertex>, 
  std::vector<MyFace>, 
  std::vector<MyEdge> > {
};

  //データの読み込み
  vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, fname);

  //必要に応じて
  vcg::tri::Clean< MyMesh >::RemoveDuplicateVertex(mesh);
  vcg::tri::Clean< MyMesh >::RemoveDuplicateEdge(mesh);
  vcg::tri::Clean< MyMesh >::RemoveDuplicateFace(mesh);

  //エッジ情報作成
  vcg::tri::UpdateTopology< MyMesh >::FaceFace(mesh);
  vcg::tri::UpdateTopology< MyMesh >::AllocateEdge(mesh);

表示

  glLineWidth(2);
  glColor3d(0, 0, 1);
  glBegin(GL_LINES);

  for (const auto& f : mesh.face) {
    for (size_t i = 0; i < 3; i++) {
      glVertex3d(
        f.cFEp(i)->cV(0)->P().X(),
        f.cFEp(i)->cV(0)->P().Y(),
        f.cFEp(i)->cV(0)->P().Z());
      glVertex3d(
        f.cFEp(i)->cV(1)->P().X(),
        f.cFEp(i)->cV(1)->P().Y(),
        f.cFEp(i)->cV(1)->P().Z());
    }
  }
  glEnd();

VCG Library メッシュからfaceのみを削除する

VCG LibraryのBall Pivotingでメッシュ生成

VCG LibraryでkdTree

VCG Library でスムージング

VCG Library ターゲットの周辺のオブジェクトを取得

VCG LibraryでMeshに三角形を登録する方法

VCG Library でポリゴンファイル保存

VCG Libraryで色のついたポリゴンの読み込み・表示

VCG LibのFace-FaceやEdge-Faceなどの関連付け

VCG Library

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: