VCG笔记-如何定义mesh

VCG lib提供了很多对mesh进行编码的方式,最常见的就是由一个顶点(vertices )集合和一个三角形(triangles )集合构成,(即三角形构成三角形网格,四面体构成四面体网格)。如下面这行代码就是VCG中定义mesh类型的一个例子:

class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector, std::vector > {};

其中vcg::tri::TriMesh是三角形网格的基本类型,结合如下模板参数进行具体定义:

  • 包含顶点的容器,通常是一个std::vector,用我们自定义的顶点类型来确定vector中的元素类型。
  • 可随机访问的包含面(face)的容器,同样地我们需要用自定义的面类型来确定该容器的元素类型。

也就是说,定义一个网格类型的时候,我们只需要继承vcg::tri::TriMesh,并提供包含编码网格元素的容器即可。在下面这个例子中,我们仍然使用元素类型为MyEdge(顾名思义,就是我们自定义的边的类型)的vector来表示边的集合。注意,VCG中并没有预先定义一个顺序来传递顶点,面,边容器参数,也就是说我们上面这样写只是惯例而已,也可以不按照这个顺序来传递参数。

#include 
#include 

class MyVertex; class MyEdge; class MyFace;
struct MyUsedTypes : public vcg::UsedTypes   ::AsVertexType,
    vcg::Use     ::AsEdgeType,
    vcg::Use     ::AsFaceType>{};
class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::BitFlags  >{};
class MyFace : public vcg::Face<   MyUsedTypes, vcg::face::FFAdj, vcg::face::VertexRef, vcg::face::BitFlags > {};
class MyEdge : public vcg::Edge<   MyUsedTypes> {};
class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector, std::vector  > {};

其中,对vertex、edge、face类型的理解是深入使用VCG lib的关键点。无论是vertex、edge、face还是tetrahedron都是用户自定义的包含一系列特性的集合(collection)。举个例子,你可能期望vertex中包含vertex的(x,y,z)坐标,但是对于该vertex处的surface normal和color等有时候需要,有时候又不需要。VCG lib就为我们提供了十分便捷优雅的方式来定义需要存储在vertex、face、edge种的一些特性,如下面这个例子就按照复杂度递增的方式展示了如何有效的定义MyVertex:

#include <vcg/complex/complex.h>

class MyVertex; class MyEdge; class MyFace;
struct MyUsedTypes : public vcg::UsedTypes<vcg::Use<MyVertex>   ::AsVertexType,
    vcg::Use<MyEdge>     ::AsEdgeType,
    vcg::Use<MyFace>     ::AsFaceType>{};

class MyVertex0 : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f  >{};
class MyVertex1 : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::BitFlags  >{};
class MyVertex2 : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Color4b, vcg::vertex::CurvatureDirf,
    vcg::vertex::Qualityf, vcg::vertex::Normal3f, vcg::vertex::BitFlags  >{};

定义的三个顶点类型分别存储了如下信息:

  • MyVertex0存储了顶点的double类型的三元组坐标(coordinates )和float类型的法向量(normal )
  • MyVertex1在MyVertex0的基础上还存储了4位颜色值
  • MyVertex2存储了一系列的不同的组件或者叫属性(components)

vcg::Vertex是VCG中vertex的基类,vcg::UsedTypes声明了mesh定义中使用的vertex、face、edge等类型。这其实是我们自定义的实体类型(MyVertex,MyEdge,MyFace和在mesh定义中使用的一些其他类)之间的一个映射,或者说这就是一个中间层吧,这样可以给予开发人员更大的灵活性(题外话,不是有大牛说过吗:计算机中的任何问题都可以通过增加一层来解决。这儿的思路是一致的)。还有些其他的属性(components)是为一些简单的几何类型开发的,在vcg/simplex文件夹中,完整的列表可以参看 Vertex Components, Edge Components 和Face Components的官网页面。我们可以在利用这些成分来组装我们需要的vertex/edge/face,进行构建完整的mesh类型。下面是一个完整的例子:

#include 
#include 

// io
#include 
#include 

class MyVertex; class MyEdge; class MyFace;
struct MyUsedTypes : public vcg::UsedTypes   ::AsVertexType,
    vcg::Use     ::AsEdgeType,
    vcg::Use     ::AsFaceType>{};
class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::BitFlags  >{};
class MyFace : public vcg::Face<   MyUsedTypes, vcg::face::FFAdj, vcg::face::VertexRef, vcg::face::BitFlags > {};
class MyEdge : public vcg::Edge<   MyUsedTypes> {};
class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector, std::vector  > {};
int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("Usage trimesh_base \n");
        return -1;
    }
    MyMesh m;
    if (vcg::tri::io::ImporterOFF::Open(m, argv[1]) != vcg::tri::io::ImporterOFF::NoError)
    {
        printf("Error reading file  %s\n", argv[1]);
        exit(0);
    }
    vcg::tri::RequirePerVertexNormal(m);
    vcg::tri::UpdateNormal::PerVertexNormalized(m);
    printf("Input mesh  vn:%i fn:%i\n", m.VN(), m.FN());
    printf("Mesh has %i vert and %i faces\n", m.VN(), m.FN());
    return 0;
}

注意:vcg::face::VertexRef 是存储了三个指向mesh中vertex的指针。

你可能感兴趣的:(VCG,meshlab与vcg)