OpenMesh入门6(译自OpenMesh6.3 Documents)

使用mesh属性和特征

本例中,我们将演示如何修改位置、法线、颜色、纹理坐标等标准属性的数据类型。前一节中,我们已经学习了通过调用合适的request方法使用标准属性。与自定义属性不同,用户可以指定数据类型,并传递给句柄给mesh,而标准属性中,数据类型通过所谓的特征(traits)结构定义。通过特征结构traits,我们可以自定义并扩展mesh的数据结构,实现这一目的,我们需要修改两个重要的特性:

1.修改位置、法线、颜色及纹理坐标的数据类型

2.扩展mesh实体的节点、表面、边缘及半边

开始吧。

每一个自定义特征,都应该继承自缺省特征。

struct MyTraits: OpenMesh::DefaultTraits

正如前面提到的,我们可以把诸如MyMesh::PointMyMesh::NormalMyMesh::Color,  MyMesh::TexCoord这些标准属性的基本类型都改掉。改成OpenMesh提供的向量(vector)类,甚至用另外一个库的其他类型都可以。这里,我们简单地将位置和法线的数据类型,从缺省的OpenMesh::Vec3f( OpenMesh::DefaultTraits中定义)类型修改为OpenMesh::Vec3d类型。

typedef OpenMesh::Vec3dPoint;

typedef OpenMesh::Vec3dNormal;

(常规的,位置和法线最好是一样的类型,否则,我们就不得不进行大量的,依赖于vector类的,类型转换)

注意这些设置将覆盖其traits父类中的对应元素!既然我们一般都从DefaultTraits类中派生我们自己的traits,那么,现在就看看DefaultTraits是什么样:

实际上,OpenMesh::DefaultTraits仅仅是一个空的结构。它仅定义了位置、法线、纹理坐标和颜色的类型,还有一个我们需要显式调用的属性。

//HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );

 PrevHalfedge 属性有所不同,它不控制一个属性,但他仍然对mesh数据有巨大影响,它在halfedge结构中添加额外的信息,但其对下列因素的影响是双倍的:

1.快速访问前一个半边

2.增加内存开销

使用这个特性,取决于我们的具体需求。一种情况是前一个半边需要经常访问的,如频繁调用add_face()函数,使用这个属性将使其执行时间将会显著下降。但如果不是必要的,我们一般不用它,这样可以降低内存开销。

//HalfedgeAttributes( OpenMesh::Attributes::None );

Then we need 8bytes less per edge, which can be quite a lot as one can derive from the Eulerformula ( ), that for aregular triangle meshes with genus  the number ofedges  is approximatelythree times the number of vertices .(译者注:不太懂这段说什么,不翻译了)

完整代码如下:

#include

#include

//--------------------

#include

#include

#include

#ifndefDOXY_IGNORE_THIS

// Define mypersonal traits

struct MyTraits: OpenMesh::DefaultTraits

{

// Let Point andNormal be a vector of doubles

typedef OpenMesh::Vec3dPoint;

typedef OpenMesh::Vec3dNormal;

// Alreadydefined in OpenMesh::DefaultTraits

//HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );

// Uncomment nextline to disable attribute PrevHalfedge

//HalfedgeAttributes( OpenMesh::Attributes::None );

//

// or

//

//HalfedgeAttributes( 0 );

};

#endif

// Define my meshwith the new traits!

typedef OpenMesh::TriMesh_ArrayKernelTMyMesh;

//------------------------------------------------------------------ main ----

int main(int argc, char **argv)

{

MyMesh mesh;

if (argc!=2)

{

std::cerr <<"Usage:"<< argv[0] << " \n";

return 1;

}

// Just make surethat point element type is double

if ( typeid( OpenMesh::vector_traits::value_type)

!= typeid(double) )

{

std::cerr <<"Ouch!ERROR! Data type is wrong!\n";

return 1;

}

// Make sure thatnormal element type is double

if ( typeid( OpenMesh::vector_traits::value_type)

!= typeid(double) )

{

std::cerr <<"Ouch!ERROR! Data type is wrong!\n";

return 1;

}

// Add vertexnormals as default property (ref. previous tutorial)

mesh.request_vertex_normals();

// Add facenormals as default property

mesh.request_face_normals();

// load a mesh

OpenMesh::IO::Optionsopt;

if ( ! OpenMesh::IO::read_mesh(mesh,argv[1],opt))

{

std::cerr <<"Errorloading mesh from file " << argv[1] << std::endl;

return 1;

}

// If the filedid not provide vertex normals, then calculate them

if ( !opt.check( OpenMesh::IO::Options::VertexNormal) &&

mesh.has_face_normals()&& mesh.has_vertex_normals() )

{

// let the meshupdate the normals

mesh.update_normals();

}

// move allvertices one unit length along it's normal direction

for(MyMesh::VertexIter v_it = mesh.vertices_begin();

v_it !=mesh.vertices_end(); ++v_it)

{

std::cout <<"Vertex#"<< *v_it << ": " << mesh.point( *v_it );

mesh.set_point(*v_it, mesh.point(*v_it)+mesh.normal(*v_it) );

std::cout <<" moved to"<< mesh.point( *v_it ) << std::endl;

}

return 0;

}

 

你可能感兴趣的:(OpenMesh)