OMToolkit  1.0
The polygonal mesh processing tool.
 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>
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