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

使用标准属性

本例主要说明以下问题:

1.如何添加和移除标准属性

2.如何获取和设置标准属性值

前面我们已经知道,我们可以绑定额外的数据实体到mesh上,作为mesh的属性。OpenMesh提供一系列所谓标准属性。与自定义属性不同,这些属性拥有特殊的特性和不同的接口,这正是本文关注的事情。

下表列出了可用的标准属性及其适用对象(节点、面、边、半边等)。

 

Vertex

Face

Edge

Halfedge

Color

X

X

X

 

Normal

X

X

 

X

Position (*)

X

 

 

 

Status

X

X

X

X

TexCoord

X

 

 

X

给实体添加标准属性,可简单地通过查询方法,例如:request_face_normals()。唯一的例外是位置属性,它不能被添加,因为这个属性应当是始终存在的,根本不能被移除。

本例中,我们:

1.mesh对象添加节点法线属性

2.加载文件

3.检查文件数据是否提供了节点法线数据,如果未提供则计算法线。

4.将每个节点沿着法线方向移动一个单位长度

5.通过std::cout方法将最终位置输出

现在,我们开始为mesh添加节点法线属性。

mesh.request_vertex_normals();

用类似的方法,我们可以查询其他标准属性,如面法线属性:

 

mesh.request_face_normals();

if (!mesh.has_vertex_normals())

{

std::cerr << "ERROR:Standard vertex property 'Normals' not available!\n";

return 1;

}

如果文件数据中未包含法线数据,我们可以利用update_normals()函数计算。

但是,即使文件提供了法线数据,我们也可以利用标准属性做更多的事情,比如,修改它,也可以在用完后移除它。

mesh.release_vertex_normals();

但是,上面的代码运行后,发生了什么呢?当再次查询法线属性后就会发现,其实什么都没做,法线属性依然存在。但第二次移除后就会真的移除掉。标准属性拥有一个引用计数器,用于保存法线被引用的次数,每次引用它,都会被递增,而移除时则会被递减。如果引用计数器递减为0,则属性会被真正从内存中移除。

从上表看到,有9个动态可查询属性(9个?可能不包括status?)。查询函数定义在OpenMesh::Concepts::KernelT中,包括:

·       request_edge_status()

·       request_edge_colors()

·       request_face_colors()

·       request_face_normals()

·       request_face_status()

·       request_face_texture_index()

·       request_halfedge_status()

·       request_halfedge_normals()

·       request_halfedge_texcoords1D()

·       request_halfedge_texcoords2D()

·       request_halfedge_texcoords3D()

·       request_vertex_colors()

·       request_vertex_normals()

·       request_vertex_status()

·       request_vertex_texcoords1D()

·       request_vertex_texcoords2D()

·       request_vertex_texcoords3D()

已添加的属性可通过下列函数移除:

·       release_edge_status()

·       release_edge_colors()

·       release_face_colors()

·       release_face_normals()

·       release_face_status()

·       release_face_texture_index()

·       release_halfedge_status()

·       release_halfedge_normals()

·       release_halfedge_texcoords1D()

·       release_halfedge_texcoords2D()

·       release_halfedge_texcoords3D()

·       release_vertex_colors()

·       release_vertex_normals()

·       release_vertex_status()

·       release_vertex_texcoords1D()

·       release_vertex_texcoords2D()

·       release_vertex_texcoords3D()

属性的存在性可通过下列函数测试:

(译者注:区别于request,这是测试是否有数据,request是查询是否有属性)

·       has_edge_status()

·       has_edge_colors()

·       has_face_colors()

·       has_face_normals()

·       has_face_status()

·       has_face_texture_index()

·       has_halfedge_status()

·       has_halfedge_normals()

·       has_halfedge_texcoords1D()

·       has_halfedge_texcoords2D()

·       has_halfedge_texcoords3D()

·       has_vertex_colors()

·       has_vertex_normals()

·       has_vertex_status()

·       has_vertex_texcoords1D()

·       has_vertex_texcoords2D()

·       has_vertex_texcoords3D()

当属性查询(译者注:request_)可用时,上述函数(译者注:has_)返回true表示属性数据存在。

状态(status)属性用于标记几何元素状态,如:选定、删除等,参考: Deletinggeometry elements 获取更多信息。

现在,我们知道了如何添加和移除标准属性,但是如何访问他们的数据呢?与自定义属性通过成员函数property()访问接口不同,每一个标准属性提供了getset函数。前面的例子中,我们已经使用针对节点位置属性的get/set函数对,读取了节点位置数据并计算更新了它。这里,我们要将所有的节点沿着其法线方向移动一个单位长度。

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

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

{

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

}

get函数需要实体句柄作为参数,返回该实体的这个属性值,set函数需要额外的参数,用于传递新属性值给指定的实体。按照表中给出的,并非所有实体都具有get/set函数对,例如,表面实体有法线属性,但是没有纹理坐标属性,所以,调用mesh.textcoord2D(_face_handle),将在编译时产生错误。

我们已经了解了如何添加和移除标准属性,但还有一个问题:属性中保存的数据是什么类型?它还有什么其他的隐藏的秘密?下一节(Using meshattributes and traits),我们给出问题答案。

完整代码如下:

#include <iostream>

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

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

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

typedef OpenMesh::TriMesh_ArrayKernelT<>MyMesh;

int main(int argc, char **argv)

{

MyMesh mesh;

if (argc!=2)

{

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

return 1;

}

// request vertex normals, so the meshreader can use normal information

// if available

mesh.request_vertex_normals();

// assure we have vertex normals

if (!mesh.has_vertex_normals())

{

std::cerr << "ERROR:Standard vertex property 'Normals' not available!\n";

return 1;

}

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 file did not provide vertexnormals, then calculate them

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

{

// we need face normals to update thevertex normals

mesh.request_face_normals();

// let the mesh update the normals

mesh.update_normals();

// dispose the face normals, as we don'tneed them anymore

mesh.release_face_normals();

}

// move all vertices one unit lengthalong 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;

}

// don't need the normals anymore? Removethem!

mesh.release_vertex_normals();

// just check if it really works

if (mesh.has_vertex_normals())

{

std::cerr << "Ouch!ERROR! Shouldn't have any vertex normals anymore!\n";

return 1;

}

return 0;

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值