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<iostream>

#include<typeinfo>

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

#include<OpenMesh/Core/IO/MeshIO.hh>

#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>

#include<OpenMesh/Core/Geometry/VectorT.hh>

#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_ArrayKernelT<MyTraits>MyMesh;

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

int main(int argc, char **argv)

{

MyMesh mesh;

if (argc!=2)

{

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

return 1;

}

// Just make surethat point element type is double

if ( typeid( OpenMesh::vector_traits<MyMesh::Point>::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<MyMesh::Normal>::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;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章