OMToolkit 1.0 The polygonal mesh processing tool.

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
OMGeometry.hxx
Go to the documentation of this file.
1 //==============================================================================
14 #ifndef _OM_GEOMETRY_HXX_
15 #define _OM_GEOMETRY_HXX_
16
18 // Constructor - creates an instance of Geometry from an OpenMesh mesh
19 // @param mesh OpenMesh mesh to be converted
20 // @param binding Specifies additional attributes for mesh generation normal binding and color binding. If there is no normal in Mesh, they will be computed
21 // @param defaultColor Specifies default color which will be added, if there is no color attribute in Mesh
22 // @see AttributeBinding
24 template <class Mesh>
25 OMGeometry<Mesh>::OMGeometry(Mesh mesh, AttributeBinding binding, Vec4 &defaultColor) : Geometry()
26 {
27 OpenMesh::Utils::Timer timer;
28 timer.reset();
29 timer.start();
30 using namespace OMToolkit;
31
32 // try to load vertices
33 if (LoadVertices(mesh))
34 {
35 MDS_LOG_NOTE("Vertices successfully loaded into OSG...");
36 }
37 else
38 {
39 MDS_LOG_NOTE("Problem with copying vertices into OSG, aborting...");
40 loaded_done = false;
41 timer.stop();
42 return;
43 }
44
45 // try to load faces
46 if (LoadFaces(mesh))
47 {
48 MDS_LOG_NOTE("Faces successfully loaded into OSG...");
49 }
50 else
51 {
52 MDS_LOG_NOTE("Problem with copying faces into OSG, aborting...");
53 loaded_done = false;
54 timer.stop();
55 return;
56 }
57
58 // test attributes and load normals
59 if (!(binding & NORMAL_NONE))
60 {
61 if (binding & NORMAL_PER_FACE)
62 if (LoadNormals(mesh, Geometry::BIND_PER_PRIMITIVE))
63 {
64 MDS_LOG_NOTE("Normals successfully loaded into OSG, bound per face...");
65 }
66 else
67 {
68 MDS_LOG_NOTE("Normals bound per face failed to load, aborting...");
69 loaded_done = false;
70 timer.stop();
71 return;
72 }
73 if (binding & NORMAL_PER_VERTEX)
74 if (LoadNormals(mesh, Geometry::BIND_PER_VERTEX))
75 {
76 MDS_LOG_NOTE("Normals successfully loaded into OSG, bound per vertex...");
77 }
78 else
79 {
80 MDS_LOG_NOTE("Normals bound per vertex failed to load, aborting...");
81 loaded_done = false;
82 timer.stop();
83 return;
84 }
85 }
86
87 // test attributes and load colors
88 if (!(binding & COLOR_NONE))
89 {
90 if (binding & COLOR_PER_VERTEX)
91 if (LoadColor(mesh, defaultColor, Geometry::BIND_PER_VERTEX))
92 {
93 MDS_LOG_NOTE("Colors successfully loaded into OSG, bound per vertex...");
94 }
95 else
96 {
97 MDS_LOG_NOTE("Colors bound per vertex failed to load, aborting...");
98 loaded_done = false;
99 timer.stop();
100 return;
101 }
102 if (binding & COLOR_PER_FACE)
103 if (LoadColor(mesh, defaultColor, Geometry::BIND_PER_PRIMITIVE))
104 {
105 MDS_LOG_NOTE("Colors successfully loaded into OSG, bound per face...");
106 }
107 else
108 {
109 MDS_LOG_NOTE("Colors bound per face failed to load, aborting...");
110 loaded_done = false;
111 timer.stop();
112 return;
113 }
114 }
115 timer.stop();
116 MDS_LOG_NOTE("Loading done in: " << timer.as_string(OpenMesh::Utils::Timer::MSeconds));
117 loaded_done = true;
118 }
119
121 // Allows testing if geometry was successfully loaded
122 // @return True, if all the model was loaded successfully.
124 template <class Mesh>
125 bool OMGeometry<Mesh>::isLoadedOk()
126 {
127 return loaded_done;
128 }
129
131 // Loads vertices into osg from OpenMesh
132 // @param mesh Structure with a mesh to be loaded
133 // return True if there was no problem with adding all the vertices.
135 template <class Mesh>
136 bool OMGeometry<Mesh>::LoadVertices(Mesh mesh)
137 {
138 // create auxiliary variables
139 ref_ptr<Vec3Array> vertices = new osg::Vec3Array;
140 OpenMesh::IO::ExporterT<Mesh> exporter(mesh);
141 Mesh::VertexIter vertexIt;
142 Mesh::VertexIter vertexEnd = mesh.vertices_end();
143 OpenMesh::Vec3f vertex;
144
145 // pass all vertices of mesh and add them into osg
146 for (vertexIt = mesh.vertices_begin(); vertexIt != vertexEnd; ++vertexIt)
147 {
148 OpenMesh::Vec3f vertex = exporter.point(vertexIt);
149 vertices->push_back(Vec3( vertex[0],
150 vertex[1],
151 vertex[2]));
152 }
153
154 // test if numbers correspond
155 if (vertices->size() != mesh.n_vertices()) return false;
156 setVertexArray(vertices);
157 return true;
158 }
159
161 // Loads faces into osg from OpenMesh
162 // @param mesh Structure with a mesh to be loaded
163 // return True if there was no problem with adding all the faces.
165 template <class Mesh>
166 bool OMGeometry<Mesh>::LoadFaces(Mesh mesh)
167 {
168 // auxiliary variables
169 ref_ptr<DrawElementsUInt> face;
170 OpenMesh::IO::ExporterT<Mesh> exporter(mesh);
171 Mesh::FaceIter faceIt;
172 Mesh::FaceIter faceEnd = mesh.faces_end();
173
174 // if a mesh is pure triangle mesh, we will be adding only triangles
175 if (exporter.is_triangle_mesh())
176 {
177 face = new DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
178 std::vector<Mesh::VertexHandle> faceVertices(3);
179
180 // pass all faces and add them into osg
181 for (faceIt = mesh.faces_begin(); faceIt != faceEnd; ++faceIt)
182 {
183 exporter.get_vhandles(faceIt, faceVertices);
184 face->push_back(faceVertices[0].idx());
185 face->push_back(faceVertices[1].idx());
186 face->push_back(faceVertices[2].idx());
187 }
188 if (face->size() != mesh.n_faces()*3) return false;
189 addPrimitiveSet(face);
190 }
191
192 // if a mesh is a polygonal mesh, we must check each face
193 else
194 {
195 std::vector<Mesh::VertexHandle> faceVertices;
196 std::vector<Mesh::VertexHandle>::iterator it, end;
197
198 // pass all faces
199 for (faceIt = mesh.faces_begin(); faceIt != faceEnd; ++faceIt)
200 {
201 face = new DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0);
202 exporter.get_vhandles(faceIt, faceVertices);
203 end = faceVertices.end();
204 // pass each vertex and add them into osg
205 for (it = faceVertices.begin(); it != end; ++it)
206 {
207 face->push_back(it->idx());
208 }
209
210 addPrimitiveSet(face);
211 }
212 if (getPrimitiveSetList().size() != mesh.n_faces()) return false;
213 }
214
215 return true;
216 }
217
219 // Loads and associes colors into osg from OpenMesh
220 // @param mesh Structure with a mesh to be loaded
221 // @param defaultColor If there is no color in OpenMesh, this color will be associated to every vertex/face
222 // @param binding OSG color binding.
223 // @see AttributeBinding
224 // @return True if there was no problem with adding all the colors.
226 template <class Mesh>
227 bool OMGeometry<Mesh>::LoadColor(Mesh mesh, osg::Vec4 &defaultColor = osg::Vec4(1.0, 1.0, 1.0, 1.0), Geometry::AttributeBinding binding = Geometry::BIND_PER_VERTEX)
228 {
229 // create auxiliary variables
230 OpenMesh::IO::ExporterT<Mesh> exporter(mesh);
231 ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
232 OpenMesh::Vec4uc color;
233 OpenMesh::Vec4uc zeros(1,0,0,255);
234
235 // check attributes and do what is asked
236 if (binding == Geometry::BIND_PER_VERTEX)
237 {
238 // if there is no colors, go default
239 if (!exporter.has_vertex_colors())
240 {
241 colors->resize(exporter.n_vertices(), defaultColor);
242 }
243 else
244 {
245 // else pass all vertices
246 Mesh::VertexIter vertex;
247 Mesh::VertexIter end = mesh.vertices_end();
248
249 /*bool hasColors = false;
250 for (vertex = mesh.vertices_begin(); vertex != end; ++vertex)
251 {
252 color = exporter.colorA(vertex);
253 if (color != zeros)
254 {
255 hasColors = true;
256 break;
257 }
258 }
259
260 if (hasColors)*/
261 for (vertex = mesh.vertices_begin(); vertex != end; ++vertex)
262 {
263 color = exporter.colorA(vertex);
264 colors->push_back(Vec4( (float)color[0]/255.0f,
265 (float)color[1]/255.0f,
266 (float)color[2]/255.0f,
267 (float)color[3]/255.0f));
268 /*std::cout << colors->back()[0] << " " <<
269 colors->back()[1] << " " <<
270 colors->back()[2] << " " <<
271 colors->back()[3] << std::endl;*/
272 }
273 //else colors->resize(exporter.n_vertices(), defaultColor);
274
275
276 if (colors->size() != mesh.n_vertices()) return false;
277 }
278 }
279 else if (binding == Geometry::BIND_PER_PRIMITIVE)
280 {
281 // if there is no face colors
282 if (!exporter.has_face_colors())
283 {
284 colors->resize(exporter.n_vertices(), defaultColor);
285 }
286 // pass all faces
287 else
288 {
289 Mesh::FaceIter face;
290 Mesh::FaceIter end = mesh.faces_end();
291
292 /*bool hasColors = false;
293 for (face = mesh.faces_begin(); face != end; ++face)
294 {
295 color = exporter.colorA(face);
296 if (color != zeros)
297 {
298 hasColors = true;
299 break;
300 }
301 }
302
303 if (hasColors)*/
304 for (face = mesh.faces_begin(); face != end; ++face)
305 {
306 color = exporter.colorA(face);
307 colors->push_back(Vec4( (float)color[0]/255.0f,
308 (float)color[1]/255.0f,
309 (float)color[2]/255.0f,
310 (float)color[3]/255.0f));
311 }
312 //else colors->resize(exporter.n_faces(), defaultColor);
313
314 if (colors->size() != mesh.n_faces()) return false;
315 }
316 }
317 else return false;
318
319 // finally, add this array
320 setColorArray(colors);
321 setColorBinding(binding);
322 return true;
323 }
324
326 // Loads and associes normals into osg from OpenMesh (if there is no normals, they will be computed)
327 // @param mesh Structure with a mesh to be loaded
328 // @param binding OSG normal binding.
329 // @see AttributeBinding
330 // @return True if there was no problem with adding all the normals.
332 template <class Mesh>
333 bool OMGeometry<Mesh>::LoadNormals(Mesh mesh, Geometry::AttributeBinding binding = Geometry::BIND_PER_PRIMITIVE)
334 {
335 // load auxiliary variables
336 OpenMesh::IO::ExporterT<Mesh> exporter(mesh);
337 ref_ptr<Vec3Array> normals = new Vec3Array();
338
339 // select binding options
340 if (binding == Geometry::BIND_PER_PRIMITIVE)
341 {
342 Mesh::FaceIter face;
343 Mesh::FaceIter end = mesh.faces_end();
344 OpenMesh::Vec3f normal;
345
346 // if there is no normals, we must compute them
347 if (!exporter.has_face_normals())
348 {
349 mesh.request_face_normals();
350 for (face = mesh.faces_begin(); face != end; ++face)
351 {
352 mesh.set_normal(face, mesh.calc_face_normal(face));
353 normal = exporter.normal(face);
354 normals->push_back(Vec3( normal[0],
355 normal[1],
356 normal[2]));
357 }
358 mesh.release_face_normals();
359 }
360 // if there are normals, we use them
361 else
362 {
363 for (face = mesh.faces_begin(); face != end; ++face)
364 {
365 normal = exporter.normal(face);
366 normals->push_back(Vec3( normal[0],
367 normal[1],
368 normal[2]));
369 }
370 }
371 }
372 // binding
373 else if (binding == Geometry::BIND_PER_VERTEX)
374 {
375 Mesh::VertexIter vertex;
376 Mesh::VertexIter end = mesh.vertices_end();
377 OpenMesh::Vec3f normal;
378
379 // if there is no vertex normals
380 if (!exporter.has_vertex_normals())
381 {
382 bool faceNormalsDelete = false;
383
384 // we must have face normals
385 if (!exporter.has_face_normals())
386 {
387 faceNormalsDelete = true;
388
389 mesh.request_face_normals();
390 Mesh::FaceIter face;
391 Mesh::FaceIter end = mesh.faces_end();
392 for (face = mesh.faces_begin(); face != end; ++face)
393 {
394 mesh.set_normal(face, mesh.calc_face_normal(face));
395 }
396 }
397 // then, we compute missing vertex normals
398 mesh.request_vertex_normals();
399 for (vertex = mesh.vertices_begin(); vertex != end; ++vertex)
400 {
401 mesh.set_normal(vertex, mesh.calc_vertex_normal(vertex));
402 normal = exporter.normal(vertex);
403 normals->push_back(Vec3( normal[0],
404 normal[1],
405 normal[2]));
406 }
407
408 // release all aux
409 mesh.release_vertex_normals();
410 if (faceNormalsDelete) mesh.release_face_normals();
411 }
412 // if we already have vertex normals
413 else
414 {
415 for (vertex = mesh.vertices_begin(); vertex != end; ++vertex)
416 {
417 normal = exporter.normal(vertex);
418 normals->push_back(Vec3( normal[0],
419 normal[1],
420 normal[2]));
421 }
422 }
423 }
424
425 // if binding is invalid, return false
426 else return false;
427
428 setNormalArray(normals);
429 setNormalBinding(binding);
430
431 return true;
432 }
433
434 #endif