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
49 OFFImporter::~OFFImporter(){
50
51 }
52
53 //-----------------------------------------------------------------------------
54
56 OFFImporter::OFFImporter() :
57 polyMesh_(0),
58 triMesh_(0),
59 object_(0),
60 objectOptions_(0),
61 maxFaceValence_(0) {}
62
63 //-----------------------------------------------------------------------------
64
66 void OFFImporter::addObject( BaseObject* _object ){
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
93 Vec3f OFFImporter::vertex(uint _index){
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
131 PolyMesh* OFFImporter::polyMesh(){
132 if (polyMesh_ == 0)
133 return 0;
134 else
135 return polyMesh_;
136 }
137
138 //-----------------------------------------------------------------------------
139
141 TriMesh* OFFImporter::triMesh(){
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
329 void OFFImporter::finish() {
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
436 bool OFFImporter::hasVertexNormals(){
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
467 uint OFFImporter::n_vertices(){
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
503 BaseObject* OFFImporter::getObject(){
504
505 return object_;
506 }
507
508 //-----------------------------------------------------------------------------
509
510 QString OFFImporter::path(){
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 }
OFFImporter::OFFImporter
OFFImporter()
constructor
Definition: OFFImporter.cc:56
OFFImporter::triMesh
TriMesh * triMesh()
get a pointer to the active triMesh
Definition: OFFImporter.cc:141
OFFImporter::finish
void finish()
Definition: OFFImporter.cc:329
OFFImporter::vertex
Vec3f vertex(uint _index)
get vertex with given index
Definition: OFFImporter.cc:93
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
OFFImporter::getObject
BaseObject * getObject()
get BaseObject data of object
Definition: OFFImporter.cc:503
OFFImporter::hasVertexNormals
bool hasVertexNormals()
Query Object Options.
Definition: OFFImporter.cc:436
OFFImporter::setObjectOptions
void setObjectOptions(ObjectOptions _options)
Definition: OFFImporter.cc:522
OFFImporter::setVertexTexCoord
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
Definition: OFFImporter.cc:151
OFFImporter::addNormal
int addNormal(const Vec3f &_normal)
add a normal
Definition: OFFImporter.cc:113
OFFImporter::hasOption
bool hasOption(ObjectOptionsE _option)
test if object has a certain option
Definition: OFFImporter.cc:461
MeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT_impl.hh:350
OFFImporter::polyMesh
PolyMesh * polyMesh()
get a pointer to the active polyMesh
Definition: OFFImporter.cc:131
OpenMesh::PolyMeshT::FaceEdgeIter
Kernel::FaceEdgeIter FaceEdgeIter
Circulator.
Definition: PolyMeshT.hh:169
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
OFFImporter::addObject
void addObject(BaseObject *_object)
add initial object
Definition: OFFImporter.cc:66
OFFImporter::setNormal
void setNormal(VertexHandle _vh, int _normalID)
set vertex normal
Definition: OFFImporter.cc:196
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OFFImporter::path
QString path()
Path of the OFF file.
Definition: OFFImporter.cc:510
OFFImporter::~OFFImporter
~OFFImporter()
base class needs virtual destructor
Definition: OFFImporter.cc:49
OFFImporter::setVertexColor
void setVertexColor(VertexHandle _vh, int _colorIndex)
set vertex color
Definition: OFFImporter.cc:555
OFFImporter::addTexCoord
int addTexCoord(const Vec2f &_coord)
add texture coordinates
Definition: OFFImporter.cc:104
OFFImporter::setObjectName
void setObjectName(QString _name)
change the name of an object
Definition: OFFImporter.cc:546
OFFImporter::addVertex
VertexHandle addVertex(const Vec3f &_point)
add a vertex with coordinate _point
Definition: OFFImporter.cc:236
BaseObject
Definition: BaseObject.hh:82
OpenMesh::VectorT< float, 3 >
OFFImporter::addColor
int addColor(const Vec4f &_color)
add a color
Definition: OFFImporter.cc:122
OFFImporter::addOption
void addOption(ObjectOptionsE _option)
add an option
Definition: OFFImporter.cc:528
BaseObject::setName
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:723
OFFImporter::addFace
int addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
Definition: OFFImporter.cc:261
OFFImporter::objectOptions
ObjectOptions & objectOptions()
get Object Options
Definition: OFFImporter.cc:540
OFFImporter::removeOption
void removeOption(ObjectOptionsE _option)
remove an option
Definition: OFFImporter.cc:534
OFFImporter::n_vertices
uint n_vertices()
Global Properties.
Definition: OFFImporter.cc:467
PolyMeshObject
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
OFFImporter::setFaceColor
void setFaceColor(FaceHandle _fh, int _colorIndex)
set face color
Definition: OFFImporter.cc:595