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
57polyMesh_(0),
58triMesh_(0),
59object_(0),
60objectOptions_(0),
61maxFaceValence_(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
105 texCoords_.push_back( _coord );
106
107 return texCoords_.size()-1;
108}
109
110//-----------------------------------------------------------------------------
111
113int OFFImporter::addNormal(const Vec3f& _normal){
114 normals_.push_back( _normal );
115
116 return normals_.size()-1;
117}
118
119//-----------------------------------------------------------------------------
120
122int 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
151void 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
196void 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
236VertexHandle 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
261int 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(auto it : invalidFaces_) {
336
337 OMVHandles& vhandles = it;
338
339 // double vertices
340 for (unsigned int j = 0; j < vhandles.size(); ++j)
341 {
342 TriMesh::Point p = triMesh()->point(vhandles[j]);
343 vhandles[j] = triMesh()->add_vertex(p);
344 // DO STORE p, reference may not work since vertex array
345 // may be relocated after adding a new vertex !
346
347 // Mark vertices of failed face as non-manifold
348 if (triMesh()->has_vertex_status()) {
349 triMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
350 }
351 }
352
353 // add face
354 OpenMesh::SmartFaceHandle fh = triMesh()->add_face(vhandles);
355
356 // Mark failed face as non-manifold
357 if (triMesh()->has_face_status())
358 triMesh()->status(fh).set_fixed_nonmanifold(true);
359
360 // Mark edges of failed face as non-two-manifold
361 if (triMesh()->has_edge_status()) {
362 for(auto fe_it : fh.edges()) { //
363 triMesh()->status(fe_it).set_fixed_nonmanifold(true);
364 }
365 }
366
367 faceMapTri_.push_back(fh);
368 }
369
370 } else if ( isPolyMesh() ) {
371
372 for(auto it : invalidFaces_) {
373
374 OMVHandles& vhandles = it;
375
376 // double vertices
377 for (unsigned int j = 0; j < vhandles.size(); ++j)
378 {
379 TriMesh::Point p = polyMesh()->point(vhandles[j]);
380 vhandles[j] = polyMesh()->add_vertex(p);
381 // DO STORE p, reference may not work since vertex array
382 // may be relocated after adding a new vertex !
383
384 // Mark vertices of failed face as non-manifold
385 if (polyMesh()->has_vertex_status()) {
386 polyMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
387 }
388 }
389
390 // add face
391 OpenMesh::SmartFaceHandle fh = polyMesh()->add_face(vhandles);
392
393 // Mark failed face as non-manifold
394 if (polyMesh()->has_face_status())
395 polyMesh()->status(fh).set_fixed_nonmanifold(true);
396
397 // Mark edges of failed face as non-two-manifold
398 if (polyMesh()->has_edge_status()) {
399 for(auto fe_it : fh.edges()) {
400 polyMesh()->status(fe_it).set_fixed_nonmanifold(true);
401 }
402 }
403
404 faceMapPoly_.push_back(fh);
405 }
406 }
407
408 // Clear all invalid faces
409 invalidFaces_.clear();
410}
411
412//-----------------------------------------------------------------------------
413
414bool OFFImporter::isTriangleMesh(){
415 return objectOptions_ & TRIMESH;
416}
417
418//-----------------------------------------------------------------------------
419
420bool OFFImporter::isPolyMesh(){
421 return objectOptions_ & POLYMESH;
422}
423
424//-----------------------------------------------------------------------------
425
426bool OFFImporter::isBinary(){
427 return objectOptions_ & BINARY;
428}
429
430//-----------------------------------------------------------------------------
431
433
434 return objectOptions_ & VERTEXNORMAL;
435}
436
437//-----------------------------------------------------------------------------
438
439bool OFFImporter::hasTextureCoords(){
440 return objectOptions_ & VERTEXTEXCOORDS;
441}
442
443//-----------------------------------------------------------------------------
444
445bool OFFImporter::hasVertexColors() {
446 return objectOptions_ & VERTEXCOLOR;
447}
448
449//-----------------------------------------------------------------------------
450
451bool OFFImporter::hasFaceColors() {
452 return objectOptions_ & FACECOLOR;
453}
454
455//-----------------------------------------------------------------------------
456
457bool OFFImporter::hasOption(ObjectOptionsE _option) {
458 return objectOptions_ & _option;
459}
460
461//-----------------------------------------------------------------------------
462
464 return vertices_.size();
465}
466
467//-----------------------------------------------------------------------------
468
469uint OFFImporter::n_normals(){
470 return normals_.size();
471}
472
473//-----------------------------------------------------------------------------
474
475uint OFFImporter::n_texCoords(){
476 return texCoords_.size();
477}
478
479//-----------------------------------------------------------------------------
480
481void OFFImporter::reserve(unsigned int _nv, unsigned int _ne, unsigned int _nf) {
482
483 vertices_.reserve(_nv);
484 normals_.reserve(_nv);
485 texCoords_.reserve(_nv);
486 colors_.reserve(_nv);
487
488 if(isPolyMesh() && polyMesh_ != 0) {
489 polyMesh_->reserve(_nv, _ne, _nf);
490 }
491
492 if(isTriangleMesh() && triMesh_ != 0) {
493 triMesh_->reserve(_nv, _ne, _nf);
494 }
495}
496
497//-----------------------------------------------------------------------------
498
500
501 return object_;
502}
503
504//-----------------------------------------------------------------------------
505
507 return path_;
508}
509
510//-----------------------------------------------------------------------------
511
512void OFFImporter::setPath(QString _path){
513 path_ = _path;
514}
515
516//-----------------------------------------------------------------------------
517
518void OFFImporter::setObjectOptions(ObjectOptions _options){
519 objectOptions_ = _options;
520}
521
522//-----------------------------------------------------------------------------
523
524void OFFImporter::addOption(ObjectOptionsE _option) {
525 objectOptions_ |= _option;
526}
527
528//-----------------------------------------------------------------------------
529
530void OFFImporter::removeOption(ObjectOptionsE _option) {
531 if(objectOptions_ & _option) objectOptions_ -= _option;
532}
533
534//-----------------------------------------------------------------------------
535
536OFFImporter::ObjectOptions& OFFImporter::objectOptions(){
537 return objectOptions_;
538}
539
540//-----------------------------------------------------------------------------
541
542void OFFImporter::setObjectName(QString _name){
543
544 if ( object_ != 0 )
545 object_->setName( _name );
546}
547
548//------------------------------------------------------------------------------
549
551void OFFImporter::setVertexColor(VertexHandle _vh, int _colorIndex) {
552
553 if ( isTriangleMesh() ){
554
555 //handle triangle meshes
556 if ( !triMesh() ) return;
557
558 if ( _colorIndex < (int) colors_.size() ){
559
560 if ( vertexMapTri_.find( _vh ) != vertexMapTri_.end() ){
561 triMesh()->set_color( vertexMapTri_[_vh], colors_[_colorIndex] );
562 objectOptions_ |= VERTEXCOLOR;
563 }
564
565 }else{
566 std::cerr << "Error: Color ID too large" << std::endl;
567 }
568
569 } else if ( isPolyMesh() ){
570
571 //handle poly meshes
572 if ( !polyMesh() ) return;
573
574 if ( _colorIndex < (int) colors_.size() ){
575
576 if ( vertexMapPoly_.find( _vh ) != vertexMapPoly_.end() ){
577 polyMesh()->set_color( vertexMapPoly_[_vh], colors_[_colorIndex] );
578 objectOptions_ |= VERTEXCOLOR;
579 }
580
581 }else{
582 std::cerr << "Error: Color ID too large" << std::endl;
583 }
584
585 }
586}
587
588//------------------------------------------------------------------------------
589
591void OFFImporter::setFaceColor(FaceHandle _fh, int _colorIndex) {
592
593 if ( isTriangleMesh() ){
594
595 //handle triangle meshes
596 if ( !triMesh() ) return;
597
598 if ( _colorIndex < (int) colors_.size() ){
599
600 if ( _fh < (int)faceMapTri_.size() ) {
601 triMesh()->set_color( faceMapTri_[_fh],colors_[_colorIndex] );
602 objectOptions_ |= FACECOLOR;
603 }
604
605 }else{
606 std::cerr << "Error: Color ID too large" << std::endl;
607 }
608
609 } else if ( isPolyMesh() ){
610
611 //handle poly meshes
612 if ( !polyMesh() ) return;
613
614 if ( _colorIndex < (int) colors_.size() ){
615
616 if ( _fh < (int)faceMapPoly_.size() ) {
617 polyMesh()->set_color( faceMapPoly_[_fh], colors_[_colorIndex] );
618 objectOptions_ |= FACECOLOR;
619 }
620
621 }else{
622 std::cerr << "Error: Color ID too large" << std::endl;
623 }
624
625 }
626}
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:721
MeshT * mesh()
return a pointer to the mesh
int addTexCoord(const Vec2f &_coord)
add texture coordinates
Definition: OFFImporter.cc:104
ObjectOptions & objectOptions()
get Object Options
Definition: OFFImporter.cc:536
TriMesh * triMesh()
get a pointer to the active triMesh
Definition: OFFImporter.cc:141
PolyMesh * polyMesh()
get a pointer to the active polyMesh
Definition: OFFImporter.cc:131
void setObjectOptions(ObjectOptions _options)
Definition: OFFImporter.cc:518
OFFImporter()
constructor
Definition: OFFImporter.cc:56
VertexHandle addVertex(const Vec3f &_point)
add a vertex with coordinate _point
Definition: OFFImporter.cc:236
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
Definition: OFFImporter.cc:151
bool hasVertexNormals()
Query Object Options.
Definition: OFFImporter.cc:432
void setObjectName(QString _name)
change the name of an object
Definition: OFFImporter.cc:542
void setVertexColor(VertexHandle _vh, int _colorIndex)
set vertex color
Definition: OFFImporter.cc:551
int addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
Definition: OFFImporter.cc:261
void addOption(ObjectOptionsE _option)
add an option
Definition: OFFImporter.cc:524
uint n_vertices()
Global Properties.
Definition: OFFImporter.cc:463
int addNormal(const Vec3f &_normal)
add a normal
Definition: OFFImporter.cc:113
void removeOption(ObjectOptionsE _option)
remove an option
Definition: OFFImporter.cc:530
Vec3f vertex(uint _index)
get vertex with given index
Definition: OFFImporter.cc:93
~OFFImporter()
base class needs virtual destructor
Definition: OFFImporter.cc:49
void setFaceColor(FaceHandle _fh, int _colorIndex)
set face color
Definition: OFFImporter.cc:591
QString path()
Path of the OFF file.
Definition: OFFImporter.cc:506
void finish()
Definition: OFFImporter.cc:329
void addObject(BaseObject *_object)
add initial object
Definition: OFFImporter.cc:66
bool hasOption(ObjectOptionsE _option)
test if object has a certain option
Definition: OFFImporter.cc:457
int addColor(const Vec4f &_color)
add a color
Definition: OFFImporter.cc:122
BaseObject * getObject()
get BaseObject data of object
Definition: OFFImporter.cc:499
void setNormal(VertexHandle _vh, int _normalID)
set vertex normal
Definition: OFFImporter.cc:196
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:139
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
PolyConnectivity::ConstFaceEdgeRange edges() const
Returns a range of edges of the face (PolyConnectivity::fv_range())