Developer Documentation
OFFImporter.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 
44 #include "OFFImporter.hh"
45 
46 //-----------------------------------------------------------------------------
47 
50 
51 }
52 
53 //-----------------------------------------------------------------------------
54 
57 polyMesh_(0),
58 triMesh_(0),
59 object_(0),
60 objectOptions_(0),
61 maxFaceValence_(0) {}
62 
63 //-----------------------------------------------------------------------------
64 
67 
68  PolyMeshObject* polyMeshObj = dynamic_cast< PolyMeshObject* > (_object);
69  TriMeshObject* triMeshObj = dynamic_cast< TriMeshObject* > (_object);
70 
71  if ( polyMeshObj ){
72 
73  polyMesh_ = polyMeshObj->mesh();
74  object_ = _object;
75  objectOptions_ |= POLYMESH;
76  objectOptions_ &= ~TRIMESH;
77 
78  } else if ( triMeshObj ){
79 
80  triMesh_ = triMeshObj->mesh();
81  object_ = _object;
82  objectOptions_ |= TRIMESH;
83  objectOptions_ &= ~POLYMESH;
84 
85  } else {
86  std::cerr << "Error: Cannot add object. Type is unknown!" << std::endl;
87  }
88 }
89 
90 //-----------------------------------------------------------------------------
91 
94 
95  if ( vertices_.size() > _index )
96  return vertices_[ _index ];
97  else
98  return Vec3f();
99 }
100 
101 //-----------------------------------------------------------------------------
102 
104 int OFFImporter::addTexCoord(const Vec2f& _coord){
105  texCoords_.push_back( _coord );
106 
107  return texCoords_.size()-1;
108 }
109 
110 //-----------------------------------------------------------------------------
111 
113 int OFFImporter::addNormal(const Vec3f& _normal){
114  normals_.push_back( _normal );
115 
116  return normals_.size()-1;
117 }
118 
119 //-----------------------------------------------------------------------------
120 
122 int OFFImporter::addColor(const Vec4f& _color) {
123  colors_.push_back( _color );
124 
125  return colors_.size()-1;
126 }
127 
128 //-----------------------------------------------------------------------------
129 
132  if (polyMesh_ == 0)
133  return 0;
134  else
135  return polyMesh_;
136 }
137 
138 //-----------------------------------------------------------------------------
139 
142  if (triMesh_ == 0)
143  return 0;
144  else
145  return triMesh_;
146 }
147 
148 //-----------------------------------------------------------------------------
149 
151 void OFFImporter::setVertexTexCoord(VertexHandle _vh, int _texCoordID){
152 
153  if ( isTriangleMesh() ){
154 
155  //handle triangle meshes
156  if ( !triMesh() ) return;
157 
158  if ( _texCoordID < (int) texCoords_.size() ){
159 
160  //perhaps request texCoords for the mesh
161  if ( !triMesh()->has_vertex_texcoords2D() )
162  triMesh()->request_vertex_texcoords2D();
163 
164  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() )
165  triMesh()->set_texcoord2D( vertexMapTri_[_vh], texCoords_[ _texCoordID ] );
166  objectOptions_ |= VERTEXTEXCOORDS;
167 
168  }else{
169  std::cerr << "Error: TexCoord ID too large" << std::endl;
170  }
171 
172  } else if ( isPolyMesh() ){
173 
174  //handle poly meshes
175  if ( !polyMesh() ) return;
176 
177  if ( _texCoordID < (int) texCoords_.size() ){
178 
179  //perhaps request texCoords for the mesh
180  if ( !polyMesh()->has_vertex_texcoords2D() )
181  polyMesh()->request_vertex_texcoords2D();
182 
183  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() )
184  polyMesh()->set_texcoord2D( vertexMapPoly_[_vh], texCoords_[ _texCoordID ] );
185  objectOptions_ |= VERTEXTEXCOORDS;
186 
187  }else{
188  std::cerr << "Error: TexCoord ID too large" << std::endl;
189  }
190  }
191 }
192 
193 //-----------------------------------------------------------------------------
194 
196 void OFFImporter::setNormal(VertexHandle _vh, int _normalID){
197 
198  if ( isTriangleMesh() ){
199 
200  //handle triangle meshes
201  if ( !triMesh() ) return;
202 
203  if ( _normalID < (int) normals_.size() ){
204 
205  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() ){
206  triMesh()->set_normal( vertexMapTri_[_vh], (TriMesh::Point) normals_[ _normalID ] );
207  objectOptions_ |= VERTEXNORMAL;
208  }
209 
210  }else{
211  std::cerr << "Error: normal ID too large" << std::endl;
212  }
213 
214  } else if ( isPolyMesh() ){
215 
216  //handle poly meshes
217  if ( !polyMesh() ) return;
218 
219  if ( _normalID < (int) normals_.size() ){
220 
221  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() ){
222  polyMesh()->set_normal( vertexMapPoly_[_vh], (PolyMesh::Point) normals_[ _normalID ] );
223  objectOptions_ |= VERTEXNORMAL;
224  }
225 
226  }else{
227  std::cerr << "Error: normal ID too large" << std::endl;
228  }
229 
230  }
231 }
232 
233 //-----------------------------------------------------------------------------
234 
236 VertexHandle OFFImporter::addVertex(const Vec3f& _point){
237 
238  vertices_.push_back( _point );
239 
240  int id = vertices_.size()-1;
241 
242  if ( isTriangleMesh() ){
243 
244  //handle triangle meshes
245  if ( !triMesh() ) return false;
246  vertexMapTri_[ id ] = triMesh()->add_vertex( (TriMesh::Point) vertices_[id] );
247 
248  } else if ( isPolyMesh() ){
249 
250  //handle poly meshes
251  if ( !polyMesh() ) return false;
252  vertexMapPoly_[ id ] = polyMesh()->add_vertex( (PolyMesh::Point) vertices_[id] );
253  }
254 
255  return id;
256 }
257 
258 //-----------------------------------------------------------------------------
259 
261 int OFFImporter::addFace(const VHandles& _indices) {
262 
263  int faceIndex = -1;
264 
265  if ( isTriangleMesh() ){
266 
267  //handle triangle meshes
268  if ( !triMesh() ) return -1;
269 
270  std::vector< TriMesh::VertexHandle > vertices;
271 
272  for (uint i=0; i < _indices.size(); i++){
273 
274  if ( vertexMapTri_.find( _indices[i] ) != vertexMapTri_.end() ){
275 
276  vertices.push_back( vertexMapTri_[ _indices[i] ] );
277 
278  } else {
279  std::cerr << "Error: Cannot add face. Undefined index (" << _indices[i] << ")" << std::endl;
280  return -1;
281  }
282  }
283 
284  TriMesh::FaceHandle fh = triMesh()->add_face( vertices );
285 
286  if(fh.is_valid()) {
287  faceMapTri_.push_back( fh );
288  faceIndex = faceMapTri_.size()-1;
289  } else {
290  // Store non-manifold face
291  invalidFaces_.push_back( vertices );
292  }
293 
294  } else if ( isPolyMesh() ){
295 
296  //handle poly meshes
297  if ( !polyMesh() ) return -1;
298 
299  std::vector< PolyMesh::VertexHandle > vertices;
300 
301  for (uint i=0; i < _indices.size(); i++){
302 
303  if ( vertexMapPoly_.find( _indices[i] ) != vertexMapPoly_.end() ){
304 
305  vertices.push_back( vertexMapPoly_[ _indices[i] ] );
306 
307  }else{
308  std::cerr << "Error: Cannot add face. Undefined index (" << _indices[i] << ")" << std::endl;
309  return -1;
310  }
311  }
312 
313  PolyMesh::FaceHandle fh = polyMesh()->add_face( vertices );
314 
315  if(fh.is_valid()) {
316  faceMapPoly_.push_back(fh);
317  faceIndex = faceMapPoly_.size()-1;
318  } else {
319  // Store non-manifold face vertices
320  invalidFaces_.push_back( vertices );
321  }
322  }
323 
324  return faceIndex;
325 }
326 
327 //-----------------------------------------------------------------------------
328 
330 
331  if(invalidFaces_.empty()) return;
332 
333  if ( isTriangleMesh() ) {
334 
335  for(std::vector<OMVHandles>::iterator it = invalidFaces_.begin();
336  it != invalidFaces_.end(); ++it) {
337 
338  OMVHandles& vhandles = *it;
339 
340  // double vertices
341  for (unsigned int j = 0; j < vhandles.size(); ++j)
342  {
343  TriMesh::Point p = triMesh()->point(vhandles[j]);
344  vhandles[j] = triMesh()->add_vertex(p);
345  // DO STORE p, reference may not work since vertex array
346  // may be relocated after adding a new vertex !
347 
348  // Mark vertices of failed face as non-manifold
349  if (triMesh()->has_vertex_status()) {
350  triMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
351  }
352  }
353 
354  // add face
355  OpenMesh::FaceHandle fh = triMesh()->add_face(vhandles);
356 
357  // Mark failed face as non-manifold
358  if (triMesh()->has_face_status())
359  triMesh()->status(fh).set_fixed_nonmanifold(true);
360 
361  // Mark edges of failed face as non-two-manifold
362  if (triMesh()->has_edge_status()) {
363  TriMesh::FaceEdgeIter fe_it = triMesh()->fe_iter(fh);
364  for(; fe_it.is_valid(); ++fe_it) {
365  triMesh()->status(*fe_it).set_fixed_nonmanifold(true);
366  }
367  }
368 
369  faceMapTri_.push_back(fh);
370  }
371 
372  } else if ( isPolyMesh() ) {
373 
374  for(std::vector<OMVHandles>::iterator it = invalidFaces_.begin();
375  it != invalidFaces_.end(); ++it) {
376 
377  OMVHandles& vhandles = *it;
378 
379  // double vertices
380  for (unsigned int j = 0; j < vhandles.size(); ++j)
381  {
382  TriMesh::Point p = polyMesh()->point(vhandles[j]);
383  vhandles[j] = polyMesh()->add_vertex(p);
384  // DO STORE p, reference may not work since vertex array
385  // may be relocated after adding a new vertex !
386 
387  // Mark vertices of failed face as non-manifold
388  if (polyMesh()->has_vertex_status()) {
389  polyMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
390  }
391  }
392 
393  // add face
394  OpenMesh::FaceHandle fh = polyMesh()->add_face(vhandles);
395 
396  // Mark failed face as non-manifold
397  if (polyMesh()->has_face_status())
398  polyMesh()->status(fh).set_fixed_nonmanifold(true);
399 
400  // Mark edges of failed face as non-two-manifold
401  if (polyMesh()->has_edge_status()) {
402  TriMesh::FaceEdgeIter fe_it = polyMesh()->fe_iter(fh);
403  for(; fe_it.is_valid(); ++fe_it) {
404  polyMesh()->status(*fe_it).set_fixed_nonmanifold(true);
405  }
406  }
407 
408  faceMapPoly_.push_back(fh);
409  }
410  }
411 
412  // Clear all invalid faces
413  invalidFaces_.clear();
414 }
415 
416 //-----------------------------------------------------------------------------
417 
418 bool OFFImporter::isTriangleMesh(){
419  return objectOptions_ & TRIMESH;
420 }
421 
422 //-----------------------------------------------------------------------------
423 
424 bool OFFImporter::isPolyMesh(){
425  return objectOptions_ & POLYMESH;
426 }
427 
428 //-----------------------------------------------------------------------------
429 
430 bool OFFImporter::isBinary(){
431  return objectOptions_ & BINARY;
432 }
433 
434 //-----------------------------------------------------------------------------
435 
437 
438  return objectOptions_ & VERTEXNORMAL;
439 }
440 
441 //-----------------------------------------------------------------------------
442 
443 bool OFFImporter::hasTextureCoords(){
444  return objectOptions_ & VERTEXTEXCOORDS;
445 }
446 
447 //-----------------------------------------------------------------------------
448 
449 bool OFFImporter::hasVertexColors() {
450  return objectOptions_ & VERTEXCOLOR;
451 }
452 
453 //-----------------------------------------------------------------------------
454 
455 bool OFFImporter::hasFaceColors() {
456  return objectOptions_ & FACECOLOR;
457 }
458 
459 //-----------------------------------------------------------------------------
460 
461 bool OFFImporter::hasOption(ObjectOptionsE _option) {
462  return objectOptions_ & _option;
463 }
464 
465 //-----------------------------------------------------------------------------
466 
468  return vertices_.size();
469 }
470 
471 //-----------------------------------------------------------------------------
472 
473 uint OFFImporter::n_normals(){
474  return normals_.size();
475 }
476 
477 //-----------------------------------------------------------------------------
478 
479 uint OFFImporter::n_texCoords(){
480  return texCoords_.size();
481 }
482 
483 //-----------------------------------------------------------------------------
484 
485 void OFFImporter::reserve(unsigned int _nv, unsigned int _ne, unsigned int _nf) {
486 
487  vertices_.reserve(_nv);
488  normals_.reserve(_nv);
489  texCoords_.reserve(_nv);
490  colors_.reserve(_nv);
491 
492  if(isPolyMesh() && polyMesh_ != 0) {
493  polyMesh_->reserve(_nv, _ne, _nf);
494  }
495 
496  if(isTriangleMesh() && triMesh_ != 0) {
497  triMesh_->reserve(_nv, _ne, _nf);
498  }
499 }
500 
501 //-----------------------------------------------------------------------------
502 
504 
505  return object_;
506 }
507 
508 //-----------------------------------------------------------------------------
509 
511  return path_;
512 }
513 
514 //-----------------------------------------------------------------------------
515 
516 void OFFImporter::setPath(QString _path){
517  path_ = _path;
518 }
519 
520 //-----------------------------------------------------------------------------
521 
522 void OFFImporter::setObjectOptions(ObjectOptions _options){
523  objectOptions_ = _options;
524 }
525 
526 //-----------------------------------------------------------------------------
527 
528 void OFFImporter::addOption(ObjectOptionsE _option) {
529  objectOptions_ |= _option;
530 }
531 
532 //-----------------------------------------------------------------------------
533 
534 void OFFImporter::removeOption(ObjectOptionsE _option) {
535  if(objectOptions_ & _option) objectOptions_ -= _option;
536 }
537 
538 //-----------------------------------------------------------------------------
539 
540 OFFImporter::ObjectOptions& OFFImporter::objectOptions(){
541  return objectOptions_;
542 }
543 
544 //-----------------------------------------------------------------------------
545 
546 void OFFImporter::setObjectName(QString _name){
547 
548  if ( object_ != 0 )
549  object_->setName( _name );
550 }
551 
552 //------------------------------------------------------------------------------
553 
555 void OFFImporter::setVertexColor(VertexHandle _vh, int _colorIndex) {
556 
557  if ( isTriangleMesh() ){
558 
559  //handle triangle meshes
560  if ( !triMesh() ) return;
561 
562  if ( _colorIndex < (int) colors_.size() ){
563 
564  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() ){
565  triMesh()->set_color( vertexMapTri_[_vh], colors_[_colorIndex] );
566  objectOptions_ |= VERTEXCOLOR;
567  }
568 
569  }else{
570  std::cerr << "Error: Color ID too large" << std::endl;
571  }
572 
573  } else if ( isPolyMesh() ){
574 
575  //handle poly meshes
576  if ( !polyMesh() ) return;
577 
578  if ( _colorIndex < (int) colors_.size() ){
579 
580  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() ){
581  polyMesh()->set_color( vertexMapPoly_[_vh], colors_[_colorIndex] );
582  objectOptions_ |= VERTEXCOLOR;
583  }
584 
585  }else{
586  std::cerr << "Error: Color ID too large" << std::endl;
587  }
588 
589  }
590 }
591 
592 //------------------------------------------------------------------------------
593 
595 void OFFImporter::setFaceColor(FaceHandle _fh, int _colorIndex) {
596 
597  if ( isTriangleMesh() ){
598 
599  //handle triangle meshes
600  if ( !triMesh() ) return;
601 
602  if ( _colorIndex < (int) colors_.size() ){
603 
604  if ( _fh < (int)faceMapTri_.size() ) {
605  triMesh()->set_color( faceMapTri_[_fh],colors_[_colorIndex] );
606  objectOptions_ |= FACECOLOR;
607  }
608 
609  }else{
610  std::cerr << "Error: Color ID too large" << std::endl;
611  }
612 
613  } else if ( isPolyMesh() ){
614 
615  //handle poly meshes
616  if ( !polyMesh() ) return;
617 
618  if ( _colorIndex < (int) colors_.size() ){
619 
620  if ( _fh < (int)faceMapPoly_.size() ) {
621  polyMesh()->set_color( faceMapPoly_[_fh], colors_[_colorIndex] );
622  objectOptions_ |= FACECOLOR;
623  }
624 
625  }else{
626  std::cerr << "Error: Color ID too large" << std::endl;
627  }
628 
629  }
630 }
Handle for a face entity.
Definition: Handles.hh:141
void removeOption(ObjectOptionsE _option)
remove an option
Definition: OFFImporter.cc:534
Vec3f vertex(uint _index)
get vertex with given index
Definition: OFFImporter.cc:93
Kernel::FaceEdgeIter FaceEdgeIter
Circulator.
Definition: PolyMeshT.hh:169
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
void setObjectOptions(ObjectOptions _options)
Definition: OFFImporter.cc:522
ObjectOptions & objectOptions()
get Object Options
Definition: OFFImporter.cc:540
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
BaseObject * getObject()
get BaseObject data of object
Definition: OFFImporter.cc:503
void finish()
Definition: OFFImporter.cc:329
PolyMesh * polyMesh()
get a pointer to the active polyMesh
Definition: OFFImporter.cc:131
void setNormal(VertexHandle _vh, int _normalID)
set vertex normal
Definition: OFFImporter.cc:196
void setVertexColor(VertexHandle _vh, int _colorIndex)
set vertex color
Definition: OFFImporter.cc:555
MeshT * mesh()
return a pointer to the mesh
bool hasVertexNormals()
Query Object Options.
Definition: OFFImporter.cc:436
bool hasOption(ObjectOptionsE _option)
test if object has a certain option
Definition: OFFImporter.cc:461
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
Definition: OFFImporter.cc:151
void setObjectName(QString _name)
change the name of an object
Definition: OFFImporter.cc:546
int addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
Definition: OFFImporter.cc:261
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:723
void addObject(BaseObject *_object)
add initial object
Definition: OFFImporter.cc:66
void addOption(ObjectOptionsE _option)
add an option
Definition: OFFImporter.cc:528
OFFImporter()
constructor
Definition: OFFImporter.cc:56
int addNormal(const Vec3f &_normal)
add a normal
Definition: OFFImporter.cc:113
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
VertexHandle addVertex(const Vec3f &_point)
add a vertex with coordinate _point
Definition: OFFImporter.cc:236
~OFFImporter()
base class needs virtual destructor
Definition: OFFImporter.cc:49
int addColor(const Vec4f &_color)
add a color
Definition: OFFImporter.cc:122
int addTexCoord(const Vec2f &_coord)
add texture coordinates
Definition: OFFImporter.cc:104
QString path()
Path of the OFF file.
Definition: OFFImporter.cc:510
TriMesh * triMesh()
get a pointer to the active triMesh
Definition: OFFImporter.cc:141
void setFaceColor(FaceHandle _fh, int _colorIndex)
set face color
Definition: OFFImporter.cc:595
uint n_vertices()
Global Properties.
Definition: OFFImporter.cc:467