OgreVisualModel.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 program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program 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 General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <sofa/gui/qt/viewer/qtogre/OgreVisualModel.h>
00028 
00029 #include <sofa/core/ObjectFactory.h>
00030 #include <sofa/helper/io/Mesh.h>
00031 #include <sofa/simulation/tree/GNode.h>
00032 
00033 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00034 #include <sofa/core/componentmodel/behavior/BaseMechanicalMapping.h>
00035 #include <sofa/core/BaseMapping.h>
00036 
00037 #include <iostream>
00038 
00039 namespace sofa
00040 {
00041 
00042   namespace component
00043   {
00044 
00045     namespace visualmodel
00046     {
00047       
00048 SOFA_DECL_CLASS(OgreVisualModel)
00049 
00050 int OgreVisualModel::counter; //static counter to get unique name for entities
00051 
00052 OgreVisualModel::OgreVisualModel()
00053     : materialname(initData(&materialname, "materialname", "material name")),scale(1.0)
00054 , ogreMesh(NULL), ogreEntity(NULL), ogreNode(NULL)
00055 {   
00056 }
00057 
00058 
00059 std::string OgreVisualModel::uniqueName(void)
00060 {
00061      std::ostringstream s;
00062       s << getOgreName() + "_" << ++OgreVisualModel::counter;
00063       return s.str();
00064 }
00065 
00066 
00067 std::string OgreVisualModel::getOgreName()
00068 {
00069   return "SOFA"+static_cast<sofa::simulation::tree::GNode*>(getContext())->getPathName()+"/"+getName();
00070 }
00071 
00072 void OgreVisualModel::parse(core::objectmodel::BaseObjectDescription* arg)
00073 {
00074   
00075   if (arg->getAttribute("scale")!=NULL) {
00076     //obj->applyScale(atof(arg->getAttribute("scale","1.0")));
00077     scale=atof(arg->getAttribute("scale","1.0"));
00078   }
00079 //   if (arg->getAttribute("rx")!=NULL) {
00080 //     //obj->applyRotation(Quat(Vector3(1,0,0), atof(arg->getAttribute("rx","0.0"))*R_PI/180));
00081 //   }
00082 //   if (arg->getAttribute("ry")!=NULL) {
00083 //     //obj->applyRotation(Quat(Vector3(0,1,0), atof(arg->getAttribute("ry","0.0"))*R_PI/180));
00084 //   }
00085 //   if (arg->getAttribute("rz")!=NULL) {
00086 //     //obj->applyRotation(Quat(Vector3(0,0,1), atof(arg->getAttribute("rz","0.0"))*R_PI/180));
00087 //   }
00088     
00089   if (arg->getAttribute("dx")!=NULL || arg->getAttribute("dy")!=NULL || arg->getAttribute("dz")!=NULL) {
00090     //obj->applyTranslation(atof(arg->getAttribute("dx","0.0")),atof(arg->getAttribute("dy","0.0")),atof(arg->getAttribute("dz","0.0")));
00091     dx=atof(arg->getAttribute("dx","0.0"));
00092     dy=atof(arg->getAttribute("dy","0.0"));
00093     dz=atof(arg->getAttribute("dz","0.0"));
00094   }
00095   
00096   VisualModelImpl::parse(arg);  
00097 }
00098 bool OgreVisualModel::lightSwitched;
00099 
00100 void OgreVisualModel::attach(Ogre::SceneManager* sceneMgr)
00101 {
00102   // Attach the mesh to an entity and a scene node
00103   // Create OGRE Mesh
00104   ogreMesh = Ogre::MeshManager::getSingleton().getByName(getOgreName()+".mesh");
00105   if (!ogreMesh.isNull()) setName(uniqueName());
00106   ogreMesh = Ogre::MeshManager::getSingleton().createManual(getOgreName()+".mesh", "General"); 
00107 
00108   if (3*this->vertices.size() > sceneMgr->getShadowIndexBufferSize()) 
00109     sceneMgr->setShadowIndexBufferSize(3*this->vertices.size());
00110 
00111   Ogre::SubMesh *submesh = ogreMesh->createSubMesh();
00112   Ogre::VertexData* vertexData = ogreMesh->sharedVertexData = new Ogre::VertexData();
00113   Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
00114   size_t currOffset[2] = {0, 0};
00115   // positions
00116   vertexDecl->addElement(0, currOffset[0], Ogre::VET_FLOAT3, Ogre::VES_POSITION);
00117   currOffset[0] += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
00118   // normals
00119   vertexDecl->addElement(0, currOffset[0], Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
00120   currOffset[0] += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
00121   if (!this->texturename.getValue().empty())
00122     {
00123       // two dimensional texture coordinates
00124       vertexDecl->addElement(1, currOffset[1], Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
00125       currOffset[1] += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
00126     }
00127   // allocate the vertex buffer
00128   vertexData->vertexCount = this->vertices.size();
00129   vBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), (vertexData->vertexCount>0?vertexData->vertexCount:1), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
00130   Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00131   binding->setBinding(0, vBuffer);
00132     
00133   uploadVertices();
00134   // Upload tex coordinates
00135   if (!this->texturename.getValue().empty())
00136     {
00137       Ogre::HardwareVertexBufferSharedPtr vBuffer2 = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(1), (vertexData->vertexCount>0?vertexData->vertexCount:1), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00138       Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00139       binding->setBinding(1, vBuffer2);
00140       //texture coordinates are inverted with Ogre
00141       for (unsigned int i=0;i<this->vtexcoords.size();++i) this->vtexcoords[i][1] =1- this->vtexcoords[i][1];
00142       vBuffer2->writeData(0, this->vtexcoords.size() * sizeof(this->vtexcoords[0]), this->vtexcoords.getData());
00143     }
00144   submesh->useSharedVertices = true;
00145   // allocate index buffer
00146   submesh->indexData->indexCount = 3 * getNbTriangles();
00147   iBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer((this->vertices.size() < 0x10000) ? Ogre::HardwareIndexBuffer::IT_16BIT : Ogre::HardwareIndexBuffer::IT_32BIT, (submesh->indexData->indexCount>0?submesh->indexData->indexCount:1), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00148   submesh->indexData->indexBuffer = iBuffer;
00149   uploadIndices();
00150   computeBounds();
00151 
00152   //Apply the good material/texture/colour
00153   submesh_material = std::string("Sofa/") + uniqueName();
00154   Ogre::MaterialPtr mat;
00155   if (!materialname.getValue().empty()) {    
00156     Ogre::MaterialPtr mat_mem = Ogre::MaterialManager::getSingleton().getByName(materialname.getValue());
00157     mat = mat_mem->clone(submesh_material);
00158   }
00159   else
00160     {       
00161       mat = Ogre::MaterialManager::getSingleton().create(submesh_material, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 
00162       //Two side polygon!
00163       mat->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);
00164       
00165       if (!this->texturename.getValue().empty()) //A texture has been specified
00166         {
00167           Ogre::TextureUnitState *ogre_texture = mat->getTechnique(0)->getPass(0)->createTextureUnitState(getOgreName()+std::string("_texture")); 
00168           ogre_texture->setTextureName(this->texturename.getValue());
00169 //        if (scaleTex.getValue() != 0)
00170 //          ogre_texture->setTextureScale(Ogre::Real(this->scaleTex.getValue()), Ogre::Real(this->scaleTex.getValue()));
00171         }
00172     }       
00173     submesh->setMaterialName(submesh_material);
00174     updateMaterial(mat);
00175 
00176 // unsigned short src, dest;
00177 //  if (!ogreMesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT,src, dest))
00178 // {
00179 //   ogreMesh->buildTangentVectors(Ogre::VES_TANGENT,src, dest);
00180 // }
00181 
00182   // this line makes clear the mesh is loaded (avoids memory leaks)
00183 
00184   ogreMesh->load();
00185 
00186   ogreEntity = sceneMgr->createEntity( getOgreName(), getOgreName()+".mesh" );
00187   
00188   ogreEntity->setNormaliseNormals(true); 
00189 
00190   ogreNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
00191   
00192   ogreNode->attachObject(ogreEntity);
00193 
00194   ogreNode->setInitialState();
00195   
00196   //ogreNode->showBoundingBox(true);
00197 }
00198 
00199 
00200 void OgreVisualModel::reinit()
00201 {
00202  Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(submesh_material);
00203  if (!mat.isNull())
00204  {
00205    updateMaterial(mat);
00206  }
00207  updateVisual();
00208 }
00209 
00210 void OgreVisualModel::updateMaterial(Ogre::MaterialPtr &mat)
00211 {  
00212     if (this->material.getValue().useDiffuse)
00213       mat->getTechnique(0)->getPass(0)->setDiffuse(Ogre::ColourValue(this->material.getValue().diffuse[0],this->material.getValue().diffuse[1],this->material.getValue().diffuse[2],this->material.getValue().diffuse[3]));
00214     else
00215       mat->getTechnique(0)->getPass(0)->setDiffuse(Ogre::ColourValue(0,0,0,0));
00216     
00217     if (this->material.getValue().useAmbient)
00218       mat->getTechnique(0)->getPass(0)->setAmbient(Ogre::ColourValue(this->material.getValue().ambient[0],this->material.getValue().ambient[1],this->material.getValue().ambient[2],this->material.getValue().ambient[3]));
00219     else
00220       mat->getTechnique(0)->getPass(0)->setAmbient(Ogre::ColourValue(0,0,0,0));
00221     
00222     if (this->material.getValue().useEmissive)
00223       mat->getTechnique(0)->getPass(0)->setSelfIllumination(Ogre::ColourValue(this->material.getValue().emissive[0],this->material.getValue().emissive[1],this->material.getValue().emissive[2],this->material.getValue().emissive[3]));
00224     else
00225       mat->getTechnique(0)->getPass(0)->setSelfIllumination(Ogre::ColourValue(0,0,0,0));
00226     
00227     if (this->material.getValue().useSpecular)
00228       mat->getTechnique(0)->getPass(0)->setSpecular(Ogre::ColourValue(this->material.getValue().specular[0],this->material.getValue().specular[1],this->material.getValue().specular[2],this->material.getValue().specular[3]));
00229     else
00230       mat->getTechnique(0)->getPass(0)->setSpecular(Ogre::ColourValue(0,0,0,0));
00231     
00232     if (this->material.getValue().useShininess)
00233       mat->getTechnique(0)->getPass(0)->setShininess(Ogre::Real(this->material.getValue().shininess));
00234     else
00235       mat->getTechnique(0)->getPass(0)->setShininess(Ogre::Real(45));
00236     mat->compile();
00237 }
00238 
00239 void OgreVisualModel::updateVisual()
00240 {
00241   if (ogreMesh.isNull()) return;
00242   sofa::core::componentmodel::topology::BaseMeshTopology* topology = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(getContext()->getTopology());
00243   if (topology && topology->getRevision() != meshRevision)
00244     uploadIndices();
00245 
00246 
00247   if (this->modified//  || lightSwitched
00248       )
00249   { 
00250       uploadVertices(); 
00251       computeNormals();
00252       computeBounds();   
00253       lightSwitched = false;
00254     }
00255 }
00256 
00257 
00258 void OgreVisualModel::uploadVertices()
00259 {
00260   this->modified = false;
00261   Ogre::VertexData* vertexData = ogreMesh->sharedVertexData;
00262   Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
00263   
00264   if (!ogreMesh->isPreparedForShadowVolumes())
00265     {
00266       if (this->vertices.size() > vertexData->vertexCount)
00267         {
00268       // need to resize hardware buffers
00269       if (this->vertices.size() >= 2* vertexData->vertexCount)
00270         vertexData->vertexCount = this->vertices.size();
00271       else
00272         vertexData->vertexCount *= 2;
00273       
00274       vBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), (vertexData->vertexCount>0?vertexData->vertexCount:1),       
00275           Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
00276       
00277       Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00278       
00279       binding->setBinding(0, vBuffer);
00280         }
00281     if (this->vnormals.size() == 0) computeNormals();
00282       Coord* pVertex = static_cast<Coord*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00283       for (unsigned int i=0; i < this->vertices.size(); i++)
00284         {
00285       *(pVertex++) = this->vertices[i];
00286       if (this->vnormals.size() <= i)  ; //*(pVertex++) = (Real)0;
00287       else                             
00288         *(pVertex++) = this->vnormals[i];
00289         }
00290       dx = dy = dz = 0;
00291       scale = 1;
00292       vBuffer->unlock();      
00293     }
00294   else
00295     {      
00296 
00297       // The mesh has been reorganized to be extruded for shadow volumes
00298       const Ogre::VertexElement* posElem = ogreMesh->sharedVertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
00299       Ogre::HardwareVertexBufferSharedPtr vBufferPos = ogreMesh->sharedVertexData->vertexBufferBinding->getBuffer(posElem->getSource());
00300         
00301       const Ogre::VertexElement* normElem = ogreMesh->sharedVertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
00302       Ogre::HardwareVertexBufferSharedPtr vBufferNorm = ogreMesh->sharedVertexData->vertexBufferBinding->getBuffer(normElem->getSource());
00303 
00304       if (this->vertices.size() > vertexData->vertexCount)
00305     {
00306       // need to resize hardware buffers
00307       if (this->vertices.size() >= 2* vertexData->vertexCount)
00308         vertexData->vertexCount = this->vertices.size();
00309       else
00310         vertexData->vertexCount *= 2;
00311       vBufferPos = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(posElem->getSource()), 2*(vertexData->vertexCount>0?vertexData->vertexCount:1), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
00312       vBufferNorm = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(normElem->getSource()), (vertexData->vertexCount>0?vertexData->vertexCount:1), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
00313       Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00314       binding->setBinding(posElem->getSource(), vBufferPos);
00315       binding->setBinding(normElem->getSource(), vBufferNorm);
00316         }
00317 
00318       Coord* pVertex = static_cast<Coord*>(vBufferPos->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00319       // Two copies of each position must be sent
00320       memcpy(pVertex, this->vertices.getData(), this->vertices.size()*sizeof(Coord));
00321       memcpy(pVertex+this->vertices.size(), this->vertices.getData(), this->vertices.size()*sizeof(Coord));
00322       vBufferPos->unlock();
00323       Coord* pNormal = static_cast<Coord*>(vBufferNorm->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00324       memcpy(pNormal, this->vnormals.getData(), this->vnormals.size()*sizeof(Coord));
00325       vBufferNorm->unlock();
00326         
00327       // We must recompute normals
00328 
00329       ogreMesh->getEdgeList()->updateFaceNormals(0,vBufferPos);
00330     }
00331 }
00332 
00333 void OgreVisualModel::uploadIndices()
00334 {
00335   unsigned int nindices = 3*getNbTriangles();
00336     if (iBuffer->getNumIndexes() < nindices)
00337     {
00338         unsigned int nalloc;
00339         // need to resize hardware buffers
00340         if (nindices >= 2* iBuffer->getNumIndexes())
00341             nalloc = nindices;
00342         else
00343             nalloc = 2*iBuffer->getNumIndexes();
00344         iBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer((nalloc < 0x10000) ? Ogre::HardwareIndexBuffer::IT_16BIT : Ogre::HardwareIndexBuffer::IT_32BIT, (nalloc>0?nalloc:1), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00345         ogreMesh->getSubMesh(0)->indexData->indexBuffer = iBuffer;
00346     }
00347     ogreMesh->getSubMesh(0)->indexData->indexCount = 3 * getNbTriangles();
00348     sofa::core::componentmodel::topology::BaseMeshTopology* topology = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(getContext()->getTopology());
00349   
00350     if (this->useTopology && topology)
00351     {      
00352       const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = topology->getTriangles();
00353         const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = topology->getQuads();
00354         if (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT)
00355         {
00356             unsigned int* pIndices = static_cast<unsigned int*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00357             for (unsigned int i=0; i < triangles.size(); ++i)
00358             {
00359                 *(pIndices++) = static_cast<unsigned int>(triangles[i][0]);
00360         *(pIndices++) = static_cast<unsigned int>(triangles[i][1]);
00361         *(pIndices++) = static_cast<unsigned int>(triangles[i][2]);
00362             }
00363             for (unsigned int i = 0; i < quads.size() ; i++)
00364             {
00365           *(pIndices++) = static_cast<unsigned int>(quads[i][0]);
00366           *(pIndices++) = static_cast<unsigned int>(quads[i][1]);
00367           *(pIndices++) = static_cast<unsigned int>(quads[i][2]);
00368           *(pIndices++) = static_cast<unsigned int>(quads[i][0]);
00369           *(pIndices++) = static_cast<unsigned int>(quads[i][2]);
00370           *(pIndices++) = static_cast<unsigned int>(quads[i][3]);
00371             }
00372             iBuffer->unlock();
00373         }
00374         else
00375         {
00376             unsigned short* pIndices = static_cast<unsigned short*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00377             for (unsigned int i=0; i < triangles.size(); ++i)
00378             {
00379           *(pIndices++) = static_cast<unsigned short>(triangles[i][0]);
00380           *(pIndices++) = static_cast<unsigned short>(triangles[i][1]);
00381           *(pIndices++) = static_cast<unsigned short>(triangles[i][2]);
00382             }
00383             for (unsigned int i = 0; i < quads.size() ; i++)
00384             {
00385           *(pIndices++) = static_cast<unsigned short>(quads[i][0]);
00386           *(pIndices++) = static_cast<unsigned short>(quads[i][1]);
00387           *(pIndices++) = static_cast<unsigned short>(quads[i][2]);
00388           *(pIndices++) = static_cast<unsigned short>(quads[i][0]);
00389           *(pIndices++) = static_cast<unsigned short>(quads[i][2]);
00390           *(pIndices++) = static_cast<unsigned short>(quads[i][3]);
00391             }
00392             iBuffer->unlock();
00393         }
00394     meshRevision = topology->getRevision();
00395     }
00396     else
00397     {
00398         if (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT)
00399         {
00400       iBuffer->writeData(0, this->triangles.size() * sizeof(Triangle), this->triangles.getData());
00401         }
00402         else
00403         {
00404       
00405             unsigned short* pIndices = static_cast<unsigned short*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
00406             for (unsigned int i=0; i < triangles.size(); ++i)
00407             {
00408           *(pIndices++) = static_cast<unsigned short>(triangles[i][0]);
00409           *(pIndices++) = static_cast<unsigned short>(triangles[i][1]);
00410           *(pIndices++) = static_cast<unsigned short>(triangles[i][2]);
00411             }         
00412         for (unsigned int i = 0; i < quads.size() ; i++)
00413             {
00414           *(pIndices++) = static_cast<unsigned short>(this->quads[i][0]);
00415           *(pIndices++) = static_cast<unsigned short>(this->quads[i][1]);
00416           *(pIndices++) = static_cast<unsigned short>(this->quads[i][2]);
00417           *(pIndices++) = static_cast<unsigned short>(this->quads[i][0]);
00418           *(pIndices++) = static_cast<unsigned short>(this->quads[i][2]);
00419           *(pIndices++) = static_cast<unsigned short>(this->quads[i][3]);
00420             }
00421             iBuffer->unlock();
00422         }
00423     
00424     }
00425     
00426 }
00427 
00428 void OgreVisualModel::computeNormals()
00429 {
00430       if (this->vertNormIdx.size() != this->vertices.size())
00431       {
00432           // x has been resized
00433     this->vertNormIdx.resize(this->vertices.size());
00434     for (unsigned int i = 0; i < this->vertices.size(); i++)
00435               this->vertNormIdx[i] = i;
00436       }
00437       if (this->vertices.size() == 0) return; //nothing to do
00438       this->vnormals.resize(this->vertices.size());
00439        for (unsigned int i = 0; i < this->vnormals.size(); i++)
00440            this->vnormals[i].clear();
00441       if (this->useTopology)
00442       {
00443     
00444       sofa::core::componentmodel::topology::BaseMeshTopology* topology = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(getContext()->getTopology());
00445       if (topology != NULL)
00446       {
00447           const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = topology->getTriangles();
00448           const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = topology->getQuads();
00449           for (unsigned int i = 0; i < triangles.size() ; i++)
00450           {
00451         const Coord & v1 = this->vertices[triangles[i][0]];
00452         const Coord & v2 = this->vertices[triangles[i][1]];
00453         const Coord & v3 = this->vertices[triangles[i][2]];
00454               Coord n = cross(v2-v1, v3-v1);
00455               n.normalize();
00456           this->vnormals[vertNormIdx[triangles[i][0]]] += n;
00457           this->vnormals[vertNormIdx[triangles[i][1]]] += n;
00458           this->vnormals[vertNormIdx[triangles[i][2]]] += n;
00459           }
00460           for (unsigned int i = 0; i < quads.size() ; i++)
00461           {
00462         const Coord & v1 = this->vertices[quads[i][0]];
00463         const Coord & v2 = this->vertices[quads[i][1]];
00464         const Coord & v3 = this->vertices[quads[i][3]];
00465               Coord n = cross(v2-v1, v3-v1);
00466               n.normalize();
00467           this->vnormals[vertNormIdx[quads[i][0]]] += n;
00468           this->vnormals[vertNormIdx[quads[i][1]]] += n;
00469           this->vnormals[vertNormIdx[quads[i][2]]] += n;
00470           this->vnormals[vertNormIdx[quads[i][3]]] += n;
00471           }
00472       }
00473       }
00474       else
00475       {   
00476           for (unsigned int i = 0; i < triangles.size() ; i++)
00477           {
00478         const Coord & v1 = this->vertices[triangles[i][0]];
00479         const Coord & v2 = this->vertices[triangles[i][1]];
00480         const Coord & v3 = this->vertices[triangles[i][2]];
00481               Coord n = cross(v2-v1, v3-v1);
00482               n.normalize();
00483           this->vnormals[vertNormIdx[triangles[i][0]]] += n;
00484           this->vnormals[vertNormIdx[triangles[i][1]]] += n;
00485           this->vnormals[vertNormIdx[triangles[i][2]]] += n;
00486           }
00487       }
00488       for (int i = this->vnormals.size()-1; i >=0 ; i--)
00489       {
00490     Coord n = this->vnormals[vertNormIdx[i]];
00491           n.normalize();
00492       this->vnormals[i] = n;
00493       }
00494 }
00495 
00496 void OgreVisualModel::computeBounds()
00497 {
00498     Ogre::Vector3 bbmin, bbmax;
00499     float r2max = 0;
00500     if (this->vertices.size()>0)
00501     {
00502       bbmin = conv(this->vertices[0]);
00503         bbmax = bbmin;
00504     r2max = this->vertices[0].norm2();
00505     for (unsigned int i=1; i<this->vertices.size(); i++)
00506         {
00507       Ogre::Vector3 p = conv(this->vertices[i]);
00508             bbmin.makeFloor(p);
00509             bbmax.makeCeil(p);
00510             float r2 = p.squaredLength();
00511             if (r2 > r2max) r2max = r2;
00512         }
00513     }
00514     else
00515     {
00516         bbmin = Ogre::Vector3(0,0,0);
00517         bbmax = Ogre::Vector3(0,0,0);
00518     }
00519     ogreMesh->_setBounds( Ogre::AxisAlignedBox( bbmin, bbmax ), false );
00520     ogreMesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(r2max));
00521     if (ogreNode)
00522         ogreNode->_updateBounds();
00523 }
00524 
00525 int OgreVisualModelClass = sofa::core::RegisterObject("OGRE 3D Visual Model")
00526 .add < OgreVisualModel >()
00527 ;
00528     }
00529   }
00530 }

Generated on Sun Nov 23 02:28:38 2008 for Sofa by  doxygen 1.5.7.1