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