The following table lists all available standard properties and the suitable entity for which it can be used.
Vertex | Face | Edge | Halfedge | |
Color | X | X | ||
Normal | X | X | ||
Position(*) | X | |||
Status | X | X | X | X |
TexCoord | X |
To add a standard property to an entity simply use the appropriate request method, e.g. request_face_normal()
. The only exception is the position (*). It cannot be added because it is permanently available, hence it cannot be remove as well.
In this example we
mesh.request_vertex_normals();
mesh.request_face_normals();
update_normals()
, if the file didn't provide any.
But we can do more with standard properties. We can verify if the mesh has already the property vertex normals
if (!mesh.has_vertex_normals()) { std::cerr << "ERROR: Standard vertex property 'Normals' not available!\n"; return 1; }
mesh.release_vertex_normals();
Now we know how to add and remove standard properties, but how do we access them? Again we need the mesh object. Unlike the custom properties, where we accessed one with the mesh member function property()
, for each standard property the mesh provides a get and a set method. We have used one pair of get/set methods already in the previous three tutorials, where we computed a new location for the vertex position. Here we move all vertices a unit length along their normal direction:
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) );
}
mesh.texcoord(
_face_handle ) will result in an error when compiling the code.
Since we know how to add/remove/access standard properties, one further question remains. What data types do they have? And are there more hidden secrets? The next tutorial (Using mesh traits and attributes) will give the answer.
The complete source looks like this:
#include <iostream> // -------------------- #include <OpenMesh/Core/IO/MeshIO.hh> #include <OpenMesh/Core/Mesh/Types/TriMesh_ArrayKernelT.hh> typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh; int main(int argc, char **argv) { MyMesh mesh; if (argc!=2) { std::cerr << "Usage: properties <input>\n"; return 1; } // request vertex normals, so the mesh reader 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::Options opt; if ( ! OpenMesh::IO::read_mesh(mesh,argv[1], opt)) { std::cerr << "Error loading mesh from file " << argv[1] << std::endl; return 1; } // If the file did not provide vertex normals, then calculate them if ( !opt.check( OpenMesh::IO::Options::VertexNormal ) ) { // we need face normals to update the vertex normals mesh.request_face_normals(); // let the mesh update the normals mesh.update_normals(); // dispose the face normals, as we don't need them anymore mesh.release_face_normals(); } // move all vertices 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; } // don't need the normals anymore? Remove them! 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; }