VisualModelImpl.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/visualmodel/VisualModelImpl.h>
00026 
00027 #include <sofa/component/topology/TriangleSetTopologyModifier.h>
00028 #include <sofa/component/topology/QuadSetTopologyModifier.h>
00029 #include <sofa/component/topology/TetrahedronSetTopologyModifier.h>
00030 #include <sofa/component/topology/HexahedronSetTopologyModifier.h>
00031 
00032 #include <sofa/component/topology/PointSetTopologyChange.h>
00033 #include <sofa/component/topology/TriangleSetTopologyChange.h>
00034 #include <sofa/component/topology/QuadSetTopologyChange.h>
00035 #include <sofa/component/topology/TetrahedronSetTopologyChange.h>
00036 #include <sofa/component/topology/HexahedronSetTopologyChange.h>
00037 
00038 #include <sofa/component/topology/SparseGridTopology.h>
00039 
00040 #include <sofa/helper/system/FileRepository.h>
00041 #include <sofa/helper/gl/RAII.h>
00042 #include <sofa/helper/vector.h>
00043 #include <sofa/defaulttype/Quat.h>
00044 #include <sofa/core/ObjectFactory.h>
00045 #include <sofa/helper/io/Mesh.h>
00046 #include <sofa/helper/rmath.h>
00047 #include <sstream>
00048 
00049 #include <map>
00050 
00051 namespace sofa
00052 {
00053 
00054 namespace component
00055 {
00056 
00057 namespace visualmodel
00058 {
00059 
00060 using namespace sofa::defaulttype;
00061 using namespace sofa::core::componentmodel::topology;
00062 
00063 void VisualModelImpl::parse(core::objectmodel::BaseObjectDescription* arg)
00064 {
00065     this->core::VisualModel::parse(arg);
00066     VisualModelImpl* obj = this;
00067 
00068     if (arg->getAttribute("normals")!=NULL)
00069       obj->setUseNormals(atoi(arg->getAttribute("normals"))!=0);
00070 
00071     if (arg->getAttribute("castshadow")!=NULL)
00072         obj->setCastShadow(atoi(arg->getAttribute("castshadow"))!=0);
00073 
00074     std::string loader = arg->getAttribute("loader","");
00075 
00076      std::string file;
00077      file=(arg->getAttribute("texturename",""));
00078      if (!file.empty())
00079      {
00080           texturename.setValue( sofa::helper::system::DataRepository.getFile ( file ));
00081      }
00082  
00083      file=(arg->getAttribute("filename",""));
00085      //if (!file.empty() && sofa::helper::system::DataRepository.findFile (file))
00086      //{
00087        filename.setValue( sofa::helper::system::DataRepository.getFile ( file ));
00088      //}
00089 
00090 
00091     if (arg->getAttribute("flip")!=NULL) {
00092         obj->flipFaces();
00093     }
00094     if (arg->getAttribute("color")) {
00095         obj->setColor(arg->getAttribute("color"));
00096     }
00097     scaleTex= 1.0f;
00098     if (arg->getAttribute("scaleTex")!=NULL) {
00099         //obj->applyUVScale(atof(arg->getAttribute("scaleTex","1.0")), atof(arg->getAttribute("scaleTex","1.0")));
00100         scaleTex=(float)(atof(arg->getAttribute("scaleTex","1.0")));
00101         obj->applyUVScale(scaleTex, scaleTex);
00102     }
00103     if (arg->getAttribute("du")!=NULL || arg->getAttribute("dv")!=NULL) {    
00104         obj->applyUVTranslation(atof(arg->getAttribute("du","0.0")), atof(arg->getAttribute("dv","0.0")));   
00105     }
00106 
00107 
00108 //       if (arg->getAttribute("scale")!=NULL) {
00109 //  scale.setValue(atof(arg->getAttribute("scale","1.0")));
00110 //       }
00111     if (arg->getAttribute("rx")!=NULL || arg->getAttribute("ry")!=NULL || arg->getAttribute("rz")!=NULL) {
00112     rotation.setValue(Vector3((SReal)(atof(arg->getAttribute("rx","0.0"))),(SReal)(atof(arg->getAttribute("ry","0.0"))),(SReal)(atof(arg->getAttribute("rz","0.0")))));
00113     }    
00114     
00115      if (arg->getAttribute("dx")!=NULL || arg->getAttribute("dy")!=NULL || arg->getAttribute("dz")!=NULL) {
00116     translation.setValue(Vector3((SReal)atof(arg->getAttribute("dx","0.0")), (SReal)atof(arg->getAttribute("dy","0.0")), (SReal)atof(arg->getAttribute("dz","0.0"))));
00117      }
00118 }
00119 
00120   SOFA_DECL_CLASS(VisualModelImpl)
00121 
00122   int VisualModelImplClass = core::RegisterObject("Generic visual model. If a viewer is active it will replace the VisualModel alias, otherwise nothing will be displayed.")
00123   .add< VisualModelImpl >()
00124   .addAlias("VisualModel")
00125   ;
00126   
00127 VisualModelImpl::VisualModelImpl() //const std::string &name, std::string filename, std::string loader, std::string textureName)
00128   :  useTopology(false), lastMeshRev(-1), useNormals(true), castShadow(true), 
00129 
00130      field_vertices    (initDataPtr(&field_vertices,&vertices,  "position",   "vertices of the model") ), 
00131      field_vnormals    (initDataPtr(&field_vnormals, &vnormals, "normals",   "normals of the model") ), 
00132      field_vtexcoords  (initDataPtr(&field_vtexcoords, &vtexcoords, "texcoords",  "coordinates of the texture") ), 
00133      field_triangles   (initDataPtr(&field_triangles, &triangles,"triangles" ,  "triangles of the model") ), 
00134      field_quads       (initDataPtr(&field_quads, &quads,   "quads",    "quads of the model") ), 
00135      filename          (initData   (&filename,    "filename","Path to the model", false)),
00136      texturename       (initData                            (&texturename, "texturename","Name of the Texture")),
00137      translation       (initData   (&translation, Vector3(), "translation", "Initial Translation of the object")),
00138      rotation          (initData   (&rotation, Vector3(), "rotation", "Initial Rotation of the object")),
00139      scale             (initData   (&scale, (SReal)(1.0), "scale", "Initial Scale of the object")),
00140      material(initData(&material,"material","Material")) //, tex(NULL)
00141 {
00142   inputVertices = &vertices;
00143 }
00144 
00145 VisualModelImpl::~VisualModelImpl()
00146 {
00147     if (inputVertices != &vertices) delete inputVertices;
00148 }
00149 
00150 bool VisualModelImpl::isTransparent()
00151 {
00152   return (material.getValue().useDiffuse && material.getValue().diffuse[3] < 1.0);
00153 }
00154 
00155 void VisualModelImpl::drawVisual()
00156 {
00157     if (!isTransparent())
00158         internalDraw();
00159 }
00160 
00161 void VisualModelImpl::drawTransparent()
00162 {
00163     if (isTransparent())
00164         internalDraw();
00165 }
00166 
00167 void VisualModelImpl::drawShadow()
00168 {
00169     if (!isTransparent() && getCastShadow())
00170     {
00171         //std::cout << "drawShadow for "<<getName()<<std::endl;
00172         internalDraw();
00173     }
00174 }
00175 
00176 void VisualModelImpl::setMesh(helper::io::Mesh &objLoader, bool tex)
00177 {
00178   const vector< vector< vector<int> > > &facetsImport = objLoader.getFacets();
00179   const vector<Vector3> &verticesImport = objLoader.getVertices();
00180   const vector<Vector3> &normalsImport = objLoader.getNormals();
00181   const vector<Vector3> &texCoordsImport = objLoader.getTexCoords();
00182 
00183   const helper::io::Mesh::Material &materialImport = objLoader.getMaterial();
00184 
00185   if (!material.isSet() && materialImport.activated)
00186   {
00187     helper::io::Mesh::Material M;
00188     M = materialImport;
00189     material.setValue(M);
00190   }
00191 
00192 //             std::cout << "Vertices Import size : " << verticesImport.size() << " (" << normalsImport.size() << " normals)." << std::endl;
00193 
00194   int nbVIn = verticesImport.size();
00195             // First we compute for each point how many pair of normal/texcoord indices are used
00196             // The map store the final index of each combinaison
00197   vector< std::map< std::pair<int,int>, int > > vertTexNormMap;
00198   vertTexNormMap.resize(nbVIn);
00199   for (unsigned int i = 0; i < facetsImport.size(); i++)
00200   {
00201     const vector<vector <int> >& vertNormTexIndex = facetsImport[i];
00202     if (vertNormTexIndex[0].size() < 3) continue; // ignore lines
00203     const vector<int>& verts = vertNormTexIndex[0];
00204     const vector<int>& texs = vertNormTexIndex[1];
00205     const vector<int>& norms = vertNormTexIndex[2];
00206     for (unsigned int j = 0; j < verts.size(); j++)
00207     {
00208       vertTexNormMap[verts[j]][std::make_pair((tex?texs[j]:-1), (useNormals?norms[j]:0))] = 0;
00209     }
00210   }
00211 
00212             // Then we can compute how many vertices are created
00213   int nbVOut = 0;
00214   bool vsplit = false;
00215   for (int i = 0; i < nbVIn; i++)
00216   {
00217     int s = vertTexNormMap[i].size();
00218     nbVOut += s;
00219     if (s!=1)
00220       vsplit = true;
00221   }
00222 
00223             // Then we can create the final arrays
00224 
00225   vertices.resize(nbVOut);
00226   vnormals.resize(nbVOut);
00227 
00228   if (tex)
00229     vtexcoords.resize(nbVOut);
00230 
00231   if (vsplit)
00232   {
00233     inputVertices = new ResizableExtVector<Coord>;
00234     inputVertices->resize(nbVIn);
00235     vertPosIdx.resize(nbVOut);
00236     vertNormIdx.resize(nbVOut);
00237   }
00238   else
00239     inputVertices = &vertices;
00240 
00241   int nbNOut = 0; 
00242   for (int i = 0, j = 0; i < nbVIn; i++)
00243   {
00244     if (vsplit)
00245       (*inputVertices)[i] = verticesImport[i];
00246     std::map<int, int> normMap;
00247     for (std::map<std::pair<int, int>, int>::iterator it = vertTexNormMap[i].begin();
00248      it != vertTexNormMap[i].end(); ++it)
00249     {
00250       vertices[j] = verticesImport[i];
00251       int t = it->first.first;
00252       int n = it->first.second;
00253       if ((unsigned)n < normalsImport.size())
00254     vnormals[j] = normalsImport[n];
00255       if ((unsigned)t < texCoordsImport.size())      
00256     vtexcoords[j] = texCoordsImport[t];
00257       
00258       if (vsplit)
00259       {
00260     vertPosIdx[j] = i;
00261     if (normMap.count(n))
00262       vertNormIdx[j] = normMap[n];
00263     else
00264       vertNormIdx[j] = normMap[n] = nbNOut++;
00265       }
00266       it->second = j++;
00267     }
00268   }
00269   if (!vsplit) nbNOut = nbVOut;
00270   else if (nbNOut == nbVOut) vertNormIdx.resize(0);
00271 
00272 //             std::cout << "Vertices Export size : " << nbVOut << " (" << nbNOut << " normals)." << std::endl;
00273 
00274 //             std::cout << "Facets Import size : " << facetsImport.size() << std::endl;
00275 
00276             // Then we create the triangles and quads
00277 
00278   for (unsigned int i = 0; i < facetsImport.size(); i++)
00279   {
00280     const vector<vector <int> >& vertNormTexIndex = facetsImport[i];
00281     if (vertNormTexIndex[0].size() < 3) continue; // ignore lines
00282     const vector<int>& verts = vertNormTexIndex[0];
00283     const vector<int>& texs = vertNormTexIndex[1];
00284     const vector<int>& norms = vertNormTexIndex[2];
00285     vector<int> idxs;
00286     idxs.resize(verts.size());
00287     for (unsigned int j = 0; j < verts.size(); j++)
00288     {
00289       idxs[j] = vertTexNormMap[verts[j]][std::make_pair((tex?texs[j]:-1), (useNormals?norms[j]:0))];
00290       if ((unsigned)idxs[j] >= (unsigned)nbVOut)
00291       {
00292     std::cerr << "ERROR(VisualModelImpl): index "<<idxs[j]<<" out of range\n";
00293     idxs[j] = 0;
00294       }
00295     }
00296 
00297     if (verts.size() == 4)
00298     { // quad
00299       quads.push_back(helper::make_array(idxs[0],idxs[1],idxs[2],idxs[3]));
00300     }
00301     else
00302     { // triangle(s)
00303       for (unsigned int j = 2; j < verts.size(); j++)
00304       {
00305     triangles.push_back(helper::make_array(idxs[0],idxs[j-1],idxs[j]));                     
00306       }
00307     }
00308   }
00309 
00310 //             std::cout << "Facets Export size : ";
00311 //             if (!triangles.empty())
00312 //                 std::cout << triangles.size() << " triangles";
00313 //             if (!quads.empty())
00314 //                 std::cout << quads.size() << " quads";
00315 //             std::cout << "." << std::endl;
00316 
00317             //for (unsigned int i = 0; i < triangles.size() ; i++)
00318             //    std::cout << "T"<<i<<": "<<triangles[i][0]<<" "<<triangles[i][1]<<" "<<triangles[i][2]<<std::endl;
00319 
00320   computeNormals();
00321   computeBBox();
00322 }
00323 
00324 bool VisualModelImpl::load(const std::string& filename, const std::string& loader, const std::string& textureName)
00325 {
00326     bool tex = !textureName.empty();
00327     if (!textureName.empty() )
00328     {
00329       std::string textureFilename(textureName);
00330       if (sofa::helper::system::DataRepository.findFile (textureFilename))             
00331         tex = loadTexture(textureName);      
00332       else       
00333           logWarning(std::string("Texture \"") + textureName +std::string("\" not found"));       
00334     }
00335     tex = !textureName.empty();
00336     
00337     if (!filename.empty() && vertices.size() == 0)
00338     {
00339       std::string meshFilename(filename);
00340       if (sofa::helper::system::DataRepository.findFile (meshFilename))
00341       {       
00342         //name = filename;
00343         helper::io::Mesh *objLoader;
00344         if (loader.empty())
00345             objLoader = helper::io::Mesh::Create(filename);
00346         else
00347             objLoader = helper::io::Mesh::FactoryMesh::CreateObject(loader, filename);
00348 
00349         if (!objLoader)
00350         {
00351             return false;
00352         }
00353         else
00354         {
00355       setMesh(*objLoader,tex);
00356       //std::cout << "VisualModel::load, vertices.size = "<< vertices.size() <<std::endl;
00357     }
00358       }
00359       else               
00360         logWarning(std::string("Mesh \"") + filename +std::string("\" not found"));       
00361     }
00362     else
00363     {
00364       if (vertices.size() == 0)
00365       {
00366           std::cout << "VisualModel: will use Topology."<<std::endl;
00367           useTopology = true;
00368       }
00369       else  computeBBox();
00370       modified = true;
00371     }
00372     
00373     if (!xformsModified)
00374     {
00375          // add one identity matrix
00376         xforms.resize(1);
00377     }
00378     return true;
00379 }
00380 
00381 void VisualModelImpl::applyTranslation(const double dx, const double dy, const double dz)
00382 {
00383     Vector3 d((GLfloat)dx,(GLfloat)dy,(GLfloat)dz);
00384     VecCoord& x = *getVecX();
00385     for (unsigned int i = 0; i < x.size(); i++)
00386     {
00387         x[i] += d;
00388     }
00389     updateVisual();
00390 }
00391 
00392     //Apply Rotation from Euler angles (in degree!)
00393 void VisualModelImpl::applyRotation (const double rx, const double ry, const double rz)
00394 {
00395     Quaternion q=helper::Quater<SReal>::createQuaterFromEuler( Vec<3,SReal>(rx,ry,rz)*M_PI/180.0);
00396     applyRotation(q);
00397 }       
00398 void VisualModelImpl::applyRotation(const Quat q)
00399 {
00400     VecCoord& x = *getVecX();
00401     for (unsigned int i = 0; i < x.size(); i++)
00402     {
00403         x[i] = q.rotate(x[i]);
00404     }
00405     updateVisual();
00406 }
00407 
00408 void VisualModelImpl::applyScale(const double scale)
00409 {
00410     VecCoord& x = *getVecX();
00411     for (unsigned int i = 0; i < x.size(); i++)
00412     {
00413         x[i] *= (GLfloat) scale;
00414     }
00415     updateVisual();
00416 }
00417 
00418 void VisualModelImpl::applyUVTranslation(const double dU, const double dV)
00419 {
00420     for (unsigned int i = 0; i < vtexcoords.size(); i++)
00421     {
00422         vtexcoords[i][0] += (GLfloat) dU;
00423         vtexcoords[i][1] += (GLfloat) dV;
00424     }
00425 }
00426 
00427 void VisualModelImpl::applyUVScale(const double scaleU, const double scaleV)
00428 {
00429     for (unsigned int i = 0; i < vtexcoords.size(); i++)
00430     {
00431         vtexcoords[i][0] *= (GLfloat) scaleU;
00432         vtexcoords[i][1] *= (GLfloat) scaleV;
00433     }
00434 }
00435 
00436 void VisualModelImpl::init()
00437 {
00438 
00439   load(filename.getValue(), "", texturename.getValue());
00440   _topology = getContext()->getMeshTopology();
00441   
00442     field_vertices.beginEdit();
00443     field_vnormals.beginEdit(); 
00444     field_vtexcoords.beginEdit();
00445     field_triangles.beginEdit();
00446     field_quads.beginEdit();
00447 
00448  
00449 
00450     applyScale(scale.getValue());
00451     applyRotation(rotation.getValue()[0],rotation.getValue()[1],rotation.getValue()[2]);     
00452     applyTranslation(translation.getValue()[0],translation.getValue()[1],translation.getValue()[2]);
00453     
00454 
00455     translation.setValue(Vector3());
00456     rotation.setValue(Vector3());
00457     scale.setValue((SReal)1.0);
00458     VisualModel::init();
00459     updateVisual();
00460 }
00461 
00462 void VisualModelImpl::computeNormals()
00463 {
00464     if (vertNormIdx.empty())
00465     {
00466         int nbn = vertices.size();
00467 //      std::cerr << "nb of visual vertices"<<nbn<<std::endl;
00468 //      std::cerr << "nb of visual triangles"<<triangles.size()<<std::endl; 
00469 
00470         ResizableExtVector<Coord>& normals = vnormals;
00471 
00472         normals.resize(nbn);
00473         for (int i = 0; i < nbn; i++)
00474             normals[i].clear();
00475     
00476         for (unsigned int i = 0; i < triangles.size() ; i++)
00477         {
00478       
00479             const Coord  v1 = vertices[triangles[i][0]];
00480             const Coord  v2 = vertices[triangles[i][1]];
00481             const Coord  v3 = vertices[triangles[i][2]];
00482             Coord n = cross(v2-v1, v3-v1);
00483         
00484             n.normalize();
00485             normals[triangles[i][0]] += n;
00486             normals[triangles[i][1]] += n;
00487             normals[triangles[i][2]] += n;
00488         
00489         }
00490         for (unsigned int i = 0; i < quads.size() ; i++)
00491         {
00492             const Coord & v1 = vertices[quads[i][0]];
00493             const Coord & v2 = vertices[quads[i][1]];
00494             const Coord & v3 = vertices[quads[i][2]];
00495             const Coord & v4 = vertices[quads[i][3]];
00496             Coord n1 = cross(v2-v1, v4-v1);
00497             Coord n2 = cross(v3-v2, v1-v2);
00498             Coord n3 = cross(v4-v3, v2-v3);
00499             Coord n4 = cross(v1-v4, v3-v4);
00500             n1.normalize(); n2.normalize(); n3.normalize(); n4.normalize();
00501             normals[quads[i][0]] += n1;
00502             normals[quads[i][1]] += n2;
00503             normals[quads[i][2]] += n3;
00504             normals[quads[i][3]] += n4;
00505         }
00506         for (unsigned int i = 0; i < normals.size(); i++)
00507         {
00508             normals[i].normalize();
00509         }
00510     }
00511     else
00512     {
00513         vector<Coord> normals;
00514         int nbn = 0;
00515         for (unsigned int i = 0; i < vertNormIdx.size(); i++)
00516             if (vertNormIdx[i] >= nbn)
00517                 nbn = vertNormIdx[i]+1;
00518 
00519         normals.resize(nbn);
00520         for (int i = 0; i < nbn; i++)
00521             normals[i].clear();
00522 
00523         for (unsigned int i = 0; i < triangles.size() ; i++)
00524         {
00525             const Coord & v1 = vertices[triangles[i][0]];
00526             const Coord & v2 = vertices[triangles[i][1]];
00527             const Coord & v3 = vertices[triangles[i][2]];
00528             Coord n = cross(v2-v1, v3-v1);
00529             n.normalize();
00530             normals[vertNormIdx[triangles[i][0]]] += n;
00531             normals[vertNormIdx[triangles[i][1]]] += n;
00532             normals[vertNormIdx[triangles[i][2]]] += n;
00533         }
00534 
00535         for (unsigned int i = 0; i < quads.size() ; i++)
00536         {
00537             const Coord & v1 = vertices[quads[i][0]];
00538             const Coord & v2 = vertices[quads[i][1]];
00539             const Coord & v3 = vertices[quads[i][2]];
00540             const Coord & v4 = vertices[quads[i][3]];
00541             Coord n1 = cross(v2-v1, v4-v1);
00542             Coord n2 = cross(v3-v2, v1-v2);
00543             Coord n3 = cross(v4-v3, v2-v3);
00544             Coord n4 = cross(v1-v4, v3-v4);
00545             n1.normalize(); n2.normalize(); n3.normalize(); n4.normalize();
00546             normals[vertNormIdx[quads[i][0]]] += n1;
00547             normals[vertNormIdx[quads[i][1]]] += n2;
00548             normals[vertNormIdx[quads[i][2]]] += n3;
00549             normals[vertNormIdx[quads[i][3]]] += n4;
00550         }
00551 
00552         for (unsigned int i = 0; i < normals.size(); i++)
00553         {
00554             normals[i].normalize();
00555         }
00556         vnormals.resize(vertices.size());
00557         for (unsigned int i = 0; i < vertices.size(); i++)
00558         {
00559             vnormals[i] = normals[vertNormIdx[i]];
00560         }
00561     }
00562 }
00563 
00564 void VisualModelImpl::computeBBox()
00565 {
00566     const VecCoord& x = vertices;
00567     Vec3f minBBox(1e10,1e10,1e10);
00568     Vec3f maxBBox(-1e10,-1e10,-1e10);
00569     for (unsigned int i = 0; i < x.size(); i++)
00570     {
00571         const Coord& p = x[i];
00572         for (int c=0;c<3;c++)
00573         {
00574             if (p[c] > maxBBox[c]) maxBBox[c] = p[c];
00575             if (p[c] < minBBox[c]) minBBox[c] = p[c];
00576         }
00577     }
00578     bbox[0] = minBBox;
00579     bbox[1] = maxBBox;
00580 }
00581 
00582 bool VisualModelImpl::addBBox(double* minBBox, double* maxBBox)
00583 {
00584     if (bbox[0][0] > bbox[1][0]) return false;
00585     for (unsigned int i=0; i<xforms.size(); i++)
00586     {
00587         const Vec3f& center = xforms[i].getCenter();
00588         const Quat& orientation = xforms[i].getOrientation();
00589         for (int j=0;j<8;j++)
00590         {
00591             Coord p ( bbox[(j>>0)&1][0], bbox[(j>>1)&1][1], bbox[(j>>2)&1][2]);
00592             p = orientation.rotate(p) + center;
00593             for (int c=0;c<3;c++)
00594             {
00595                 if (p[c] > maxBBox[c]) maxBBox[c] = p[c];
00596                 if (p[c] < minBBox[c]) minBBox[c] = p[c];
00597             }
00598         }
00599     }
00600     return true;
00601 }
00602 
00603 void VisualModelImpl::flipFaces()
00604 {
00605     for (unsigned int i = 0; i < triangles.size() ; i++)
00606     {
00607         int temp = triangles[i][1];
00608         triangles[i][1] = triangles[i][2];
00609         triangles[i][2] = temp;
00610     }
00611 
00612     for (unsigned int i = 0; i < quads.size() ; i++)
00613     {
00614         int temp = quads[i][1];
00615         quads[i][1] = quads[i][3];
00616         quads[i][3] = temp;
00617 
00618     }
00619 
00620     for (unsigned int i = 0; i < vnormals.size(); i++)
00621     {
00622         vnormals[i] = -vnormals[i];
00623     }
00624 }
00625 
00626 void VisualModelImpl::setColor(float r, float g, float b, float a)
00627 {
00628   helper::io::Mesh::Material M = material.getValue();
00629   M.setColor(r,g,b,a);
00630   material.setValue(M);
00631 }
00632 
00633 static int hexval(char c)
00634 {
00635     if (c>='0' && c<='9') return c-'0';
00636     else if (c>='a' && c<='f') return (c-'a')+10;
00637     else if (c>='A' && c<='F') return (c-'A')+10;
00638     else return 0;
00639 }
00640 
00641 void VisualModelImpl::setColor(std::string color)
00642 {
00643     if (color.empty()) return;
00644     float r = 1.0f;
00645     float g = 1.0f;
00646     float b = 1.0f;
00647     float a = 1.0f;
00648     if (color[0]>='0' && color[0]<='9')
00649     {
00650         sscanf(color.c_str(),"%f %f %f %f", &r, &g, &b, &a);
00651     }
00652     else if (color[0]=='#' && color.length()>=7)
00653     {
00654         r = (hexval(color[1])*16+hexval(color[2]))/255.0f;
00655         g = (hexval(color[3])*16+hexval(color[4]))/255.0f;
00656         b = (hexval(color[5])*16+hexval(color[6]))/255.0f;
00657         if (color.length()>=9)
00658             a = (hexval(color[7])*16+hexval(color[8]))/255.0f;
00659     }
00660     else if (color[0]=='#' && color.length()>=4)
00661     {
00662         r = (hexval(color[1])*17)/255.0f;
00663         g = (hexval(color[2])*17)/255.0f;
00664         b = (hexval(color[3])*17)/255.0f;
00665         if (color.length()>=5)
00666             a = (hexval(color[4])*17)/255.0f;
00667     }
00668     else if (color == "white")    { r = 1.0f; g = 1.0f; b = 1.0f; }
00669     else if (color == "black")    { r = 0.0f; g = 0.0f; b = 0.0f; }
00670     else if (color == "red")      { r = 1.0f; g = 0.0f; b = 0.0f; }
00671     else if (color == "green")    { r = 0.0f; g = 1.0f; b = 0.0f; }
00672     else if (color == "blue")     { r = 0.0f; g = 0.0f; b = 1.0f; }
00673     else if (color == "cyan")     { r = 0.0f; g = 1.0f; b = 1.0f; }
00674     else if (color == "magenta")  { r = 1.0f; g = 0.0f; b = 1.0f; }
00675     else if (color == "yellow")   { r = 1.0f; g = 1.0f; b = 0.0f; }
00676     else if (color == "gray")     { r = 0.5f; g = 0.5f; b = 0.5f; }
00677     else
00678     {
00679         std::cerr << "Unknown color "<<color<<std::endl;
00680         return;
00681     }
00682     setColor(r,g,b,a);
00683 } 
00684 
00685 void VisualModelImpl::updateVisual()
00686 {
00687     //std::cout << "VisualModelImpl::updateVisual()"<<std::endl;
00688     if (modified && (!vertices.empty() || useTopology))
00689     {
00690         if (useTopology)
00691         {
00695             sofa::core::componentmodel::topology::TopologyModifier* topoMod; 
00696             this->getContext()->get(topoMod);           
00697             
00698             if (topoMod) { // dynamic topology
00699                 useTopology=false;                
00700                 computeMesh();
00701             }
00702             else {
00703                 
00704                 if (topoMod == NULL && (_topology->getRevision() != lastMeshRev))  // static topology
00705                 {
00706                     computeMesh();
00707                 }
00708             }
00709         }
00710         computePositions();
00711         computeNormals();
00712         computeBBox();
00713         modified = false;
00714     }
00715 }
00716 
00717 
00718 void VisualModelImpl::computePositions()
00719 {
00720     if (!vertPosIdx.empty())
00721     { // Need to transfer positions
00722         for (unsigned int i=0 ; i < vertices.size(); ++i)
00723             vertices[i] = (*inputVertices)[vertPosIdx[i]];
00724     }
00725 }
00726 
00727 void VisualModelImpl::computeMesh()
00728 {
00729     if (vertices.empty())
00730     {
00731         if (_topology->hasPos())
00732         {
00733     
00734     if (sofa::component::topology::SparseGridTopology * spTopo = dynamic_cast< sofa::component::topology::SparseGridTopology *>(_topology))
00735     {     
00736       std::cout << "VisualModel: getting marching cube mesh from topology : ";
00737       sofa::helper::io::Mesh m;
00738       spTopo->getMesh(m);
00739       setMesh(m, !texturename.getValue().empty());
00740       std::cout
00741           <<m.getVertices().size()<<" points, " 
00742           <<m.getFacets().size()  << " triangles."<<std::endl;
00743       useTopology = false; //visual model needs to be created only once at initial time
00744       return;
00745     }
00746     if (this->f_printLog.getValue())
00747         std::cout << "VisualModel: copying "<<_topology->getNbPoints()<<" points from topology."<<std::endl;
00748         vertices.resize(_topology->getNbPoints());
00749         
00750         for (unsigned int i=0;i<vertices.size();i++)
00751         {
00752             vertices[i][0] = (Real)_topology->getPX(i);
00753             vertices[i][1] = (Real)_topology->getPY(i);
00754             vertices[i][2] = (Real)_topology->getPZ(i);
00755         }
00756         
00757         }
00758         else
00759         {
00760             core::componentmodel::behavior::BaseMechanicalState* mstate = dynamic_cast<core::componentmodel::behavior::BaseMechanicalState*>(_topology->getContext()->getMechanicalState());
00761             if (mstate)
00762             {
00763                 if (this->f_printLog.getValue())
00764                     std::cout << "VisualModel: copying "<<mstate->getSize()<<" points from mechanical state."<<std::endl;
00765                 vertices.resize(mstate->getSize());
00766                         
00767                 for (unsigned int i=0;i<vertices.size();i++)
00768                 {
00769                     vertices[i][0] = (Real)mstate->getPX(i);
00770                     vertices[i][1] = (Real)mstate->getPY(i);
00771                     vertices[i][2] = (Real)mstate->getPZ(i);
00772                 }
00773             }
00774         }
00775     }
00776 
00777     lastMeshRev = _topology->getRevision();
00778     const vector<sofa::core::componentmodel::topology::BaseMeshTopology::Triangle>& inputTriangles = _topology->getTriangles();
00779     if (this->f_printLog.getValue())
00780     std::cout << "VisualModel: copying "<<inputTriangles.size()<<" triangles from topology."<<std::endl;
00781 
00782     triangles.resize(inputTriangles.size());
00783 
00784     for (unsigned int i=0; i<triangles.size(); ++i){
00785         triangles[i] = inputTriangles[i];       
00786     }
00787 
00788     const vector<sofa::core::componentmodel::topology::BaseMeshTopology::Quad>& inputQuads = _topology->getQuads();
00789     if (this->f_printLog.getValue())
00790     std::cout << "VisualModel: copying "<<inputQuads.size()<<" quads from topology."<<std::endl;
00791     quads.resize(inputQuads.size());
00792     for (unsigned int i=0; i<quads.size(); ++i)
00793         quads[i] = inputQuads[i];
00794 }
00795 
00796 void VisualModelImpl::handleTopologyChange() {
00797 
00798     bool debug_mode = false;
00799 
00800     std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00801     std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00802 
00803     while( itBegin != itEnd )
00804     {
00805         core::componentmodel::topology::TopologyChangeType changeType = (*itBegin)->getChangeType();
00806         
00807         switch( changeType ) 
00808         {
00809                 case core::componentmodel::topology::ENDING_EVENT:
00810                     {
00811                         //std::cout << "INFO_print : Vis - ENDING_EVENT" << std::endl;
00812                         updateVisual();
00813                         break;
00814                     }
00815 
00816                 case core::componentmodel::topology::TRIANGLESADDED:
00817                     {
00818                         //std::cout << "INFO_print : Vis - TRIANGLESADDED" << std::endl;
00819                         
00820                         const sofa::component::topology::TrianglesAdded *ta=static_cast< const sofa::component::topology::TrianglesAdded * >( *itBegin );
00821                         Triangle t;
00822                         
00823                         for (unsigned int i=0;i<ta->getNbAddedTriangles();++i) {
00824                             
00825                             t[0]=(int)(ta->triangleArray[i])[0];
00826                             t[1]=(int)(ta->triangleArray[i])[1];
00827                             t[2]=(int)(ta->triangleArray[i])[2];
00828                             triangles.push_back(t);                         
00829                         }
00830                         
00831                         break;
00832                     }
00833 
00834                 case core::componentmodel::topology::QUADSADDED:
00835                     {
00836                         //std::cout << "INFO_print : Vis - QUADSADDED" << std::endl;
00837                         
00838                         const sofa::component::topology::QuadsAdded *ta_const=static_cast< const sofa::component::topology::QuadsAdded * >( *itBegin );
00839                         sofa::component::topology::QuadsAdded *ta = const_cast< sofa::component::topology::QuadsAdded * >(ta_const);
00840                         Quad t;
00841                         
00842                         for (unsigned int i=0;i<ta->getNbAddedQuads();++i) {
00843                             
00844                             t[0]=(int)(ta->getQuad(i))[0];
00845                             t[1]=(int)(ta->getQuad(i))[1];
00846                             t[2]=(int)(ta->getQuad(i))[2];
00847                             t[3]=(int)(ta->getQuad(i))[3];
00848                             quads.push_back(t);                         
00849                         }
00850                         
00851                         break;
00852                     }
00853 
00854                 case core::componentmodel::topology::TRIANGLESREMOVED:
00855                     {
00856                         //std::cout << "INFO_print : Vis - TRIANGLESREMOVED" << std::endl;
00857 
00858                         unsigned int last;
00859                         unsigned int ind_last;
00860                                             
00861                         last= _topology->getNbTriangles() - 1;
00862 
00863                         const sofa::helper::vector<unsigned int> &tab = ( static_cast< const sofa::component::topology::TrianglesRemoved *>( *itBegin ) )->getArray();
00864 
00865                         Triangle tmp;                                           
00866                         
00867                         for (unsigned int i = 0; i <tab.size(); ++i)
00868                         {
00869                             unsigned int ind_k = tab[i];                    
00870                             
00871                             tmp = triangles[ind_k]; 
00872                             triangles[ind_k] = triangles[last];
00873                             triangles[last] = tmp;
00874 
00875                             ind_last = triangles.size() - 1;
00876 
00877                             if(last != ind_last){
00878 
00879                                 tmp = triangles[last];
00880                                 triangles[last] = triangles[ind_last];
00881                                 triangles[ind_last] = tmp;
00882                             }
00883                             
00884                             triangles.resize( triangles.size() - 1 );                               
00885 
00886                             --last;
00887 
00888                         }                       
00889 
00890                         break;
00891                     }
00892 
00893                     case core::componentmodel::topology::QUADSREMOVED:
00894                     {
00895                         //std::cout << "INFO_print : Vis - QUADSREMOVED" << std::endl;
00896 
00897                         unsigned int last;
00898                         unsigned int ind_last;                          
00899                                                 
00900                         last= _topology->getNbQuads() - 1;                                      
00901 
00902                         const sofa::helper::vector<unsigned int> &tab = ( static_cast< const sofa::component::topology::QuadsRemoved *>( *itBegin ) )->getArray();
00903 
00904                         Quad tmp;                   
00905 
00906                         for (unsigned int i = 0; i <tab.size(); ++i)
00907                         {
00908 
00909                             unsigned int ind_k = tab[i];                
00910 
00911                             tmp = quads[ind_k];
00912                             quads[ind_k] = quads[last];
00913                             quads[last] = tmp;                              
00914 
00915                             ind_last = quads.size() - 1;
00916 
00917                             if(last != ind_last){
00918 
00919                                 tmp = quads[last];
00920                                 quads[last] = quads[ind_last];
00921                                 quads[ind_last] = tmp;                                                                      
00922 
00923                             }
00924 
00925                             quads.resize( quads.size() - 1 );                                                                                       
00926 
00927                             --last;
00928 
00929                         }                       
00930 
00931                         break;
00932                     }                   
00933 
00934                     // Case "POINTSREMOVED" added to propagate the treatment to the Visual Model
00935                     
00936                     case core::componentmodel::topology::POINTSREMOVED:
00937                     {   
00938                             //std::cout << "INFO_print : Vis - POINTSREMOVED" << std::endl;
00939 
00940                             if (_topology->getNbTriangles()>0) {
00941                                                                 
00942                                 unsigned int last = _topology->getNbPoints() -1;
00943 
00944                                 unsigned int i,j;
00945 
00946                                 const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRemoved * >( *itBegin ) )->getArray();
00947 
00948                                 sofa::helper::vector<unsigned int> lastIndexVec;
00949 
00950                                 for(unsigned int i_init = 0; i_init < tab.size(); ++i_init){
00951                                     lastIndexVec.push_back(last - i_init);
00952                                 }
00953 
00954                                 for ( i = 0; i < tab.size(); ++i){
00955                                     
00956                                     unsigned int i_next = i;
00957                                     bool is_reached = false;
00958 
00959                                     while( (!is_reached) && (i_next < lastIndexVec.size() - 1)){
00960 
00961                                         i_next += 1 ;
00962                                         is_reached = is_reached || (lastIndexVec[i_next] == tab[i]);
00963                                     }
00964 
00965                                     if(is_reached){
00966                                         lastIndexVec[i_next] = lastIndexVec[i];
00967                                     }
00968 
00969                                     const sofa::helper::vector<unsigned int> &shell= _topology->getTriangleVertexShell(lastIndexVec[i]); 
00970                                     for (j=0;j<shell.size();++j) {
00971 
00972                                             unsigned int ind_j = shell[j]; 
00973 
00974                                             if ((unsigned)triangles[ind_j][0]==last)
00975                                                 triangles[ind_j][0]=tab[i];
00976                                             else if ((unsigned)triangles[ind_j][1]==last)
00977                                                 triangles[ind_j][1]=tab[i];
00978                                             else if ((unsigned)triangles[ind_j][2]==last)
00979                                                 triangles[ind_j][2]=tab[i];                                 
00980                                     }
00981                                                                         
00982                                     if (debug_mode) {
00983 
00984                                         for (unsigned int j_loc=0;j_loc<triangles.size();++j_loc) {
00985 
00986                                             bool is_forgotten = false;
00987                                             if ((unsigned)triangles[j_loc][0]==last){
00988                                                 triangles[j_loc][0]=tab[i];
00989                                                 is_forgotten=true;
00990 
00991                                             }else{
00992                                                 if ((unsigned)triangles[j_loc][1]==last){
00993                                                     triangles[j_loc][1]=tab[i];
00994                                                     is_forgotten=true;
00995 
00996                                                 }else{
00997                                                     if ((unsigned)triangles[j_loc][2]==last){
00998                                                         triangles[j_loc][2]=tab[i];
00999                                                         is_forgotten=true;
01000                                                     }
01001                                                 }
01002 
01003                                             }
01004 
01005                                             if(is_forgotten){
01006 
01007                                                 int ind_forgotten = j_loc;                                          
01008 
01009                                                 bool is_in_shell = false;
01010                                                 for (unsigned int j_glob=0;j_glob<shell.size();++j_glob) {
01011                                                   is_in_shell = is_in_shell || ((int)shell[j_glob] == ind_forgotten);
01012                                                 }
01013 
01014                                                 if(!is_in_shell) { 
01015                                                     std::cout << "INFO_print : Vis - triangle is forgotten in SHELL !!! global indices (point, triangle) = ( "  << last << " , " << ind_forgotten  << " )" << std::endl;
01016                                                     
01017                                                     if(ind_forgotten<_topology->getNbTriangles()){
01018                                                         const sofa::component::topology::Triangle t_forgotten = _topology->getTriangle(ind_forgotten);
01019                                                         std::cout << "INFO_print : Vis - last = " << last << std::endl; 
01020                                                         std::cout << "INFO_print : Vis - lastIndexVec[i] = " << lastIndexVec[i] << std::endl; 
01021                                                         std::cout << "INFO_print : Vis - tab.size() = " << tab.size() << " , tab = " << tab << std::endl; 
01022                                                         std::cout << "INFO_print : Vis - t_local rectified = " << triangles[j_loc] << std::endl;
01023                                                         std::cout << "INFO_print : Vis - t_global = " << t_forgotten << std::endl;
01024 
01025                                                         
01026                                                     }
01027                                                     
01028                                                 }
01029 
01030                                             }
01031 
01032                                         }
01033                                     }                                                                       
01034 
01035                                     --last;
01036                                 }
01037                                 
01038                             }else{
01039                                 
01040                                 if (_topology->getNbQuads()>0) {
01041                                     
01042                                     unsigned int last = _topology->getNbPoints() -1;
01043 
01044                                     unsigned int i,j;
01045 
01046                                     const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRemoved * >( *itBegin ) )->getArray();
01047 
01048                                     sofa::helper::vector<unsigned int> lastIndexVec;
01049                                     for(unsigned int i_init = 0; i_init < tab.size(); ++i_init){
01050 
01051                                         lastIndexVec.push_back(last - i_init);
01052                                     }
01053 
01054                                     for ( i = 0; i < tab.size(); ++i)
01055                                     {                                   
01056                                         unsigned int i_next = i;
01057                                         bool is_reached = false;
01058                                         while( (!is_reached) && (i_next < lastIndexVec.size() - 1)){
01059 
01060                                             i_next += 1 ;
01061                                             is_reached = is_reached || (lastIndexVec[i_next] == tab[i]);
01062                                         }
01063 
01064                                         if(is_reached){
01065 
01066                                             lastIndexVec[i_next] = lastIndexVec[i];
01067 
01068                                         }
01069 
01070                                         const sofa::helper::vector<unsigned int> &shell= _topology->getQuadVertexShell(lastIndexVec[i]); 
01071                                         for (j=0;j<shell.size();++j) {
01072 
01073                                                 unsigned int ind_j = shell[j]; 
01074 
01075                                                 if ((unsigned)quads[ind_j][0]==last)
01076                                                     quads[ind_j][0]=tab[i];
01077                                                 else if ((unsigned)quads[ind_j][1]==last)
01078                                                     quads[ind_j][1]=tab[i];
01079                                                 else if ((unsigned)quads[ind_j][2]==last)
01080                                                     quads[ind_j][2]=tab[i];
01081                                                 else if ((unsigned)quads[ind_j][3]==last)
01082                                                     quads[ind_j][3]=tab[i];                                         
01083                                         }                                                                               
01084 
01085                                         --last;
01086                                     }
01087 
01089                                     
01090                                 }
01091 
01092                                 
01093                             }
01094 
01095                         //}                     
01096                         
01097                         break;
01098                         
01099                     }
01100                     
01101 
01102                     // Case "POINTSRENUMBERING" added to propagate the treatment to the Visual Model
01103 
01104                     case core::componentmodel::topology::POINTSRENUMBERING:
01105                     {   
01106                             //std::cout << "INFO_print : Vis - POINTSRENUMBERING" << std::endl;
01107 
01108                             if (_topology->getNbTriangles()>0) {                                                                
01109 
01110                                 unsigned int i;
01111 
01112                                 const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRenumbering * >( *itBegin ) )->getinv_IndexArray();
01113 
01114                                 for ( i = 0; i < triangles.size(); ++i)
01115                                 {                                   
01116                                     triangles[i][0]  = tab[triangles[i][0]];
01117                                     triangles[i][1]  = tab[triangles[i][1]];
01118                                     triangles[i][2]  = tab[triangles[i][2]];                                        
01119                                 }                               
01120                                 
01121                             }else{
01122                                 if (_topology->getNbQuads()>0) {                                    
01123 
01124                                     unsigned int i;
01125 
01126                                     const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRenumbering * >( *itBegin ) )->getinv_IndexArray();
01127 
01128                                     for ( i = 0; i < quads.size(); ++i)
01129                                     {                                   
01130                                         quads[i][0]  = tab[quads[i][0]];
01131                                         quads[i][1]  = tab[quads[i][1]];
01132                                         quads[i][2]  = tab[quads[i][2]];        
01133                                         quads[i][3]  = tab[quads[i][3]];    
01134                                     }                                   
01135                                 }
01136                             }
01137 
01138                         //}                     
01139                         
01140                         break;
01141                         
01142                     }
01143 
01144                 default:
01145                     // Ignore events that are not Triangle  related.
01146                     break;
01147         }; // switch( changeType )
01148 
01149         ++itBegin;
01150     } // while( changeIt != last; )
01151 
01152 
01153 }
01154 
01155 void VisualModelImpl::initVisual()
01156 {
01157     //if (tex)
01158     //{
01159     //    tex->init();
01160     //}
01161 }
01162 
01163 void VisualModelImpl::exportOBJ(std::string name, std::ostream* out, std::ostream* mtl, int& vindex, int& nindex, int& tindex)
01164 {
01165     *out << "g "<<name<<"\n";
01166 
01167     if (mtl != NULL) // && !material.name.empty())
01168     {
01169             std::string name; // = material.name;
01170             if (name.empty())
01171             {
01172                     static int count = 0;
01173                     std::ostringstream o; o << "mat" << ++count;
01174                     name = o.str();
01175             }
01176             *mtl << "newmtl "<<name<<"\n";
01177             *mtl << "illum 4\n";
01178             if (material.getValue().useAmbient)
01179                     *mtl << "Ka "<<material.getValue().ambient[0]<<' '<<material.getValue().ambient[1]<<' '<<material.getValue().ambient[2]<<"\n";
01180             if (material.getValue().useDiffuse)
01181                     *mtl << "Kd "<<material.getValue().diffuse[0]<<' '<<material.getValue().diffuse[1]<<' '<<material.getValue().diffuse[2]<<"\n";
01182             *mtl << "Tf 1.00 1.00 1.00\n";
01183             *mtl << "Ni 1.00\n";
01184             if (material.getValue().useSpecular)
01185                     *mtl << "Ks "<<material.getValue().specular[0]<<' '<<material.getValue().specular[1]<<' '<<material.getValue().specular[2]<<"\n";
01186             if (material.getValue().useShininess)
01187                     *mtl << "Ns "<<material.getValue().shininess<<"\n";
01188             if (material.getValue().useDiffuse && material.getValue().diffuse[3]<1.0)
01189                     *mtl << "Tf "<<material.getValue().diffuse[3]<<' '<<material.getValue().diffuse[3]<<' '<<material.getValue().diffuse[3]<<"\n";
01190 
01191             *out << "usemtl "<<name<<'\n';
01192     }
01193     const ResizableExtVector<Coord>& x = *inputVertices;
01194 
01195     int nbv = x.size();
01196 
01197     for (unsigned int i=0; i<x.size(); i++)
01198     {
01199             *out << "v "<< std::fixed << x[i][0]<<' '<< std::fixed <<x[i][1]<<' '<< std::fixed <<x[i][2]<<'\n';
01200     }
01201 
01202     int nbn = 0;
01203 
01204     if (vertNormIdx.empty())
01205     {
01206         nbn = vnormals.size();
01207         for (unsigned int i=0; i<vnormals.size(); i++)
01208         {
01209             *out << "vn "<< std::fixed << vnormals[i][0]<<' '<< std::fixed <<vnormals[i][1]<<' '<< std::fixed <<vnormals[i][2]<<'\n';
01210         }
01211     }
01212     else
01213     {
01214         for (unsigned int i = 0; i < vertNormIdx.size(); i++)
01215         {
01216             if (vertNormIdx[i] >= nbn)
01217                 nbn = vertNormIdx[i]+1;
01218         }
01219         vector<int> normVertIdx(nbn);
01220         for (unsigned int i = 0; i < vertNormIdx.size(); i++)
01221         {
01222             normVertIdx[vertNormIdx[i]]=i;
01223         }
01224         for (int i = 0; i < nbn; i++)
01225         {
01226             int j = normVertIdx[i];
01227             *out << "vn "<< std::fixed << vnormals[j][0]<<' '<< std::fixed <<vnormals[j][1]<<' '<< std::fixed <<vnormals[j][2]<<'\n';
01228         }
01229     }
01230 
01231     int nbt = 0;
01232     if (!vtexcoords.empty())
01233     {
01234         nbt = vtexcoords.size();
01235         for (unsigned int i=0; i<vtexcoords.size(); i++)
01236         {
01237             *out << "vt "<< std::fixed << vtexcoords[i][0]<<' '<< std::fixed <<vtexcoords[i][1]<<'\n';
01238         }
01239     }
01240 
01241     for (unsigned int i = 0; i < triangles.size() ; i++)
01242     {
01243         *out << "f";
01244         for (int j=0;j<3;j++)
01245         {
01246             int i0 = triangles[i][j];
01247             int i_p = vertPosIdx.empty() ? i0 : vertPosIdx[i0];
01248             int i_n = vertNormIdx.empty() ? i0 : vertNormIdx[i0];
01249             if (vtexcoords.empty())
01250                 *out << ' ' << i_p+vindex+1 << "//" << i_n+nindex+1;
01251             else
01252                 *out << ' ' << i_p+vindex+1 << '/' << i0+tindex+1 << '/' << i_n+nindex+1;
01253         }
01254         *out << '\n';
01255     }
01256     for (unsigned int i = 0; i < quads.size() ; i++)
01257     {
01258         *out << "f";
01259         for (int j=0;j<4;j++)
01260         {
01261             int i0 = quads[i][j];
01262             int i_p = vertPosIdx.empty() ? i0 : vertPosIdx[i0];
01263             int i_n = vertNormIdx.empty() ? i0 : vertNormIdx[i0];
01264             if (vtexcoords.empty())
01265                 *out << ' ' << i_p+vindex+1 << "//" << i_n+nindex+1;
01266             else
01267                 *out << ' ' << i_p+vindex+1 << '/' << i0+tindex+1 << '/' << i_n+nindex+1;
01268         }
01269         *out << '\n';
01270     }
01271     *out << std::endl; 
01272     vindex+=nbv;
01273     nindex+=nbn;
01274     tindex+=nbt;
01275 }
01276 
01277 } // namespace visualmodel
01278 
01279 } // namespace component
01280 
01281 } // namespace sofa
01282 

Generated on Sun Nov 23 03:49:11 2008 for Sofa by  doxygen 1.5.7.1