Developer Documentation
OBJImporter.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 "OBJImporter.hh"
45
46//-----------------------------------------------------------------------------
47//-----------------------------------------------------------------------------
48
51
52}
53
54//-----------------------------------------------------------------------------
55
57VertexHandle OBJImporter::addVertex(const Vec3d& _point){
58 vertices_.push_back( _point );
59
60 return vertices_.size()-1;
61}
62
64Vec3d OBJImporter::vertex(unsigned int _index){
65
66 if ( vertices_.size() > _index )
67 return vertices_[ _index ];
68 else
69 return Vec3d();
70}
71
72//-----------------------------------------------------------------------------
73
76 texCoords_.push_back( _coord );
77
78 return texCoords_.size()-1;
79}
80
81//-----------------------------------------------------------------------------
82
84int OBJImporter::addNormal(const Vec3d& _normal){
85 normals_.push_back( _normal );
86
87 return normals_.size()-1;
88}
89
90//-----------------------------------------------------------------------------
91
93void OBJImporter::setDegreeU(int _degree){
94 degreeU_ = _degree;
95}
96
97//-----------------------------------------------------------------------------
98
100void OBJImporter::setDegreeV(int _degree){
101 degreeV_ = _degree;
102}
103
104
105//-----------------------------------------------------------------------------
106
109 return degreeU_;
110}
111
112//-----------------------------------------------------------------------------
113
116 return degreeV_;
117}
118
119//-----------------------------------------------------------------------------
120
122void OBJImporter::setObject(BaseObject* _object, int _groupId) {
123
124 if((unsigned int)_groupId >= triMeshes_.size()) {
125 std::cerr << "Error: Group does not exist!" << std::endl;
126 return;
127 }
128
129 if(PluginFunctions::polyMeshObject(_object->id()) != NULL) {
130
131 polyMeshes_[_groupId] = PluginFunctions::polyMeshObject(_object->id());
132 addUsedVertices(_groupId);
133
134 } else if(PluginFunctions::triMeshObject(_object->id()) != NULL) {
135
136 triMeshes_[_groupId] = PluginFunctions::triMeshObject(_object->id());
137 addUsedVertices(_groupId);
138 }
139#ifdef ENABLE_BSPLINECURVE_SUPPORT
141
142 bSplineCurves_[_groupId] = PluginFunctions::bsplineCurveObject(PluginFunctions::baseObjectData(_object));
143 }
144#endif
145#ifdef ENABLE_BSPLINESURFACE_SUPPORT
147
148 bSplineSurfaces_[_groupId] = PluginFunctions::bsplineSurfaceObject(PluginFunctions::baseObjectData(_object));
149 }
150#endif
151 else {
152 std::cerr << "Error: Cannot add object. Type is unknown!" << std::endl;
153 }
154}
155
156//-----------------------------------------------------------------------------
157
160
161 return currentGroup_;
162}
163
164//-----------------------------------------------------------------------------
165
168
169 return polyMeshes_[currentGroup_]->mesh();
170}
171
172//-----------------------------------------------------------------------------
173
176
177 return triMeshes_[currentGroup_]->mesh();
178}
179
180//-----------------------------------------------------------------------------
181
182#ifdef ENABLE_BSPLINECURVE_SUPPORT
183
184BSplineCurve* OBJImporter::currentCurve(){
185
186 return bSplineCurves_[currentGroup_]->splineCurve();
187}
188
189#endif
190
191//-----------------------------------------------------------------------------
192
193#ifdef ENABLE_BSPLINESURFACE_SUPPORT
194
195BSplineSurface* OBJImporter::currentSurface(){
196
197 return bSplineSurfaces_[currentGroup_]->splineSurface();
198}
199
200#endif
201
202//-----------------------------------------------------------------------------
203
206
207 if (isTriangleMesh(_groupId)) {
208
209 //handle triangle meshes
210 TriMesh* curMesh = triMeshes_[_groupId]->mesh();
211 if (curMesh == NULL)
212 return;
213
214 // add all vertices to the mesh
215
216 if(usedVertices_.size() <= static_cast<size_t>(_groupId)) return;
217
218 for(auto it : usedVertices_[_groupId]) {
219
220 if (it.first >= (int)vertices_.size()) {
221 std::cerr << "Error: Vertex ID too large" << std::endl;
222 continue;
223 }
224
225 if (vertexMapTri_[_groupId].find(it.first) == vertexMapTri_[_groupId].end()) {
226 vertexMapTri_[_groupId].insert(std::pair<int, TriMesh::VertexHandle>(it.first, curMesh->add_vertex((TriMesh::Point)vertices_[it.first])));
227 }
228 }
229
230 } else if (isPolyMesh(_groupId)) {
231
232 //handle triangle meshes
233 PolyMesh* curMesh = polyMeshes_[_groupId]->mesh();
234 if (curMesh == NULL)
235 return;
236
237 //add all vertices to the mesh
238
239 if(usedVertices_.size() <= static_cast<size_t>(_groupId)) return;
240
241 for(auto it : usedVertices_[_groupId]) {
242
243 if (it.first >= (int)vertices_.size()) {
244 std::cerr << "Error: Vertex ID too large" << std::endl;
245 continue;
246 }
247
248 if (vertexMapPoly_[_groupId].find(it.first) == vertexMapPoly_[_groupId].end()) {
249 vertexMapPoly_[_groupId].insert(std::pair<int, PolyMesh::VertexHandle>(it.first, curMesh->add_vertex((PolyMesh::Point)vertices_[it.first])));
250 }
251 }
252 }
253}
254
255//-----------------------------------------------------------------------------
256
258void OBJImporter::setVertexTexCoord(VertexHandle _vh, int _texCoordID){
259
260 if ( isTriangleMesh( currentGroup() ) ){
261
262 //handle triangle meshes
263 if ( !currentTriMesh() ) return;
264
265 if ( _texCoordID < (int) texCoords_.size() ){
266
267 //perhaps request texCoords for the mesh
268 if ( !currentTriMesh()->has_vertex_texcoords2D() )
269 currentTriMesh()->request_vertex_texcoords2D();
270
271 //set the texCoords
272 if ( vertexMapTri_[currentGroup_].find( _vh ) != vertexMapTri_[currentGroup_].end() )
273 currentTriMesh()->set_texcoord2D( vertexMapTri_[currentGroup_][_vh], texCoords_[ _texCoordID ] );
274
275 }else{
276 std::cerr << "Error: TexCoord ID too large" << std::endl;
277 }
278
279 } else if ( isPolyMesh( currentGroup() ) ){
280
281 //handle poly meshes
282 if ( !currentPolyMesh() ) return;
283
284 if ( _texCoordID < (int) texCoords_.size() ){
285
286 //perhaps request texCoords for the mesh
287 if ( !currentPolyMesh()->has_vertex_texcoords2D() )
288 currentPolyMesh()->request_vertex_texcoords2D();
289
290 //set the texCoords
291 if ( vertexMapPoly_[currentGroup_].find( _vh ) != vertexMapPoly_[currentGroup_].end() )
292 currentPolyMesh()->set_texcoord2D( vertexMapPoly_[currentGroup_][_vh], texCoords_[ _texCoordID ] );
293
294 }else{
295 std::cerr << "Error: TexCoord ID too large" << std::endl;
296 }
297 }
298}
299
300//-----------------------------------------------------------------------------
301
303void OBJImporter::setNormal(int _index, int _normalID){
304
305 if ( isTriangleMesh( currentGroup() ) ){
306
307 //handle triangle meshes
308 if ( !currentTriMesh() ) return;
309
310 if ( _normalID < (int) normals_.size() )
311 {
312 if ( vertexMapTri_[currentGroup_].find( _index ) != vertexMapTri_[currentGroup_].end() )
313 {
314 TriMesh::VertexHandle vh = vertexMapTri_[currentGroup_][_index];
315 TriMesh::Normal normal = static_cast<TriMesh::Normal>( normals_[ _normalID ] );
316 TriMesh* currentMesh = currentTriMesh();
317 currentMesh->set_normal( vh , normal );
318 objectOptions_[ currentGroup_ ] |= NORMALS;
319
320 storedTriHENormals_[vh] = normal;
321 }
322
323 }else{
324 std::cerr << "Error: normal ID too large" << std::endl;
325 }
326
327 } else if ( isPolyMesh( currentGroup() ) ){
328
329 //handle poly meshes
330 if ( !currentPolyMesh() ) return;
331
332 if ( _normalID < (int) normals_.size() )
333 {
334 if ( vertexMapPoly_[currentGroup_].find( _index ) != vertexMapPoly_[currentGroup_].end() )
335 {
336 PolyMesh::VertexHandle vh = vertexMapPoly_[currentGroup_][_index];
337 PolyMesh::Point normal = static_cast<PolyMesh::Point>( normals_[ _normalID ] );
338 PolyMesh* currentMesh = currentPolyMesh();
339 currentMesh->set_normal( vh , normal );
340 objectOptions_[ currentGroup_ ] |= NORMALS;
341
342 storedPolyHENormals_[vh] = normal;
343 }
344
345 }else{
346 std::cerr << "Error: normal ID too large" << std::endl;
347 }
348
349 }
350}
351
352//-----------------------------------------------------------------------------
353
354bool OBJImporter::addFace(const VHandles& _indices, OpenMesh::FaceHandle &_outFH, std::vector< TriMesh::VertexHandle > &_outTriVertices, std::vector< PolyMesh::VertexHandle > &_outPolyVertices)
355{
356 if ( isTriangleMesh( currentGroup() ) ){
357
358 //handle triangle meshes
359 if ( !currentTriMesh() ) return false;
360
361 addedFacesTri_[currentGroup_].clear();
362
363 for (unsigned int i=0; i < _indices.size(); i++){
364
365 if ( vertexMapTri_[currentGroup_].find( _indices[i] ) != vertexMapTri_[currentGroup_].end() ){
366
367 _outTriVertices.push_back( vertexMapTri_[currentGroup_][ _indices[i] ] );
368
369 }else{
370 std::cerr << "Error: cannot add face. undefined index (" << _indices[i] << ")" << std::endl;
371 return false;
372 }
373 }
374
375 size_t n_faces = currentTriMesh()->n_faces();
376
377 OpenMesh::SmartFaceHandle fh = currentTriMesh()->add_face( _outTriVertices );
378
379 //remember all new faces
380 if(!fh.is_valid()) {
381 // Store non-manifold face
382 invalidFaces_[currentGroup_].push_back(_outTriVertices);
383
384 } else {
385 // Store recently added face
386 for( size_t i=0; i < currentTriMesh()->n_faces()-n_faces; ++i )
387 addedFacesTri_[currentGroup_].push_back( TriMesh::FaceHandle(n_faces+i) );
388
389 //write stored normals into the half edges
390 if (!currentTriMesh()->has_halfedge_normals())
391 currentTriMesh()->request_halfedge_normals();
392
393 //iterate over all incoming haldedges of the added face
394 for (auto fh_iter : fh.halfedges())
395 {
396 //and write the normals to it
397 OpenMesh::SmartHalfedgeHandle heh = fh_iter;
398 TriMesh::VertexHandle vh = heh.to();
399 std::map<TriMesh::VertexHandle,TriMesh::Normal>::iterator iter = storedTriHENormals_.find(vh);
400 if (iter != storedTriHENormals_.end())
401 currentTriMesh()->set_normal(heh,iter->second);
402 }
403 storedTriHENormals_.clear();
404 }
405
406 _outFH = fh;
407 return true;
408
409 } else if ( isPolyMesh( currentGroup() ) ){
410
411 //handle poly meshes
412 if ( !currentPolyMesh() ) return false;
413
414 for (unsigned int i=0; i < _indices.size(); i++){
415
416 if ( vertexMapPoly_[currentGroup_].find( _indices[i] ) != vertexMapPoly_[currentGroup_].end() ){
417
418 _outPolyVertices.push_back( vertexMapPoly_[currentGroup_][ _indices[i] ] );
419
420 }else{
421 std::cerr << "Error: cannot add face. undefined index (" << _indices[i] << ")" << std::endl;
422 return false;
423 }
424 }
425
426 if(!vertexListIsManifold(_outPolyVertices)) {
427 std::cerr << "Face consists of multiple occurrences of the same vertex!" << std::endl;
428 return false;
429 }
430
431 OpenMesh::SmartFaceHandle fh = currentPolyMesh()->add_face( _outPolyVertices );
432
433 if(!fh.is_valid()) {
434 // Store non-manifold face
435 invalidFaces_[currentGroup_].push_back(_outPolyVertices);
436 } else {
437 addedFacePoly_ = fh;
438
439 //write stored normals into the half edges
440 if (!currentPolyMesh()->has_halfedge_normals())
441 currentPolyMesh()->request_halfedge_normals();
442
443 //iterate over all incoming haldedges of the added face
444 for (auto fh_iter : fh.halfedges())
445 {
446 //and write the normals to it
447 OpenMesh::SmartHalfedgeHandle heh = fh_iter;
448 PolyMesh::VertexHandle vh = heh.to();
449 std::map<PolyMesh::VertexHandle,PolyMesh::Normal>::iterator iter = storedTriHENormals_.find(vh);
450 if (iter != storedTriHENormals_.end())
451 currentPolyMesh()->set_normal(heh,iter->second);
452 }
453 storedPolyHENormals_.clear();
454
455 }
456
457 _outFH = fh;
458 return true;
459 }
460 return false;
461}
462
464void OBJImporter::addFace(const VHandles& _indices){
466 std::vector< TriMesh::VertexHandle > triVertices;
467 std::vector< PolyMesh::VertexHandle > polyVertices;
468 addFace(_indices,fh,triVertices,polyVertices);
469
470}
471
472//-----------------------------------------------------------------------------
473
474bool OBJImporter::vertexListIsManifold(const std::vector<PolyMesh::VertexHandle>& _vertices) const {
475
476 std::set<PolyMesh::VertexHandle> check;
477 for(auto v_it : _vertices) {
478 check.insert(v_it);
479 }
480
481 return (check.size() == _vertices.size());
482}
483
484//-----------------------------------------------------------------------------
485
487void OBJImporter::addFace(const VHandles& _indices, const std::vector<int>& _face_texcoords){
488
489
491 std::vector< TriMesh::VertexHandle > triVertices;
492 std::vector< PolyMesh::VertexHandle > polyVertices;
493 if(!addFace(_indices, fh, triVertices, polyVertices) || !fh.is_valid())
494 return;
495
496 if ( isTriangleMesh(currentGroup()) )
497 {
498 //perhaps request texCoords for the mesh
499 if ( !currentTriMesh()->has_halfedge_texcoords2D() )
500 currentTriMesh()->request_halfedge_texcoords2D();
501
502 //now add texCoords
503
504 // get first halfedge handle
505 TriMesh::HalfedgeHandle cur_heh = currentTriMesh()->halfedge_handle( addedFacesTri_[currentGroup_][0] );
506 TriMesh::HalfedgeHandle end_heh = currentTriMesh()->prev_halfedge_handle(cur_heh);
507
508 // find start heh
509 while( currentTriMesh()->to_vertex_handle(cur_heh) != triVertices[0] && cur_heh != end_heh )
510 cur_heh = currentTriMesh()->next_halfedge_handle( cur_heh);
511
512 for(unsigned int i=0; i<_face_texcoords.size(); ++i)
513 {
514 if ( _face_texcoords[i] < (int)texCoords_.size() ){
515
516 PolyMesh::TexCoord2D tex = OpenMesh::vector_cast<TriMesh::TexCoord2D>( texCoords_[ _face_texcoords[i] ] );
517 currentTriMesh()->set_texcoord2D(cur_heh, tex);
518
519 cur_heh = currentTriMesh()->next_halfedge_handle(cur_heh);
520
521 } else
522 std::cerr << "Error: cannot set texture coordinates. undefined index." << std::endl;
523 }
524 }else if (isPolyMesh(currentGroup()))
525 {
526 addedFacePoly_ = fh;
527
528 //perhaps request texCoords for the mesh
529 if ( !currentPolyMesh()->has_halfedge_texcoords2D() )
530 currentPolyMesh()->request_halfedge_texcoords2D();
531
532 //now add texCoords
533
534 if ( addedFacePoly_.is_valid() ) {
535 // get first halfedge handle
536 PolyMesh::HalfedgeHandle cur_heh = currentPolyMesh()->halfedge_handle( addedFacePoly_ );
537 PolyMesh::HalfedgeHandle end_heh = currentPolyMesh()->prev_halfedge_handle(cur_heh);
538
539 // find start heh
540 while( currentPolyMesh()->to_vertex_handle(cur_heh) != polyVertices[0] && cur_heh != end_heh )
541 cur_heh = currentPolyMesh()->next_halfedge_handle( cur_heh);
542
543 for(unsigned int i=0; i<_face_texcoords.size(); ++i)
544 {
545 if ( _face_texcoords[i] < (int)texCoords_.size() ){
546
547 PolyMesh::TexCoord2D tex = OpenMesh::vector_cast<PolyMesh::TexCoord2D>( texCoords_[ _face_texcoords[i] ] );
548 currentPolyMesh()->set_texcoord2D(cur_heh, tex);
549
550 cur_heh = currentPolyMesh()->next_halfedge_handle(cur_heh);
551
552 }else
553 std::cerr << "Error: cannot set texture coordinates. undefined index." << std::endl;
554 }
555 }
556 }
557}
558
559//-----------------------------------------------------------------------------
560
561void OBJImporter::addMaterial(std::string _materialName){
562
563
564 if ( isTriangleMesh( currentGroup() ) ){
565
566 //handle triangle meshes
567 if ( !currentTriMesh() ) return;
568
569
570 if ( materials_.find( _materialName ) != materials_.end() ){
571
572 Material& mat = materials_[ _materialName ];
573
574 //get textureIndex Property
575 OpenMesh::FPropHandleT< int > indexProperty;
576
578
579 if ( hasTexture( currentGroup() ) ){
580
581 bool textureAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOTEXTURES );
582
583 if ( textureAllowed ){
584
585 // Add texture index property if it doesn't exist yet
586 if (! currentTriMesh()->get_property_handle(indexProperty,TEXTUREINDEX) )
587 currentTriMesh()->add_property(indexProperty,TEXTUREINDEX);
588 }
589 }
590
591 // set materialNode color
592 if (mat.has_Ka()) {
593 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ka());
594 triMeshObj->materialNode()->set_ambient_color(color);
595 }
596
597 if (mat.has_Kd()) {
598 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd());
599 triMeshObj->materialNode()->set_diffuse_color(color);
600 }
601
602 if (mat.has_Ks()) {
603 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ks());
604 triMeshObj->materialNode()->set_specular_color(color);
605 }
606
607 if (mat.has_Ke()) {
608 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ke());
609 triMeshObj->materialNode()->set_emission(color);
610 }
611
612 if (mat.has_Ni()) {
613 float Ni = mat.Ni();
614 triMeshObj->materialNode()->set_indexOfRefraction(Ni);
615 }
616
617 if (mat.has_Ns()) {
618 float shininess = mat.Ns();
619 triMeshObj->materialNode()->set_shininess(shininess);
620 }
621
622 if (mat.has_illum()) {
623 triMeshObj->materialNode()->set_refractive(mat.isRefractive());
624 }
625
626
627 for (unsigned int i=0; i < addedFacesTri_[currentGroup_].size(); i++){
628
629 if ( mat.has_Kd() ) {
630 bool colorAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOCOLOR );
631
632 if ( currentTriMesh()->has_face_colors() && colorAllowed ){
633
634 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd() );
635
636 // Get alpha if available
637 if (mat.has_Tr() ) {
638 color[3] = mat.Tr();
639 } else {
640 color[3] = 1.0;
641 }
642 currentTriMesh()->set_color(addedFacesTri_[currentGroup_][i], color );
643 objectOptions_[ currentGroup() ] |= FACECOLOR;
644 }
645 }
646
647 bool textureAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOTEXTURES );
648
649 // Set the texture index in the face index property
650 if ( mat.has_Texture() ) {
651
652 if ( hasTexture( currentGroup() ) && textureAllowed )
653 currentTriMesh()->property(indexProperty, addedFacesTri_[currentGroup_][i]) = mat.map_Kd_index();
654
655 } else {
656 // If we don't have the info, set it to no texture
657 if ( hasTexture( currentGroup() ) && textureAllowed )
658 currentTriMesh()->property(indexProperty, addedFacesTri_[currentGroup_][i]) = 0;
659 }
660
661 }
662 }
663
664 } else if ( isPolyMesh( currentGroup() ) ){
665
666 //handle poly meshes
667 if ( !currentPolyMesh() ) return;
668
669 if ( materials_.find( _materialName ) != materials_.end() ){
670
671 Material& mat = materials_[ _materialName ];
672
673 //get textureIndex Property
674 OpenMesh::FPropHandleT< int > indexProperty;
675
677
678 if ( hasTexture( currentGroup() ) ){
679
680 bool textureAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOTEXTURES );
681
682 if ( textureAllowed ){
683
684 if (! currentPolyMesh()->get_property_handle(indexProperty,TEXTUREINDEX) )
685 currentPolyMesh()->add_property(indexProperty,TEXTUREINDEX);
686 }
687 }
688
689 if ( mat.has_Kd() ) {
690 bool colorAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOCOLOR );
691
692 if ( currentPolyMesh()->has_face_colors() && colorAllowed && addedFacePoly_.is_valid() ){
693
694 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd() );
695
696 // Get alpha if available
697 if (mat.has_Tr() ) {
698 color[3] = mat.Tr();
699 } else {
700 color[3] = 1.0;
701 }
702
703 currentPolyMesh()->set_color(addedFacePoly_, color );
704 polyMeshObj->materialNode()->set_diffuse_color(color);
705 objectOptions_[ currentGroup() ] |= FACECOLOR;
706 }
707 }
708
709 // set materialNode color
710 if (mat.has_Ka()) {
711 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ka());
712 polyMeshObj->materialNode()->set_ambient_color(color);
713 }
714
715 if (mat.has_Ks()) {
716 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ks());
717 polyMeshObj->materialNode()->set_specular_color(color);
718 }
719
720 if (mat.has_Ke()) {
721 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ke());
722 polyMeshObj->materialNode()->set_emission(color);
723 }
724
725 if (mat.has_Ni()) {
726 float Ni = mat.Ni();
727 polyMeshObj->materialNode()->set_indexOfRefraction(Ni);
728 }
729
730 if (mat.has_Ns()) {
731 float shininess = mat.Ns();
732 polyMeshObj->materialNode()->set_shininess(shininess);
733 }
734
735 if (mat.has_illum()) {
736 polyMeshObj->materialNode()->set_refractive(mat.isRefractive());
737 }
738
739 bool textureAllowed = ! ( objectOptions_[ currentGroup() ] & FORCE_NOTEXTURES );
740
741 // Set the texture index in the face index property
742 if ( mat.has_Texture() ) {
743
744 if ( hasTexture( currentGroup() ) && textureAllowed && addedFacePoly_.is_valid())
745 currentPolyMesh()->property(indexProperty, addedFacePoly_) = mat.map_Kd_index();
746
747 } else {
748 // If we don't have the info, set it to no texture
749 if ( hasTexture( currentGroup() ) && textureAllowed && addedFacePoly_.is_valid())
750 currentPolyMesh()->property(indexProperty, addedFacePoly_) = 0;
751 }
752 }
753 }
754}
755
756//-----------------------------------------------------------------------------
757
758// force all meshes to be opened with specific type
759void OBJImporter::forceMeshType( ObjectOptions _meshType ){
760
761
762 bool isMesh = (objectOptions_[currentGroup_] & TRIMESH) | (objectOptions_[currentGroup_] & POLYMESH);
763 bool correctType = objectOptions_[currentGroup_] & _meshType;
764
765 if ( isMesh && !correctType ) {
766 ObjectOptions options = objectOptions_[currentGroup_];
767
768 options &= ~(1<<1);
769 options &= ~(1<<2);
770 options &= ~(1<<3);
771
772 options |= _meshType;
773
774 objectOptions_[currentGroup_] = options;
775 }
776
777}
778
779//-----------------------------------------------------------------------------
780
781bool OBJImporter::isTriangleMesh(int _objectID){
782 return objectOptions_[ _objectID ] & TRIMESH;
783}
784
785//-----------------------------------------------------------------------------
786
787bool OBJImporter::isPolyMesh(int _objectID){
788 return objectOptions_[ _objectID ] & POLYMESH;
789}
790
791//-----------------------------------------------------------------------------
792
793bool OBJImporter::isCurve(int _objectID){
794 return objectOptions_[ _objectID ] & CURVE;
795}
796
797//-----------------------------------------------------------------------------
798
799bool OBJImporter::isSurface(int _objectID){
800 return objectOptions_[ _objectID ] & SURFACE;
801}
802
803bool OBJImporter::isNone(int _objectID) {
804 return objectOptions_[ _objectID ] == NONE;
805}
806
807//-----------------------------------------------------------------------------
808
809bool OBJImporter::hasNormals(int _objectID){
810
811 return objectOptions_[ _objectID ] & NORMALS;
812}
813
814//-----------------------------------------------------------------------------
815
816bool OBJImporter::hasTexture(int _objectID){
817
818 return objectOptions_[ _objectID ] & TEXTURE;
819}
820
821//-----------------------------------------------------------------------------
822
823bool OBJImporter::hasTextureCoords(int _objectID){
824 return objectOptions_[ _objectID ] & TEXCOORDS;
825}
826
827//-----------------------------------------------------------------------------
828
829void OBJImporter::setOption( ObjectOptionsE _option) {
830 objectOptions_[ currentGroup_ ] |= _option;
831}
832
834void OBJImporter::setOption( ObjectOptionsE _option, int _groupId ) {
835 objectOptions_[ _groupId ] |= _option;
836}
837
838//-----------------------------------------------------------------------------
839
841 return vertices_.size();
842}
843
844//-----------------------------------------------------------------------------
845
846unsigned int OBJImporter::n_normals(){
847 return normals_.size();
848}
849
850//-----------------------------------------------------------------------------
851
852unsigned int OBJImporter::n_texCoords(){
853 return texCoords_.size();
854}
855
856//-----------------------------------------------------------------------------
857
859 return groupNames_.size();
860}
861
862//-----------------------------------------------------------------------------
863
865
866 if (groupCount() == 0 || groupCount() <= (unsigned int)_groupId)
867 return NULL;
868
869 if(triMeshes_[_groupId] != NULL) return triMeshes_[_groupId];
870 else if(polyMeshes_[_groupId] != NULL) return polyMeshes_[_groupId];
871#ifdef ENABLE_BSPLINECURVE_SUPPORT
872 else if(bSplineCurves_[_groupId] != NULL) return bSplineCurves_[_groupId];
873#endif
874#ifdef ENABLE_BSPLINESURFACE_SUPPORT
875 else if(bSplineSurfaces_[_groupId] != NULL) return bSplineSurfaces_[_groupId];
876#endif
877
878 return NULL;
879}
880
881//-----------------------------------------------------------------------------
882
884 return materials_;
885}
886
887//-----------------------------------------------------------------------------
888
890 return path_;
891}
892
893//-----------------------------------------------------------------------------
894
895void OBJImporter::setPath(QString _path){
896 path_ = _path;
897}
898
899//-----------------------------------------------------------------------------
900
901void OBJImporter::setObjectOptions(ObjectOptions _options) {
902
903 while((unsigned int)currentGroup_ >= objectOptions_.size()) {
904 objectOptions_.push_back(NONE);
905 }
906
907 objectOptions_[currentGroup_] = _options;
908}
909
910//-----------------------------------------------------------------------------
911
913 return objectOptions_.empty();
914}
915
916//-----------------------------------------------------------------------------
917
918// check if object with given id has given option
919bool OBJImporter::hasOption( unsigned int _id, ObjectOptions _option ){
920
921 if (_id >= objectOptions_.size())
922 return false;
923
924 return objectOptions_[_id] & _option;
925}
926
927//-----------------------------------------------------------------------------
928
929void OBJImporter::setObjectName(int _objectID, QString _name){
930
931 BaseObject* obj = object( _objectID );
932
933 if ( obj != 0 )
934 obj->setName( _name );
935}
936
937//-----------------------------------------------------------------------------
938
939int OBJImporter::addGroup(const QString& _groupName) {
940
941 QString group = _groupName.trimmed();
942 int id = groupId(group);
943 if(id == -1) {
944 groupNames_.push_back(group);
945 vertexMapTri_.push_back(std::map<int,TriMesh::VertexHandle>());
946 vertexMapPoly_.push_back(std::map<int,TriMesh::VertexHandle>());
947 invalidFaces_.push_back(std::vector< OMVHandles >());
948 addedFacesTri_.push_back(std::vector< TriMesh::FaceHandle>());
949
950 triMeshes_.push_back(NULL);
951 polyMeshes_.push_back(NULL);
952#ifdef ENABLE_BSPLINECURVE_SUPPORT
953 bSplineCurves_.push_back(NULL);
954#endif
955#ifdef ENABLE_BSPLINESURFACE_SUPPORT
956 bSplineSurfaces_.push_back(NULL);
957#endif
958 return groupNames_.size() - 1;
959 }
960 return id;
961}
962
963//-----------------------------------------------------------------------------
964
965int OBJImporter::groupId(const QString& _groupName) const {
966
967 for(unsigned int i = 0; i < groupNames_.size(); ++i) {
968 if(groupNames_[i] == _groupName.trimmed()) return i;
969 }
970 return -1;
971}
972
973//-----------------------------------------------------------------------------
974
975const QString OBJImporter::groupName(const int _grpId) const {
976
977 if((unsigned int)_grpId < groupNames_.size()) {
978 return groupNames_[_grpId];
979 }
980 return QString();
981}
982
983//-----------------------------------------------------------------------------
984
985void OBJImporter::setGroupName(const int _grp, const QString& _name) {
986
987 if((unsigned int)_grp >= groupNames_.size()) return;
988
989 groupNames_[_grp] = _name;
990}
991
992//-----------------------------------------------------------------------------
993
994void OBJImporter::setCurrentGroup(const int _current) {
995
996 currentGroup_ = _current;
997}
998
999//-----------------------------------------------------------------------------
1000
1001int OBJImporter::currentGroup() const {
1002
1003 return currentGroup_;
1004}
1005
1006//-----------------------------------------------------------------------------
1007
1009
1010 // Duplicate vertices of non-manifold faces
1011 // and add them as new isolated face
1012 if(invalidFaces_[currentGroup_].empty()) return;
1013
1014 if (isTriangleMesh(currentGroup())) {
1015
1016 // Handle triangle meshes
1017 if ( !currentTriMesh() ) return;
1018
1019 for(std::vector<OMVHandles>::iterator it = invalidFaces_[currentGroup_].begin();
1020 it != invalidFaces_[currentGroup_].end(); ++it) {
1021
1022 OMVHandles& vhandles = *it;
1023
1024 // double vertices
1025 for (unsigned int j = 0; j < vhandles.size(); ++j)
1026 {
1027 TriMesh::Point p = currentTriMesh()->point(vhandles[j]);
1028 vhandles[j] = currentTriMesh()->add_vertex(p);
1029 // DO STORE p, reference may not work since vertex array
1030 // may be relocated after adding a new vertex !
1031
1032 // Mark vertices of failed face as non-manifold
1033 if (currentTriMesh()->has_vertex_status()) {
1034 currentTriMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
1035 }
1036 }
1037
1038 // add face
1039 OpenMesh::SmartFaceHandle fh = currentTriMesh()->add_face(vhandles);
1040
1041 // Mark failed face as non-manifold
1042 if (currentTriMesh()->has_face_status())
1043 currentTriMesh()->status(fh).set_fixed_nonmanifold(true);
1044
1045 // Mark edges of failed face as non-two-manifold
1046 if (currentTriMesh()->has_edge_status()) {
1047 for(auto fe_it : fh.edges()) {
1048 currentTriMesh()->status(fe_it).set_fixed_nonmanifold(true);
1049 }
1050 }
1051 }
1052
1053 } else {
1054
1055 // Handle Polymeshes
1056 if ( !currentPolyMesh() ) return;
1057
1058 for(std::vector<OMVHandles>::iterator it = invalidFaces_[currentGroup_].begin();
1059 it != invalidFaces_[currentGroup_].end(); ++it) {
1060
1061 OMVHandles& vhandles = *it;
1062
1063 // double vertices
1064 for (unsigned int j = 0; j < vhandles.size(); ++j)
1065 {
1066 PolyMesh::Point p = currentPolyMesh()->point(vhandles[j]);
1067 vhandles[j] = currentPolyMesh()->add_vertex(p);
1068 // DO STORE p, reference may not work since vertex array
1069 // may be relocated after adding a new vertex !
1070
1071 // Mark vertices of failed face as non-manifold
1072 if (currentPolyMesh()->has_vertex_status()) {
1073 currentPolyMesh()->status(vhandles[j]).set_fixed_nonmanifold(true);
1074 }
1075 }
1076
1077 // add face
1078 OpenMesh::SmartFaceHandle fh = currentPolyMesh()->add_face(vhandles);
1079
1080 // Mark failed face as non-manifold
1081 if (currentPolyMesh()->has_face_status())
1082 currentPolyMesh()->status(fh).set_fixed_nonmanifold(true);
1083
1084 // Mark edges of failed face as non-two-manifold
1085 if (currentPolyMesh()->has_edge_status()) {
1086 for(auto fe_it : fh.edges()) {
1087 currentPolyMesh()->status(fe_it).set_fixed_nonmanifold(true);
1088 }
1089 }
1090 }
1091 }
1092
1093 // Clear faces
1094 invalidFaces_[currentGroup_].clear();
1095}
1096
1097//-----------------------------------------------------------------------------
1098
1099#ifdef ENABLE_BSPLINECURVE_SUPPORT
1100void OBJImporter::setCurveGroupId(const unsigned int _count, const int _id) {
1101 curvesMap_[_count] = _id;
1102}
1103#endif
1104
1105//-----------------------------------------------------------------------------
1106
1107#ifdef ENABLE_BSPLINECURVE_SUPPORT
1108int OBJImporter::getCurveGroupId(const unsigned int _count) {
1109 return curvesMap_[_count];
1110}
1111#endif
1112
1113//-----------------------------------------------------------------------------
1114
1115#ifdef ENABLE_BSPLINECURVE_SUPPORT
1116void OBJImporter::setCurveParentId(const int _curveGroup, const int _parentGroup) {
1117 curveParentGroupMap_[_curveGroup] = _parentGroup;
1118}
1119#endif
1120
1121//-----------------------------------------------------------------------------
1122
1123#ifdef ENABLE_BSPLINECURVE_SUPPORT
1124int OBJImporter::getCurveParentId(const int _curveGroup) {
1125 return curveParentGroupMap_[_curveGroup];
1126}
1127#endif
1128
1129//-----------------------------------------------------------------------------
1130
1131#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1132void OBJImporter::setSurfaceGroupId(const unsigned int _count, const int _id) {
1133 surfacesMap_[_count] = _id;
1134}
1135#endif
1136
1137//-----------------------------------------------------------------------------
1138
1139#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1140int OBJImporter::getSurfaceGroupId(const unsigned int _count) {
1141 return surfacesMap_[_count];
1142}
1143#endif
1144
1145//-----------------------------------------------------------------------------
1146
1147#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1148void OBJImporter::setSurfaceParentId(const int _surfaceGroup, const int _parentGroup) {
1149 surfaceParentGroupMap_[_surfaceGroup] = _parentGroup;
1150}
1151#endif
1152
1153//-----------------------------------------------------------------------------
1154
1155#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1156int OBJImporter::getSurfaceParentId(const int _surfaceGroup) {
1157 return surfaceParentGroupMap_[_surfaceGroup];
1158}
1159#endif
1160
1161//-----------------------------------------------------------------------------
1162
1163//used materials
1164const std::vector<std::string> OBJImporter::usedMaterials(unsigned int _objectID){
1165
1166 if (_objectID >= usedMaterials_.size())
1167 return std::vector<std::string>();
1168 else
1169 return usedMaterials_[ _objectID ];
1170}
1171
1172//-----------------------------------------------------------------------------
1173
1174void OBJImporter::useMaterial( std::string _materialName ){
1175
1176 while( (int)usedMaterials_.size() - 1 < currentGroup() )
1177 usedMaterials_.push_back( std::vector<std::string>() );
1178
1179 //check that it is not added already
1180 for (unsigned int i=0; i < usedMaterials_[ currentGroup() ].size(); i++ )
1181 if ( usedMaterials_[ currentGroup() ][i] == _materialName )
1182 return;
1183
1184 usedMaterials_[ currentGroup() ].push_back( _materialName );
1185
1186 objectOptions_[ currentGroup() ] |= TEXTURE;
1187
1188}
1189
1191void OBJImporter::useVertex(int _vertex_index){
1192
1193 while(currentGroup_ >= (int)usedVertices_.size()) {
1194 usedVertices_.push_back(std::map<int,VertexHandle>());
1195 }
1196
1197 usedVertices_[currentGroup_].insert(std::pair<int,VertexHandle>(_vertex_index,-1));
1198
1199// while( (int)usedVertices_.size() - 1 < (int) objectOptions_.size() )
1200// usedVertices_.push_back( std::set<VertexHandle>() );
1201//
1202// usedVertices_[ objectOptions_.size() ].insert( _vertex );
1203}
1204
1205//-----------------------------------------------------------------------------
1206
void set_diffuse_color(const Vec4f &_d)
set the diffuse color.
void set_specular_color(const Vec4f &_s)
set the specular color
void set_refractive(bool _r)
set refractive flag
void set_indexOfRefraction(double _m)
set index of refraction
void set_ambient_color(const Vec4f &_a)
set the ambient color.
void set_emission(const Vec4f &_c)
set emission ( same as set_base_color(const Vec4f& _c) )
void set_shininess(float _s)
set shininess
MaterialNode * materialNode()
get a pointer to the materialnode
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:721
int id() const
Definition: BaseObject.cc:188
unsigned int groupCount()
Number of groups currently stored in the importer.
Definition: OBJImporter.cc:858
Vec3d vertex(unsigned int _index)
get vertex with given index
Definition: OBJImporter.cc:64
void addMaterial(std::string _materialName)
Add a material.
Definition: OBJImporter.cc:561
void setDegreeV(int _degree)
set degree V direction
Definition: OBJImporter.cc:100
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
Definition: OBJImporter.cc:258
unsigned int n_vertices()
Global Properties.
Definition: OBJImporter.cc:840
void useVertex(int _vertex_index)
used vertices
void setObjectOptions(ObjectOptions _options)
Definition: OBJImporter.cc:901
void addUsedVertices(int _groupId)
add all vertices that are used to the mesh (in correct order)
Definition: OBJImporter.cc:205
void addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
Definition: OBJImporter.cc:464
int addTexCoord(const Vec2f &_coord)
add texture coordinates
Definition: OBJImporter.cc:75
VertexHandle addVertex(const Vec3d &_point)
add a vertex with coordinate _point
Definition: OBJImporter.cc:57
int degreeU()
get current degree
Definition: OBJImporter.cc:108
void setDegreeU(int _degree)
set degree
Definition: OBJImporter.cc:93
bool noOptions()
Return true if the importer has no options stored.
Definition: OBJImporter.cc:912
QString path()
Path of the OBJ file.
Definition: OBJImporter.cc:889
void forceMeshType(ObjectOptions _meshType)
force all meshes to be opened with specific type
Definition: OBJImporter.cc:759
int addNormal(const Vec3d &_normal)
add a normal
Definition: OBJImporter.cc:84
void setNormal(int _index, int _normalID)
set vertex normal
Definition: OBJImporter.cc:303
bool hasOption(unsigned int _id, ObjectOptions _option)
check if object with given id has given option
Definition: OBJImporter.cc:919
BaseObject * object(int _groupId)
return object for the given group
Definition: OBJImporter.cc:864
void setObjectName(int _objectID, QString _name)
change the name of an object
Definition: OBJImporter.cc:929
TriMesh * currentTriMesh()
get a pointer to the active triMesh
Definition: OBJImporter.cc:175
void setOption(ObjectOptionsE _option)
Set Object Option.
Definition: OBJImporter.cc:829
void setObject(BaseObject *_object, int _groupId)
add an object
Definition: OBJImporter.cc:122
MaterialList & materials()
return all loaded materials
Definition: OBJImporter.cc:883
int degreeV()
get current degree
Definition: OBJImporter.cc:115
const std::vector< std::string > usedMaterials(unsigned int _objectID)
used materials
bool hasNormals(int _objectID)
Query Object Options.
Definition: OBJImporter.cc:809
int currentGroup()
Get the id of the current group.
Definition: OBJImporter.cc:159
PolyMesh * currentPolyMesh()
get a pointer to the active polyMesh
Definition: OBJImporter.cc:167
~OBJImporter()
base class needs virtual destructor
Definition: OBJImporter.cc:50
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:114
Kernel::TexCoord2D TexCoord2D
TexCoord2D type.
Definition: PolyMeshT.hh:120
SmartVertexHandle add_vertex(const Point _p)
Definition: PolyMeshT.hh:255
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:139
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
Kernel::Color Color
Color type.
Definition: PolyMeshT.hh:116
BSplineSurfaceObject * bsplineSurfaceObject(BaseObjectData *_object)
Cast an BaseObject to a BSplineSurfaceObject if possible.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
BSplineCurveObject * bsplineCurveObject(BaseObjectData *_object)
Cast an BaseObject to a BSplineCurveObject if possible.
BaseObjectData * baseObjectData(BaseObject *_object)
Cast an BaseObject to a BaseObjectData if possible.
Handle for a face entity.
Definition: Handles.hh:142
PolyConnectivity::ConstFaceEdgeRange edges() const
Returns a range of edges of the face (PolyConnectivity::fv_range())
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const
Returns a range of halfedges of the face (PolyConnectivity::fh_range())