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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "OFFImporter.hh"
51 
52 //-----------------------------------------------------------------------------
53 
56 
57 }
58 
59 //-----------------------------------------------------------------------------
60 
63 polyMesh_(0),
64 triMesh_(0),
65 object_(0),
66 objectOptions_(0),
67 maxFaceValence_(0) {}
68 
69 //-----------------------------------------------------------------------------
70 
73 
74  PolyMeshObject* polyMeshObj = dynamic_cast< PolyMeshObject* > (_object);
75  TriMeshObject* triMeshObj = dynamic_cast< TriMeshObject* > (_object);
76 
77  if ( polyMeshObj ){
78 
79  polyMesh_ = polyMeshObj->mesh();
80  object_ = _object;
81  objectOptions_ |= POLYMESH;
82  objectOptions_ &= ~TRIMESH;
83 
84  } else if ( triMeshObj ){
85 
86  triMesh_ = triMeshObj->mesh();
87  object_ = _object;
88  objectOptions_ |= TRIMESH;
89  objectOptions_ &= ~POLYMESH;
90 
91  } else {
92  std::cerr << "Error: Cannot add object. Type is unknown!" << std::endl;
93  }
94 }
95 
96 //-----------------------------------------------------------------------------
97 
100 
101  if ( vertices_.size() > _index )
102  return vertices_[ _index ];
103  else
104  return Vec3f();
105 }
106 
107 //-----------------------------------------------------------------------------
108 
110 int OFFImporter::addTexCoord(const Vec2f& _coord){
111  texCoords_.push_back( _coord );
112 
113  return texCoords_.size()-1;
114 }
115 
116 //-----------------------------------------------------------------------------
117 
119 int OFFImporter::addNormal(const Vec3f& _normal){
120  normals_.push_back( _normal );
121 
122  return normals_.size()-1;
123 }
124 
125 //-----------------------------------------------------------------------------
126 
128 int OFFImporter::addColor(const Vec4f& _color) {
129  colors_.push_back( _color );
130 
131  return colors_.size()-1;
132 }
133 
134 //-----------------------------------------------------------------------------
135 
138  if (polyMesh_ == 0)
139  return 0;
140  else
141  return polyMesh_;
142 }
143 
144 //-----------------------------------------------------------------------------
145 
148  if (triMesh_ == 0)
149  return 0;
150  else
151  return triMesh_;
152 }
153 
154 //-----------------------------------------------------------------------------
155 
157 void OFFImporter::setVertexTexCoord(VertexHandle _vh, int _texCoordID){
158 
159  if ( isTriangleMesh() ){
160 
161  //handle triangle meshes
162  if ( !triMesh() ) return;
163 
164  if ( _texCoordID < (int) texCoords_.size() ){
165 
166  //perhaps request texCoords for the mesh
167  if ( !triMesh()->has_vertex_texcoords2D() )
168  triMesh()->request_vertex_texcoords2D();
169 
170  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() )
171  triMesh()->set_texcoord2D( vertexMapTri_[_vh], texCoords_[ _texCoordID ] );
172  objectOptions_ |= VERTEXTEXCOORDS;
173 
174  }else{
175  std::cerr << "Error: TexCoord ID too large" << std::endl;
176  }
177 
178  } else if ( isPolyMesh() ){
179 
180  //handle poly meshes
181  if ( !polyMesh() ) return;
182 
183  if ( _texCoordID < (int) texCoords_.size() ){
184 
185  //perhaps request texCoords for the mesh
186  if ( !polyMesh()->has_vertex_texcoords2D() )
187  polyMesh()->request_vertex_texcoords2D();
188 
189  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() )
190  polyMesh()->set_texcoord2D( vertexMapPoly_[_vh], texCoords_[ _texCoordID ] );
191  objectOptions_ |= VERTEXTEXCOORDS;
192 
193  }else{
194  std::cerr << "Error: TexCoord ID too large" << std::endl;
195  }
196  }
197 }
198 
199 //-----------------------------------------------------------------------------
200 
202 void OFFImporter::setNormal(VertexHandle _vh, int _normalID){
203 
204  if ( isTriangleMesh() ){
205 
206  //handle triangle meshes
207  if ( !triMesh() ) return;
208 
209  if ( _normalID < (int) normals_.size() ){
210 
211  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() ){
212  triMesh()->set_normal( vertexMapTri_[_vh], (TriMesh::Point) normals_[ _normalID ] );
213  objectOptions_ |= VERTEXNORMAL;
214  }
215 
216  }else{
217  std::cerr << "Error: normal ID too large" << std::endl;
218  }
219 
220  } else if ( isPolyMesh() ){
221 
222  //handle poly meshes
223  if ( !polyMesh() ) return;
224 
225  if ( _normalID < (int) normals_.size() ){
226 
227  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() ){
228  polyMesh()->set_normal( vertexMapPoly_[_vh], (PolyMesh::Point) normals_[ _normalID ] );
229  objectOptions_ |= VERTEXNORMAL;
230  }
231 
232  }else{
233  std::cerr << "Error: normal ID too large" << std::endl;
234  }
235 
236  }
237 }
238 
239 //-----------------------------------------------------------------------------
240 
242 VertexHandle OFFImporter::addVertex(const Vec3f& _point){
243 
244  vertices_.push_back( _point );
245 
246  int id = vertices_.size()-1;
247 
248  if ( isTriangleMesh() ){
249 
250  //handle triangle meshes
251  if ( !triMesh() ) return false;
252  vertexMapTri_[ id ] = triMesh()->add_vertex( (TriMesh::Point) vertices_[id] );
253 
254  } else if ( isPolyMesh() ){
255 
256  //handle poly meshes
257  if ( !polyMesh() ) return false;
258  vertexMapPoly_[ id ] = polyMesh()->add_vertex( (PolyMesh::Point) vertices_[id] );
259  }
260 
261  return id;
262 }
263 
264 //-----------------------------------------------------------------------------
265 
267 int OFFImporter::addFace(const VHandles& _indices) {
268 
269  int faceIndex = -1;
270 
271  if ( isTriangleMesh() ){
272 
273  //handle triangle meshes
274  if ( !triMesh() ) return -1;
275 
276  std::vector< TriMesh::VertexHandle > vertices;
277 
278  for (uint i=0; i < _indices.size(); i++){
279 
280  if ( vertexMapTri_.find( _indices[i] ) != vertexMapTri_.end() ){
281 
282  vertices.push_back( vertexMapTri_[ _indices[i] ] );
283 
284  } else {
285  std::cerr << "Error: Cannot add face. Undefined index (" << _indices[i] << ")" << std::endl;
286  return -1;
287  }
288  }
289 
290  TriMesh::FaceHandle fh = triMesh()->add_face( vertices );
291 
292  if(fh.is_valid()) {
293  faceMapTri_.push_back( fh );
294  faceIndex = faceMapTri_.size()-1;
295  } else {
296  // Store non-manifold face
297  invalidFaces_.push_back( vertices );
298  }
299 
300  } else if ( isPolyMesh() ){
301 
302  //handle poly meshes
303  if ( !polyMesh() ) return -1;
304 
305  std::vector< PolyMesh::VertexHandle > vertices;
306 
307  for (uint i=0; i < _indices.size(); i++){
308 
309  if ( vertexMapPoly_.find( _indices[i] ) != vertexMapPoly_.end() ){
310 
311  vertices.push_back( vertexMapPoly_[ _indices[i] ] );
312 
313  }else{
314  std::cerr << "Error: Cannot add face. Undefined index (" << _indices[i] << ")" << std::endl;
315  return -1;
316  }
317  }
318 
319  PolyMesh::FaceHandle fh = polyMesh()->add_face( vertices );
320 
321  if(fh.is_valid()) {
322  faceMapPoly_.push_back(fh);
323  faceIndex = faceMapPoly_.size()-1;
324  } else {
325  // Store non-manifold face vertices
326  invalidFaces_.push_back( vertices );
327  }
328  }
329 
330  return faceIndex;
331 }
332 
333 //-----------------------------------------------------------------------------
334 
336 
337  if(invalidFaces_.empty()) return;
338 
339  if ( isTriangleMesh() ) {
340 
341  for(std::vector<OMVHandles>::iterator it = invalidFaces_.begin();
342  it != invalidFaces_.end(); ++it) {
343 
344  OMVHandles& vhandles = *it;
345 
346  // double vertices
347  for (unsigned int j = 0; j < vhandles.size(); ++j)
348  {
349  TriMesh::Point p = triMesh()->point(vhandles[j]);
350  vhandles[j] = triMesh()->add_vertex(p);
351  // DO STORE p, reference may not work since vertex array
352  // may be relocated after adding a new vertex !
353 
354  // Mark vertices of failed face as non-manifold
355  if (triMesh()->has_vertex_status()) {
356  triMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
357  }
358  }
359 
360  // add face
361  OpenMesh::FaceHandle fh = triMesh()->add_face(vhandles);
362 
363  // Mark failed face as non-manifold
364  if (triMesh()->has_face_status())
365  triMesh()->status(fh).set_fixed_nonmanifold(true);
366 
367  // Mark edges of failed face as non-two-manifold
368  if (triMesh()->has_edge_status()) {
369  TriMesh::FaceEdgeIter fe_it = triMesh()->fe_iter(fh);
370  for(; fe_it.is_valid(); ++fe_it) {
371  triMesh()->status(*fe_it).set_fixed_nonmanifold(true);
372  }
373  }
374 
375  faceMapTri_.push_back(fh);
376  }
377 
378  } else if ( isPolyMesh() ) {
379 
380  for(std::vector<OMVHandles>::iterator it = invalidFaces_.begin();
381  it != invalidFaces_.end(); ++it) {
382 
383  OMVHandles& vhandles = *it;
384 
385  // double vertices
386  for (unsigned int j = 0; j < vhandles.size(); ++j)
387  {
388  TriMesh::Point p = polyMesh()->point(vhandles[j]);
389  vhandles[j] = polyMesh()->add_vertex(p);
390  // DO STORE p, reference may not work since vertex array
391  // may be relocated after adding a new vertex !
392 
393  // Mark vertices of failed face as non-manifold
394  if (polyMesh()->has_vertex_status()) {
395  polyMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
396  }
397  }
398 
399  // add face
400  OpenMesh::FaceHandle fh = polyMesh()->add_face(vhandles);
401 
402  // Mark failed face as non-manifold
403  if (polyMesh()->has_face_status())
404  polyMesh()->status(fh).set_fixed_nonmanifold(true);
405 
406  // Mark edges of failed face as non-two-manifold
407  if (polyMesh()->has_edge_status()) {
408  TriMesh::FaceEdgeIter fe_it = polyMesh()->fe_iter(fh);
409  for(; fe_it.is_valid(); ++fe_it) {
410  polyMesh()->status(*fe_it).set_fixed_nonmanifold(true);
411  }
412  }
413 
414  faceMapPoly_.push_back(fh);
415  }
416  }
417 
418  // Clear all invalid faces
419  invalidFaces_.clear();
420 }
421 
422 //-----------------------------------------------------------------------------
423 
424 bool OFFImporter::isTriangleMesh(){
425  return objectOptions_ & TRIMESH;
426 }
427 
428 //-----------------------------------------------------------------------------
429 
430 bool OFFImporter::isPolyMesh(){
431  return objectOptions_ & POLYMESH;
432 }
433 
434 //-----------------------------------------------------------------------------
435 
436 bool OFFImporter::isBinary(){
437  return objectOptions_ & BINARY;
438 }
439 
440 //-----------------------------------------------------------------------------
441 
443 
444  return objectOptions_ & VERTEXNORMAL;
445 }
446 
447 //-----------------------------------------------------------------------------
448 
449 bool OFFImporter::hasTextureCoords(){
450  return objectOptions_ & VERTEXTEXCOORDS;
451 }
452 
453 //-----------------------------------------------------------------------------
454 
455 bool OFFImporter::hasVertexColors() {
456  return objectOptions_ & VERTEXCOLOR;
457 }
458 
459 //-----------------------------------------------------------------------------
460 
461 bool OFFImporter::hasFaceColors() {
462  return objectOptions_ & FACECOLOR;
463 }
464 
465 //-----------------------------------------------------------------------------
466 
467 bool OFFImporter::hasOption(ObjectOptionsE _option) {
468  return objectOptions_ & _option;
469 }
470 
471 //-----------------------------------------------------------------------------
472 
474  return vertices_.size();
475 }
476 
477 //-----------------------------------------------------------------------------
478 
479 uint OFFImporter::n_normals(){
480  return normals_.size();
481 }
482 
483 //-----------------------------------------------------------------------------
484 
485 uint OFFImporter::n_texCoords(){
486  return texCoords_.size();
487 }
488 
489 //-----------------------------------------------------------------------------
490 
491 void OFFImporter::reserve(unsigned int _nv, unsigned int _ne, unsigned int _nf) {
492 
493  vertices_.reserve(_nv);
494  normals_.reserve(_nv);
495  texCoords_.reserve(_nv);
496  colors_.reserve(_nv);
497 
498  if(isPolyMesh() && polyMesh_ != 0) {
499  polyMesh_->reserve(_nv, _ne, _nf);
500  }
501 
502  if(isTriangleMesh() && triMesh_ != 0) {
503  triMesh_->reserve(_nv, _ne, _nf);
504  }
505 }
506 
507 //-----------------------------------------------------------------------------
508 
510 
511  return object_;
512 }
513 
514 //-----------------------------------------------------------------------------
515 
517  return path_;
518 }
519 
520 //-----------------------------------------------------------------------------
521 
522 void OFFImporter::setPath(QString _path){
523  path_ = _path;
524 }
525 
526 //-----------------------------------------------------------------------------
527 
528 void OFFImporter::setObjectOptions(ObjectOptions _options){
529  objectOptions_ = _options;
530 }
531 
532 //-----------------------------------------------------------------------------
533 
534 void OFFImporter::addOption(ObjectOptionsE _option) {
535  objectOptions_ |= _option;
536 }
537 
538 //-----------------------------------------------------------------------------
539 
540 void OFFImporter::removeOption(ObjectOptionsE _option) {
541  if(objectOptions_ & _option) objectOptions_ -= _option;
542 }
543 
544 //-----------------------------------------------------------------------------
545 
546 OFFImporter::ObjectOptions& OFFImporter::objectOptions(){
547  return objectOptions_;
548 }
549 
550 //-----------------------------------------------------------------------------
551 
552 void OFFImporter::setObjectName(QString _name){
553 
554  if ( object_ != 0 )
555  object_->setName( _name );
556 }
557 
558 //------------------------------------------------------------------------------
559 
561 void OFFImporter::setVertexColor(VertexHandle _vh, int _colorIndex) {
562 
563  if ( isTriangleMesh() ){
564 
565  //handle triangle meshes
566  if ( !triMesh() ) return;
567 
568  if ( _colorIndex < (int) colors_.size() ){
569 
570  if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() ){
571  triMesh()->set_color( vertexMapTri_[_vh], colors_[_colorIndex] );
572  objectOptions_ |= VERTEXCOLOR;
573  }
574 
575  }else{
576  std::cerr << "Error: Color ID too large" << std::endl;
577  }
578 
579  } else if ( isPolyMesh() ){
580 
581  //handle poly meshes
582  if ( !polyMesh() ) return;
583 
584  if ( _colorIndex < (int) colors_.size() ){
585 
586  if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() ){
587  polyMesh()->set_color( vertexMapPoly_[_vh], colors_[_colorIndex] );
588  objectOptions_ |= VERTEXCOLOR;
589  }
590 
591  }else{
592  std::cerr << "Error: Color ID too large" << std::endl;
593  }
594 
595  }
596 }
597 
598 //------------------------------------------------------------------------------
599 
601 void OFFImporter::setFaceColor(FaceHandle _fh, int _colorIndex) {
602 
603  if ( isTriangleMesh() ){
604 
605  //handle triangle meshes
606  if ( !triMesh() ) return;
607 
608  if ( _colorIndex < (int) colors_.size() ){
609 
610  if ( _fh < (int)faceMapTri_.size() ) {
611  triMesh()->set_color( faceMapTri_[_fh],colors_[_colorIndex] );
612  objectOptions_ |= FACECOLOR;
613  }
614 
615  }else{
616  std::cerr << "Error: Color ID too large" << std::endl;
617  }
618 
619  } else if ( isPolyMesh() ){
620 
621  //handle poly meshes
622  if ( !polyMesh() ) return;
623 
624  if ( _colorIndex < (int) colors_.size() ){
625 
626  if ( _fh < (int)faceMapPoly_.size() ) {
627  polyMesh()->set_color( faceMapPoly_[_fh], colors_[_colorIndex] );
628  objectOptions_ |= FACECOLOR;
629  }
630 
631  }else{
632  std::cerr << "Error: Color ID too large" << std::endl;
633  }
634 
635  }
636 }
void setObjectOptions(ObjectOptions _options)
Definition: OFFImporter.cc:528
void setFaceColor(FaceHandle _fh, int _colorIndex)
set face color
Definition: OFFImporter.cc:601
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
Vec3f vertex(uint _index)
get vertex with given index
Definition: OFFImporter.cc:99
int addColor(const Vec4f &_color)
add a color
Definition: OFFImporter.cc:128
void setVertexColor(VertexHandle _vh, int _colorIndex)
set vertex color
Definition: OFFImporter.cc:561
int addTexCoord(const Vec2f &_coord)
add texture coordinates
Definition: OFFImporter.cc:110
BaseObject * getObject()
get BaseObject data of object
Definition: OFFImporter.cc:509
Kernel::FaceEdgeIter FaceEdgeIter
Circulator.
Definition: PolyMeshT.hh:172
bool hasVertexNormals()
Query Object Options.
Definition: OFFImporter.cc:442
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
~OFFImporter()
base class needs virtual destructor
Definition: OFFImporter.cc:55
void setNormal(VertexHandle _vh, int _normalID)
set vertex normal
Definition: OFFImporter.cc:202
void removeOption(ObjectOptionsE _option)
remove an option
Definition: OFFImporter.cc:540
int addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
Definition: OFFImporter.cc:267
uint n_vertices()
Global Properties.
Definition: OFFImporter.cc:473
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
Definition: OFFImporter.cc:157
ObjectOptions & objectOptions()
get Object Options
Definition: OFFImporter.cc:546
int addNormal(const Vec3f &_normal)
add a normal
Definition: OFFImporter.cc:119
OFFImporter()
constructor
Definition: OFFImporter.cc:62
void addObject(BaseObject *_object)
add initial object
Definition: OFFImporter.cc:72
Handle for a face entity.
Definition: Handles.hh:146
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:70
PolyMesh * polyMesh()
get a pointer to the active polyMesh
Definition: OFFImporter.cc:137
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
TriMesh * triMesh()
get a pointer to the active triMesh
Definition: OFFImporter.cc:147
void setObjectName(QString _name)
change the name of an object
Definition: OFFImporter.cc:552
bool hasOption(ObjectOptionsE _option)
test if object has a certain option
Definition: OFFImporter.cc:467
void finish()
Definition: OFFImporter.cc:335
QString path()
Path of the OFF file.
Definition: OFFImporter.cc:516
void addOption(ObjectOptionsE _option)
add an option
Definition: OFFImporter.cc:534
VertexHandle addVertex(const Vec3f &_point)
add a vertex with coordinate _point
Definition: OFFImporter.cc:242
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:734