LCOV - code coverage report
Current view: top level - ugbase/lib_grid/file_io - file_io_obj.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 136 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 4 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <fstream>
      34              : #include <vector>
      35              : #include <cstring>
      36              : #include <string>
      37              : #include "file_io_obj.h"
      38              : #include "../lg_base.h"
      39              : #include "common/util/loader/loader_obj.h"
      40              : #include "common/error.h"
      41              : 
      42              : using namespace std;
      43              : 
      44              : namespace ug
      45              : {
      46              : //TODO: disable automatic triangulation. create edges. create quads.
      47              : ////////////////////////////////////////////////////////////////////////
      48              : //      LoadGridFromOBJ
      49              : ///     Loads a file from a wavefront '.obj' file. Fills optional subset-infos.
      50            0 : bool LoadGridFromOBJ(Grid& grid, const char* filename, AVector3& aPos,
      51              :                 AVector2* paTexCoord,
      52              :                 ISubsetHandler* pSubsetHandler,
      53              :                 std::vector<OBJMaterial>* pvMaterials)
      54              : {
      55              :         LoaderObj loader;
      56              : 
      57            0 :         if(!loader.load_file(filename, false))
      58              :                 return false;
      59              : 
      60            0 :         if(loader.num_points() == 0)
      61              :                 return false;
      62              : 
      63              : //      attach data and attachment accessors
      64            0 :         if(!grid.has_vertex_attachment(aPos))
      65            0 :                 grid.attach_to_vertices(aPos);
      66              :         Grid::VertexAttachmentAccessor<AVector3> aaPosVRT(grid, aPos);
      67              : 
      68              : //      create vertices and assign position data.
      69              : //      Store pointers in a vector so that they can be accessed by index.
      70              :         vector<RegularVertex*> vVertices;
      71            0 :         vVertices.reserve(loader.num_points());
      72              :         {
      73            0 :                 for(uint i = 0; i < (uint)loader.num_points(); ++i)
      74              :                 {
      75            0 :                         RegularVertex* pVrt = *grid.create<RegularVertex>();
      76            0 :                         vVertices.push_back(pVrt);
      77            0 :                         aaPosVRT[pVrt] = *loader.point(i);
      78              :                 }
      79              :         //      if a subset handler was specified, we'll push all vertices into subset 0
      80            0 :                 if(pSubsetHandler){
      81              :                         pSubsetHandler->assign_subset(grid.begin<RegularVertex>(), grid.end<RegularVertex>(), 0);
      82              :                 }
      83              :         }
      84              : 
      85              : //      iterate through the objects in loader and add edges and faces to grid.
      86              : //      assign subsets and material indices at the same time.
      87              :         {
      88              :                 int objCounter = 0;
      89            0 :                 for(LoaderObj::ObjectIterator oIter = loader.objects_begin();
      90            0 :                         oIter != loader.objects_end(); ++oIter, ++objCounter)
      91              :                 {
      92            0 :                         LoaderObj::Object& obj = *(*oIter);
      93              :                 //      set the subset-info of this object - if requested.
      94            0 :                         if(pSubsetHandler != NULL)
      95              :                         {
      96            0 :                                 SubsetInfo si = pSubsetHandler->subset_info(objCounter);
      97            0 :                                 si.materialIndex = obj.m_iMaterialIndex;
      98            0 :                                 si.name = obj.m_strName;
      99              : 
     100            0 :                                 pSubsetHandler->set_subset_info(objCounter, si);
     101              :                         }
     102              : 
     103              :                 //      create edges and faces.
     104              :                 //      creation differs if a subset handler is supplied.
     105            0 :                         if(pSubsetHandler == NULL)
     106              :                         {
     107              :                         //      create edges
     108            0 :                                 for(size_t i = 0; i < obj.m_vEdgeList.size(); i+=2){
     109            0 :                                         for(size_t j = i; j < i+2; ++j){
     110            0 :                                                 if(obj.m_vEdgeList[j] < 0 || obj.m_vEdgeList[j] >= (int)vVertices.size()){
     111            0 :                                                         UG_THROW("Bad vertex index in edge " << i / 2 << ": " << obj.m_vEdgeList[i] + 1);
     112              :                                                 }
     113              :                                         }
     114            0 :                                         grid.create<RegularEdge>(EdgeDescriptor(vVertices[obj.m_vEdgeList[i]],
     115            0 :                                                                                                         vVertices[obj.m_vEdgeList[i+1]]));
     116              :                                 }
     117              :                         //      create triangles
     118            0 :                                 for(size_t i = 0; i < obj.m_vTriangleList.size(); i+=3){
     119            0 :                                         for(size_t j = i; j < i+3; ++j){
     120            0 :                                                 if(obj.m_vTriangleList[j] < 0 || obj.m_vTriangleList[j] >= (int)vVertices.size()){
     121            0 :                                                         UG_THROW("Bad vertex index in triangle " << i / 3 << ": " << obj.m_vTriangleList[i] + 1);
     122              :                                                 }
     123              :                                         }
     124            0 :                                         grid.create<Triangle>(TriangleDescriptor(vVertices[obj.m_vTriangleList[i]],
     125            0 :                                                                                 vVertices[obj.m_vTriangleList[i+1]], vVertices[obj.m_vTriangleList[i+2]]));
     126              :                                 }
     127              : 
     128              :                         //      create quads
     129            0 :                                 for(size_t i = 0; i < obj.m_vQuadList.size(); i+=4){
     130            0 :                                         for(size_t j = i; j < i+4; ++j){
     131            0 :                                                 if(obj.m_vQuadList[j] < 0 || obj.m_vQuadList[j] >= (int)vVertices.size()){
     132            0 :                                                         UG_THROW("Bad vertex index in quadrilateral " << i / 4 << ": " << obj.m_vQuadList[i] + 1);
     133              :                                                 }
     134              :                                         }
     135            0 :                                         grid.create<Quadrilateral>(QuadrilateralDescriptor(vVertices[obj.m_vQuadList[i]],
     136            0 :                                                                                 vVertices[obj.m_vQuadList[i+1]], vVertices[obj.m_vQuadList[i+2]],
     137            0 :                                                                                 vVertices[obj.m_vQuadList[i+3]]));
     138              :                                 }
     139              :                         }
     140              :                         else
     141              :                         {
     142              :                         //      create edges
     143            0 :                                 for(size_t i = 0; i < obj.m_vEdgeList.size(); i+=2)
     144              :                                 {
     145            0 :                                         for(size_t j = i; j < i+2; ++j){
     146            0 :                                                 if(obj.m_vEdgeList[j] < 0 || obj.m_vEdgeList[j] >= (int)vVertices.size()){
     147            0 :                                                         UG_THROW("Bad vertex index in edge " << i / 2 << ": " << obj.m_vEdgeList[i] + 1);
     148              :                                                 }
     149              :                                         }
     150            0 :                                         RegularEdge* e = *grid.create<RegularEdge>(EdgeDescriptor(vVertices[obj.m_vEdgeList[i]],
     151            0 :                                                                                                         vVertices[obj.m_vEdgeList[i+1]]));
     152            0 :                                         pSubsetHandler->assign_subset(e, objCounter);
     153              :                                 }
     154              : 
     155              :                         //      create triangles
     156            0 :                                 for(size_t i = 0; i < obj.m_vTriangleList.size(); i+=3)
     157              :                                 {
     158            0 :                                         for(size_t j = i; j < i+3; ++j){
     159            0 :                                                 if(obj.m_vTriangleList[j] < 0 || obj.m_vTriangleList[j] >= (int)vVertices.size()){
     160            0 :                                                         UG_THROW("Bad vertex index in triangle " << i / 3 << ": " << obj.m_vTriangleList[i] + 1);
     161              :                                                 }
     162              :                                         }
     163            0 :                                         Triangle* tri = *grid.create<Triangle>(TriangleDescriptor(vVertices[obj.m_vTriangleList[i]],
     164            0 :                                                                                 vVertices[obj.m_vTriangleList[i+1]], vVertices[obj.m_vTriangleList[i+2]]));
     165            0 :                                         pSubsetHandler->assign_subset(tri, objCounter);
     166              :                                 }
     167              : 
     168              :                         //      create quads
     169            0 :                                 for(size_t i = 0; i < obj.m_vQuadList.size(); i+=4)
     170              :                                 {
     171            0 :                                         for(size_t j = i; j < i+4; ++j){
     172            0 :                                                 if(obj.m_vQuadList[j] < 0 || obj.m_vQuadList[j] >= (int)vVertices.size()){
     173            0 :                                                         UG_THROW("Bad vertex index in quadrilateral " << i / 4 << ": " << obj.m_vQuadList[i] + 1);
     174              :                                                 }
     175              :                                         }
     176            0 :                                         Quadrilateral* q = *grid.create<Quadrilateral>(QuadrilateralDescriptor(vVertices[obj.m_vQuadList[i]],
     177            0 :                                                                                 vVertices[obj.m_vQuadList[i+1]], vVertices[obj.m_vQuadList[i+2]],
     178            0 :                                                                                 vVertices[obj.m_vQuadList[i+3]]));
     179            0 :                                         pSubsetHandler->assign_subset(q, objCounter);
     180              :                                 }
     181              :                         }
     182              : 
     183              :                 //      assign texture coords if the corresponding attachment is supplied
     184            0 :                         if(paTexCoord != NULL)
     185              :                         {
     186              :                         //      since you can specify texture coords for each face from the .obj specification,
     187              :                         //      and since libGrid only supports one texture coord per vertex, we reduce
     188              :                         //      the supplied information.
     189              :                                 Grid::VertexAttachmentAccessor<AVector2> aaTexVRT(grid, *paTexCoord);
     190            0 :                                 for(int i= 0; i < (int)obj.m_vTriangleListTex.size(); ++i)
     191            0 :                                         aaTexVRT[vVertices[i]] = *loader.uv(obj.m_vTriangleListTex[i]);
     192              :                         }
     193              :                 }
     194              :         }
     195              : 
     196              : //      copy materials to pvMaterials - if supplied
     197            0 :         if(pvMaterials != NULL)
     198              :         {
     199            0 :                 pvMaterials->resize(loader.num_materials());
     200            0 :                 for(int i = 0; i < loader.num_materials(); ++i)
     201              :                 {
     202              :                         const LoaderObj::Material& mat = loader.get_material(i);
     203            0 :                         (*pvMaterials)[i].m_strName = mat.m_strName;
     204            0 :                         (*pvMaterials)[i].m_strTextureDiffuse = mat.m_strTextureDiffuse;
     205              :                         (*pvMaterials)[i].m_vDiffuse = mat.m_vDiffuse;
     206            0 :                         (*pvMaterials)[i].m_fAlpha = mat.m_fAlpha;
     207              :                 }
     208              :         }
     209              : 
     210              :         return true;
     211            0 : }
     212              : 
     213              : 
     214            0 : static void WriteEdges(ofstream& out, EdgeIterator edgesBegin, EdgeIterator edgesEnd,
     215              :                                                 int indexDimension, Grid::VertexAttachmentAccessor<AInt>& aaInt)
     216              : {
     217            0 :         while(edgesBegin != edgesEnd)
     218              :         {
     219              :                 Edge* e = *edgesBegin;
     220            0 :                 out << "f";
     221            0 :                 for(uint i = 0; i < 2; ++i)
     222              :                 {
     223            0 :                         out << " " << aaInt[e->vertex(i)];
     224            0 :                         for(int j = 1; j < indexDimension; ++j)
     225            0 :                                 out << '/' << aaInt[e->vertex(i)];
     226              :                 }
     227              :                 ++edgesBegin;
     228              :                 out << endl;
     229              :         }
     230            0 : }
     231              : 
     232            0 : static void WriteFaces(ofstream& out, FaceIterator facesBegin, FaceIterator facesEnd,
     233              :                                                 int indexDimension, Grid::VertexAttachmentAccessor<AInt>& aaInt)
     234              : {
     235            0 :         while(facesBegin != facesEnd)
     236              :         {
     237              :                 Face* f = *facesBegin;
     238            0 :                 out << "f";
     239            0 :                 for(uint i = 0; i < f->num_vertices(); ++i)
     240              :                 {
     241            0 :                         out << " " << aaInt[f->vertex(i)];
     242            0 :                         for(int j = 1; j < indexDimension; ++j)
     243            0 :                                 out << '/' << aaInt[f->vertex(i)];
     244              :                 }
     245              :                 ++facesBegin;
     246              :                 out << endl;
     247              :         }
     248            0 : }
     249              : 
     250            0 : bool SaveGridToOBJ(Grid& grid, const char* filename, AVector3& aPos,
     251              :                 AVector2* paTexCoord,
     252              :                 ISubsetHandler* pSubsetHandler,
     253              :                 std::vector<OBJMaterial>* pvMaterials)
     254              : {
     255              : //      check whether the grid has vertex-position data. If not, return false
     256            0 :         if(!grid.has_vertex_attachment(aPos)){
     257              :                 UG_LOG("ERROR in SaveGridToOBJ: Position attachment missing.\n");
     258            0 :                 return false;
     259              :         }
     260              : 
     261              :         string mtrlFullFilename;
     262              :         string mtrlFilename;
     263              : 
     264              : //      check if there are materials
     265            0 :         if(pvMaterials)
     266              :         {
     267              :         //      we have to construct the material-file name.
     268              :                 mtrlFullFilename = filename;
     269            0 :                 if(mtrlFullFilename.at(mtrlFullFilename.size() - 4) == '.')
     270            0 :                         mtrlFullFilename.erase(mtrlFullFilename.size() - 4, 4);
     271            0 :                 mtrlFullFilename.append(".mtl");
     272              : 
     273              :         //      extract the name of the file and store it in mtrlFilename
     274              :                 string::size_type ind1, ind2;
     275            0 :                 ind1 = mtrlFullFilename.find_last_of('\\');
     276            0 :                 ind2 = mtrlFullFilename.find_last_of('/');
     277            0 :                 if(ind1 == string::npos)
     278            0 :                         ind1 = ind2;
     279            0 :                 else if(ind2 != string::npos)
     280            0 :                         ind1 = max(ind1, ind2);
     281              : 
     282              :         //      assign the filename
     283            0 :                 if(ind1 == string::npos)
     284              :                         mtrlFilename = mtrlFullFilename;
     285              :                 else
     286            0 :                         mtrlFilename.assign(mtrlFullFilename, ind1, mtrlFullFilename.size() - ind1);
     287              :         }
     288              : 
     289              : //      write the .obj file
     290              :         {
     291            0 :                 ofstream out(filename);
     292              : 
     293              :         //      write the header
     294              :                 out << "# exported from libGrid" << endl;
     295              : 
     296              :         //      write material file
     297            0 :                 if(pvMaterials)
     298              :                         out << "mtllib " << mtrlFilename << endl;
     299              : 
     300              :                 int indexDimension = 1;
     301              : 
     302              :         //      store indices in the vertices
     303              :                 AInt aInt;
     304              :                 grid.attach_to_vertices(aInt);
     305              :                 Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt);
     306              : 
     307              :         //      write vertex data
     308              :                 {
     309              :                         int counter = 1;
     310              :                         Grid::VertexAttachmentAccessor<AVector3> aaPos(grid, aPos);
     311            0 :                         for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); ++iter, ++counter)
     312              :                         {
     313            0 :                                 out << "v " << aaPos[*iter].x() << " " << aaPos[*iter].y() << " " <<
     314            0 :                                                                 aaPos[*iter].z() << endl;
     315            0 :                                 aaInt[*iter] = counter;
     316              :                         }
     317              :                 }
     318              : 
     319              :         //      if texture data is supplied we have to write it too
     320            0 :                 if(paTexCoord != NULL)
     321              :                 {
     322              :                         indexDimension++;
     323              :                         Grid::VertexAttachmentAccessor<AVector2> aaTex(grid, *paTexCoord);
     324            0 :                         for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); ++iter)
     325              :                         {
     326            0 :                                 out << "vt " << aaTex[*iter].x() << " " <<
     327            0 :                                                                 aaTex[*iter].y() << " 0.0" << endl;
     328              :                         }
     329              :                 }
     330              : 
     331              :         //      if a subset handler is supplied, we'll export each subset as a separate object.
     332            0 :                 if(pSubsetHandler)
     333              :                 {
     334            0 :                         for(int i = 0; i < pSubsetHandler->num_subsets(); ++i)
     335              :                         {
     336              :                         //      write object
     337            0 :                                 if(pSubsetHandler->subset_info(i).name.size() > 0)
     338            0 :                                         out << "o " << pSubsetHandler->subset_info(i).name << endl;
     339              :                                 else
     340            0 :                                         out << "o " << "sub_" << i << endl;
     341              : 
     342              :                         //      write material reference
     343            0 :                                 if((pvMaterials != NULL) && (pSubsetHandler->subset_info(i).materialIndex != -1))
     344            0 :                                         out << "usemtl " << (*pvMaterials)[pSubsetHandler->subset_info(i).materialIndex].m_strName << endl;
     345              :                                 else
     346              :                                         out << "usemtl (null)" << endl;
     347              : 
     348              :                         //      get the goc
     349              :                                 GridObjectCollection goc = pSubsetHandler->
     350            0 :                                                 get_grid_objects_in_subset(i);
     351              : 
     352            0 :                                 for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){
     353              :                                 //      write the edges of this subset
     354            0 :                                         WriteEdges(out, goc.begin<Edge>(lvl),
     355            0 :                                                                 goc.end<Edge>(lvl), indexDimension, aaInt);
     356              : 
     357              :                                 //      write the faces of this subset
     358            0 :                                         WriteFaces(out, goc.begin<Face>(lvl), goc.end<Face>(lvl),
     359              :                                                            indexDimension, aaInt);
     360              :                                 }
     361              :                         }
     362              :                 }
     363              :                 else
     364              :                 {
     365              :                 //      since no subset handler was supplied, we'll treat the whole grid as on object.
     366              :                         out << "o nonameknown" << endl;
     367              :                         out << "usemtl (null)" << endl;
     368              :                 //      write the edges
     369            0 :                         WriteEdges(out, grid.edges_begin(), grid.edges_end(), indexDimension, aaInt);
     370              : 
     371              :                 //      write the faces
     372            0 :                         WriteFaces(out, grid.faces_begin(), grid.faces_end(), indexDimension, aaInt);
     373              :                 }
     374              : 
     375              :         //      clean up
     376              :                 grid.detach_from_vertices(aInt);
     377              :         //      .obj done
     378            0 :                 out.close();
     379            0 :         }
     380              : 
     381              : //      write the material file
     382            0 :         if(pvMaterials)
     383              :         {
     384            0 :                 ofstream out(mtrlFullFilename.c_str());
     385              :                 out << "# exported from libMesh" << endl;
     386              :                 out << "# Material Count: " << pvMaterials->size() << endl;
     387              : 
     388            0 :                 for(uint i = 0; i < pvMaterials->size(); ++i)
     389              :                 {
     390              :                         vector4& vD = (*pvMaterials)[i].m_vDiffuse;
     391              :                         out << "newmtl " << (*pvMaterials)[i].m_strName << endl;
     392            0 :                         out << "Kd " << vD.x() << " " << vD.y() << " " << vD.z() << endl;
     393            0 :                         out << "d " << vD.w() << endl;
     394            0 :                         if((*pvMaterials)[i].m_strTextureDiffuse.size() > 0)
     395              :                                 out << "map_Kd " << (*pvMaterials)[i].m_strTextureDiffuse << endl;
     396              :                 }
     397              : 
     398              :         //      done
     399            0 :                 out.close();
     400            0 :         }
     401              : 
     402              :         return true;
     403              : }
     404              : 
     405              : }//     end of namespace
        

Generated by: LCOV version 2.0-1