CudaDistanceGridCollisionModel.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 #ifdef SOFA_HAVE_GLEW
00026 #include <GL/glew.h>
00027 #endif
00028 //#ifdef SOFA_HAVE_FLOWVR
00029 #include <flowvr/render/mesh.h>
00030 //#endif
00031 #include "CudaDistanceGridCollisionModel.h"
00032 #include <sofa/core/ObjectFactory.h>
00033 #include <sofa/component/collision/CubeModel.h>
00034 #include <fstream>
00035 #include <sofa/helper/gl/template.h>
00036 
00037 namespace sofa
00038 {
00039 
00040 namespace gpu
00041 {
00042 
00043 namespace cuda
00044 {
00045 
00046 SOFA_DECL_CLASS(CudaDistanceGridCollisionModel)
00047 
00048 int CudaRigidDistanceGridCollisionModelClass = core::RegisterObject("GPU-based grid distance field using CUDA")
00049 .add< CudaRigidDistanceGridCollisionModel >()
00050 .addAlias("CudaDistanceGridCollisionModel")
00051 .addAlias("CudaRigidDistanceGrid")
00052 .addAlias("CudaDistanceGrid")
00053 ;
00054 
00055 using namespace defaulttype;
00056 
00060 
00061 CudaDistanceGrid::CudaDistanceGrid(int nx, int ny, int nz, Coord pmin, Coord pmax)
00062 : nbRef(1), nx(nx), ny(ny), nz(nz), nxny(nx*ny), nxnynz(nx*ny*nz)
00063 , pmin(pmin), pmax(pmax)
00064 , cellWidth   ((pmax[0]-pmin[0])/(nx-1), (pmax[1]-pmin[1])/(ny-1),(pmax[2]-pmin[2])/(nz-1))
00065 , invCellWidth((nx-1)/(pmax[0]-pmin[0]), (ny-1)/(pmax[1]-pmin[1]),(nz-1)/(pmax[2]-pmin[2]))
00066 , cubeDim(0)
00067 {
00068     dists.resize(nxnynz);
00069 }
00070 
00071 CudaDistanceGrid::~CudaDistanceGrid()
00072 {
00073     std::map<CudaDistanceGridParams, CudaDistanceGrid*>& shared = getShared();
00074     std::map<CudaDistanceGridParams, CudaDistanceGrid*>::iterator it = shared.begin();
00075     while (it != shared.end() && it->second != this) ++it;
00076     if (it != shared.end())
00077         shared.erase(it); // remove this grid from the list of already loaded grids
00078 }
00079 
00081 CudaDistanceGrid* CudaDistanceGrid::addRef()
00082 {
00083     ++nbRef;
00084     return this;
00085 }
00086 
00088 bool CudaDistanceGrid::release()
00089 {
00090     if (--nbRef != 0)
00091         return false;
00092     delete this;
00093     return true;
00094 }
00095 
00096 CudaDistanceGrid* CudaDistanceGrid::load(const std::string& filename, double scale, int nx, int ny, int nz, Coord pmin, Coord pmax)
00097 {
00098     if (filename == "#cube")
00099     {
00100         float dim = (float)scale;
00101         int np = 5;
00102         Coord bbmin(-dim, -dim, -dim), bbmax(dim,dim,dim);
00103         std::cout << "bbox = <"<<bbmin<<">-<"<<bbmax<<">"<<std::endl;
00104         if (pmin[0]<=pmax[0])
00105         {
00106             pmin = bbmin;
00107             pmax = bbmax;
00108             Coord margin = (bbmax-bbmin)*0.1;
00109             pmin -= margin;
00110             pmax += margin;
00111         }
00112         else
00113         {
00114             for (int c=0; c<3; c++)
00115             {
00116                 if (bbmin[c] < pmin[c]) pmin[c] = bbmin[c];
00117                 if (bbmax[c] > pmax[c]) pmax[c] = bbmax[c];
00118             }
00119         }
00120         std::cout << "Creating cube distance grid in <"<<pmin<<">-<"<<pmax<<">"<<std::endl;
00121         CudaDistanceGrid* grid = new CudaDistanceGrid(nx, ny, nz, pmin, pmax);
00122         grid->calcCubeDistance(dim, np);
00123         std::cout << "Distance grid creation DONE."<<std::endl;
00124         return grid;
00125     }
00126     else if (filename.length()>4 && filename.substr(filename.length()-4) == ".raw")
00127     {
00128         CudaDistanceGrid* grid = new CudaDistanceGrid(nx, ny, nz, pmin, pmax);
00129         std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
00130         in.read((char*)&(grid->dists[0]), grid->nxnynz*sizeof(Real));
00131         if (scale != 1.0)
00132         {
00133             for (int i=0; i< grid->nxnynz; i++)
00134                 grid->dists[i] *= (float)scale;
00135         }
00136         grid->computeBBox();
00137         return grid;
00138     }
00139 //#ifdef SOFA_HAVE_FLOWVR
00140     else if (filename.length()>6 && filename.substr(filename.length()-6) == ".fmesh")
00141     {
00142         flowvr::render::Mesh mesh;
00143         if (!mesh.load(filename.c_str()))
00144         {
00145             std::cerr << "ERROR loading FlowVR mesh file "<<filename<<std::endl;
00146             return NULL;
00147         }
00148         //std::cout << "bbox = "<<mesh.bb<<std::endl;
00149         
00150         if (!mesh.getAttrib(flowvr::render::Mesh::MESH_DISTMAP))
00151         {
00152             std::cerr << "ERROR: FlowVR mesh "<<filename<<" does not contain distance information. Please use flowvr-distmap."<<std::endl;
00153             return NULL;
00154         }
00155         nx = mesh.distmap->nx;
00156         ny = mesh.distmap->ny;
00157         nz = mesh.distmap->nz;
00158         ftl::Vec3f fpmin = ftl::transform(mesh.distmap->mat,ftl::Vec3f(0,0,0))*scale;
00159         ftl::Vec3f fpmax = ftl::transform(mesh.distmap->mat,ftl::Vec3f(nx-1,ny-1,nz-1))*scale;
00160         pmin = Coord(fpmin.ptr());
00161         pmax = Coord(fpmax.ptr());
00162         std::cout << "Copying "<<nx<<"x"<<ny<<"x"<<nz<<" distance grid in <"<<pmin<<">-<"<<pmax<<">"<<std::endl;
00163         CudaDistanceGrid* grid = new CudaDistanceGrid(nx, ny, nz, pmin, pmax);
00164         for (int i=0; i< grid->nxnynz; i++)
00165             grid->dists[i] = mesh.distmap->data[i]*scale;
00166 
00167         if (mesh.getAttrib(flowvr::render::Mesh::MESH_POINTS_GROUP))
00168         {
00169             int nbpos = 0;
00170             for (int i=0;i<mesh.nbg();i++)
00171             {
00172                 if (mesh.getGP0(i) >= 0)
00173                     ++nbpos;
00174             }
00175             std::cout << "Copying "<<nbpos<<" mesh vertices."<<std::endl;
00176             grid->meshPts.resize(nbpos);
00177             int p = 0;
00178             for (int i=0;i<mesh.nbg();i++)
00179             {
00180                 int p0 = mesh.getGP0(i);
00181                 if (p0 >= 0)
00182                     grid->meshPts[p++] = Coord(mesh.getPP(p0).ptr())*scale;
00183             }
00184         }
00185         else
00186         {
00187             int nbpos = mesh.nbp();
00188             std::cout << "Copying "<<nbpos<<" mesh vertices."<<std::endl;
00189             grid->meshPts.resize(nbpos);
00190             for (int i=0;i<nbpos;i++)
00191                 grid->meshPts[i] = Coord(mesh.getPP(i).ptr())*scale;
00192         }
00193         grid->computeBBox();
00194         std::cout << "Distance grid creation DONE."<<std::endl;
00195         return grid;
00196     }
00197 //#endif
00198     else if (filename.length()>4 && filename.substr(filename.length()-4) == ".obj")
00199     {
00200         sofa::helper::io::Mesh* mesh = sofa::helper::io::Mesh::Create(filename);
00201         const sofa::helper::vector<Vector3> & vertices = mesh->getVertices();
00202 
00203         std::cout << "Computing bbox."<<std::endl;
00204         Coord bbmin, bbmax;
00205         if (!vertices.empty())
00206         {
00207             bbmin = vertices[0];
00208             bbmax = bbmin;
00209             for(unsigned int i=1;i<vertices.size();i++)
00210             {
00211                 for (int c=0; c<3; c++)
00212                     if (vertices[i][c] < bbmin[c]) bbmin[c] = (Real)vertices[i][c];
00213                     else if (vertices[i][c] > bbmax[c]) bbmax[c] = (Real)vertices[i][c];
00214             }
00215             bbmin *= scale;
00216             bbmax *= scale;
00217         }
00218         std::cout << "bbox = <"<<bbmin<<">-<"<<bbmax<<">"<<std::endl;
00219 
00220         if (pmin[0]<=pmax[0])
00221         {
00222             pmin = bbmin;
00223             pmax = bbmax;
00224             Coord margin = (bbmax-bbmin)*0.1;
00225             pmin -= margin;
00226             pmax += margin;
00227         }
00228         else if (!vertices.empty())
00229         {
00230             for (int c=0; c<3; c++)
00231             {
00232                 if (bbmin[c] < pmin[c]) pmin[c] = bbmin[c];
00233                 if (bbmax[c] > pmax[c]) pmax[c] = bbmax[c];
00234             }
00235         }
00236         std::cout << "Creating distance grid in <"<<pmin<<">-<"<<pmax<<">"<<std::endl;
00237         CudaDistanceGrid* grid = new CudaDistanceGrid(nx, ny, nz, pmin, pmax);
00238         std::cout << "Copying "<<vertices.size()<<" mesh vertices."<<std::endl;
00239         grid->meshPts.resize(vertices.size());
00240         for(unsigned int i=0;i<vertices.size();i++)
00241             grid->meshPts[i] = vertices[i]*scale;
00242         const sofa::helper::vector<sofa::helper::vector<sofa::helper::vector<int> > > & facets = mesh->getFacets();
00243         int nbt = 0;
00244         int nbq = 0;
00245         for (unsigned int i=0; i<facets.size(); i++)
00246         {
00247         const sofa::helper::vector<int>& pts = facets[i][0];
00248             if (pts.size() == 4)
00249                 ++nbq;
00250             else if (pts.size() >= 3)
00251                 nbt += pts.size()-2;
00252         }
00253         grid->meshTriangles.resize(nbt);
00254         grid->meshQuads.resize(nbq);
00255         nbt=0;
00256         nbq=0;
00257         for (unsigned int i=0; i<facets.size(); i++)
00258         {
00259         const sofa::helper::vector<int>& pts = facets[i][0];
00260             if (pts.size() == 4)
00261                 grid->meshQuads[nbq++] = sofa::core::componentmodel::topology::BaseMeshTopology::Quad(pts[0],pts[1],pts[2],pts[3]);
00262             else if (pts.size() >= 3)
00263                 for (unsigned int j=2; j<pts.size(); j++)
00264                     grid->meshTriangles[nbt++] = sofa::core::componentmodel::topology::BaseMeshTopology::Triangle(pts[0],pts[j-1],pts[j]);
00265         }
00266         std::cout << "Computing distance field."<<std::endl;
00267         grid->calcDistance();
00268         grid->computeBBox();
00269         std::cout << "Distance grid creation DONE."<<std::endl;
00270         delete mesh;
00271         return grid;
00272     }
00273     else
00274     {
00275         std::cerr << "Unknown extension: "<<filename<<std::endl;
00276         return NULL;
00277     }
00278 }
00279 
00280 bool CudaDistanceGrid::save(const std::string& filename)
00281 {
00283     if (filename.length()>4 && filename.substr(filename.length()-4) == ".raw")
00284     {
00285     std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary);
00286     out.write((const char*)&(dists[0]), nxnynz*sizeof(Real));
00287     }
00288     else
00289     {
00290     std::cerr << " CudaDistanceGrid::save(): Unsupported extension: "<<filename<<std::endl;
00291     return false;
00292     }
00293     return true;
00294 }
00295 
00296 
00297 void CudaDistanceGrid::computeBBox()
00298 {
00299     if (!meshPts.empty())
00300     {
00301         bbmin = meshPts[0];
00302         bbmax = bbmin;
00303         for(unsigned int i=1;i<meshPts.size();i++)
00304         {
00305             for (int c=0; c<3; c++)
00306                 if (meshPts[i][c] < bbmin[c]) bbmin[c] = (Real)meshPts[i][c];
00307                 else if (meshPts[i][c] > bbmax[c]) bbmax[c] = (Real)meshPts[i][c];
00308         }
00309     }
00310     else
00311     {
00312         bbmin = pmin;
00313         bbmax = pmax;
00315     }
00316 }
00317 
00318 
00321 void CudaDistanceGrid::calcCubeDistance(Real dim, int np)
00322 {
00323     cubeDim = dim;
00324     if (np > 1)
00325     {
00326         int nbp = np*np*np - (np-2)*(np-2)*(np-2);
00327         //std::cout << "Copying "<<nbp<<" cube vertices."<<std::endl;
00328         meshPts.resize(nbp);
00329         
00330         for (int i=0,z=0; z<np; z++)
00331         for (int y=0; y<np; y++)
00332         for (int x=0; x<np; x++)
00333             if (z==0 || z==np-1 || y==0 || y==np-1 || x==0 || x==np-1)
00334                 meshPts[i++] = Coord(x*dim*2/(np-1) - dim, y*dim*2/(np-1) - dim, z*dim*2/(np-1) - dim);
00335     }
00336 
00337     //std::cout << "Computing distance field."<<std::endl;
00338 
00339     Real dim2 = dim; //*0.75f; // add some 'roundness' to the cubes corner
00340 
00341     for (int i=0,z=0; z<nz; z++)
00342     for (int y=0; y<ny; y++)
00343     for (int x=0; x<nx; x++,i++)
00344     {
00345         Coord p = coord(x,y,z);
00346         Coord s = p;
00347         bool out = false;
00348         for (int c=0;c<3;c++)
00349         {
00350                  if (s[c] < -dim2) { s[c] = -dim2; out = true; }
00351             else if (s[c] >  dim2) { s[c] =  dim2; out = true; }
00352         }
00353         Real d;
00354         if (out)
00355             d = (p - s).norm();
00356         else
00357             d = helper::rmax(helper::rmax(helper::rabs(s[0]),helper::rabs(s[1])),helper::rabs(s[2])) - dim2;
00358         dists[i] = d - (dim-dim2);
00359     }
00360     //computeBBox();
00361     bbmin = Coord(-dim,-dim,-dim);
00362     bbmax = Coord( dim, dim, dim);
00363 }
00364 
00366 void CudaDistanceGrid::calcDistance()
00367 {
00368 #ifdef SOFA_HAVE_GLEW
00369 
00370     if (GLEW_EXT_framebuffer_object && GLEW_ARB_vertex_buffer_object)
00371     {
00372         static GLuint fbid = 0;
00373         if (!fbid)
00374         {
00375         glGenFramebuffersEXT(1,&fbid);
00376         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
00377         }
00378 
00379         /*
00380         if (!texcolor)
00381         glGenTextures(1, &texcolor);
00382         
00383         glBindTexture(target, texcolor);
00384         
00385         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00386         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00387         glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00388         glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00389         glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00390         glTexImage2D(target, 0, GL_RGBA8, nx, ny, 0,
00391              GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00392 
00393         if (!texdepth)
00394         glGenTextures(1, &texdepth);
00395             glBindTexture(target, texdepth);
00396         
00397         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00398         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00399         glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00400         glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00401         glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00402         glTexImage2D(target, 0, GL_DEPTH_COMPONENT24, nx, ny, 0,
00403              GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
00404 
00405         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texcolor, 0);*/
00406     }
00407     else
00408     {
00409         std::cerr << "ERROR: Unsupported OpenGL extensions EXT_framebuffer_object ARB_vertex_buffer_object" << std::endl;
00410     }
00411 
00412 #else
00413     std::cerr << "ERROR: CudaDistanceGrid::calcDistance requires GLEW to access OpenGL extensions" << std::endl;
00414 
00415 #endif
00416 }
00417 
00418 CudaDistanceGrid* CudaDistanceGrid::loadShared(const std::string& filename, double scale, int nx, int ny, int nz, Coord pmin, Coord pmax)
00419 {
00420     CudaDistanceGridParams params;
00421     params.filename = filename;
00422     params.scale = scale;
00423     params.nx = nx;
00424     params.ny = ny;
00425     params.nz = nz;
00426     params.pmin = pmin;
00427     params.pmax = pmax;
00428     std::map<CudaDistanceGridParams, CudaDistanceGrid*>& shared = getShared();
00429     std::map<CudaDistanceGridParams, CudaDistanceGrid*>::iterator it = shared.find(params);
00430     if (it != shared.end())
00431         return it->second->addRef();
00432     else
00433     {
00434         return shared[params] = load(filename, scale, nx, ny, nz, pmin, pmax);
00435     }
00436 }
00437 
00438 std::map<CudaDistanceGrid::CudaDistanceGridParams, CudaDistanceGrid*>& CudaDistanceGrid::getShared()
00439 {
00440     static std::map<CudaDistanceGridParams, CudaDistanceGrid*> instance;
00441     return instance;
00442 }
00443 
00444 
00448 
00449 CudaRigidDistanceGridCollisionModel::CudaRigidDistanceGridCollisionModel()
00450 : modified(true)
00451 , filename( initData( &filename, "filename", "load distance grid from specified file"))
00452 , scale( initData( &scale, 1.0, "scale", "scaling factor for input file"))
00453 , box( initData( &box, "box", "Field bounding box defined by xmin,ymin,zmin, xmax,ymax,zmax") )
00454 , nx( initData( &nx, 64, "nx", "number of values on X axis") )
00455 , ny( initData( &ny, 64, "ny", "number of values on Y axis") )
00456 , nz( initData( &nz, 64, "nz", "number of values on Z axis") )
00457 , dumpfilename( initData( &dumpfilename, "dumpfilename","write distance grid to specified file"))
00458 , usePoints( initData( &usePoints, true, "usePoints", "use mesh vertices for collision detection"))
00459 {
00460     rigid = NULL;
00461 }
00462 
00463 CudaRigidDistanceGridCollisionModel::~CudaRigidDistanceGridCollisionModel() 
00464 {
00465     for (unsigned int i=0; i<elems.size(); i++)
00466     {
00467         if (elems[i].grid!=NULL) elems[i].grid->release();
00468         if (elems[i].prevGrid!=NULL) elems[i].prevGrid->release();
00469     }
00470 }
00471 
00472 void CudaRigidDistanceGridCollisionModel::init()
00473 {
00474     std::cout << "> CudaRigidDistanceGridCollisionModel::init()"<<std::endl;
00475     this->core::CollisionModel::init();
00476     rigid = dynamic_cast< core::componentmodel::behavior::MechanicalState<RigidTypes>* > (getContext()->getMechanicalState());
00477 
00478     CudaDistanceGrid* grid = NULL;
00479     if (filename.getValue().empty())
00480     {
00481         if (elems.size()==0 || elems[0].grid==NULL)
00482             std::cerr << "ERROR: CudaRigidDistanceGridCollisionModel requires an input filename.\n";
00483         // else the grid has already been set
00484         return;
00485     }
00486     std::cout << "CudaRigidDistanceGridCollisionModel: creating "<<nx.getValue()<<"x"<<ny.getValue()<<"x"<<nz.getValue()<<" DistanceGrid from file "<<filename.getValue();
00487     if (scale.getValue()!=1.0) std::cout<<" scale="<<scale.getValue();
00488     if (box.getValue()[0][0]<box.getValue()[1][0]) std::cout<<" bbox=<"<<box.getValue()[0]<<">-<"<<box.getValue()[0]<<">";
00489     std::cout << std::endl;
00490     grid = CudaDistanceGrid::loadShared(filename.getValue(), scale.getValue(), nx.getValue(),ny.getValue(),nz.getValue(),box.getValue()[0],box.getValue()[1]);
00491 
00492     resize(1);
00493     elems[0].grid = grid;
00494     if (grid && !dumpfilename.getValue().empty())
00495     {
00496         std::cout << "CudaRigidDistanceGridCollisionModel: dump grid to "<<dumpfilename.getValue()<<std::endl;
00497         grid->save(dumpfilename.getValue());
00498     }
00499     std::cout << "< CudaRigidDistanceGridCollisionModel::init()"<<std::endl;
00500 }
00501 
00502 void CudaRigidDistanceGridCollisionModel::resize(int s)
00503 {
00504     this->core::CollisionModel::resize(s);
00505     elems.resize(s);
00506 }
00507 
00508 void CudaRigidDistanceGridCollisionModel::setGrid(CudaDistanceGrid* surf, int index)
00509 {
00510     if (elems[index].grid == surf) return;
00511     if (elems[index].grid!=NULL) elems[index].grid->release();
00512     elems[index].grid = surf->addRef();
00513     modified = true;
00514 }
00515 
00516 void CudaRigidDistanceGridCollisionModel::setNewState(int index, double dt, CudaDistanceGrid* grid, const Matrix3& rotation, const Vector3& translation)
00517 {
00518     grid->addRef();
00519     if (elems[index].prevGrid!=NULL)
00520         elems[index].prevGrid->release();
00521     elems[index].prevGrid = elems[index].grid;
00522     elems[index].grid = grid;
00523     elems[index].prevRotation = elems[index].rotation;
00524     elems[index].rotation = rotation;
00525     elems[index].prevTranslation = elems[index].translation;
00526     elems[index].translation = translation;
00527     if (!elems[index].isTransformed)
00528     {
00529         Matrix3 I; I.identity();
00530         if (!(rotation == I) || !(translation == Vector3()))
00531             elems[index].isTransformed = true;
00532     }
00533     elems[index].prevDt = dt;
00534     modified = true;
00535 }
00536 
00537 using sofa::component::collision::CubeModel;
00538 
00540 void CudaRigidDistanceGridCollisionModel::computeBoundingTree(int maxDepth)
00541 {
00542     CubeModel* cubeModel = this->createPrevious<CubeModel>();
00543     
00544     if (!modified && !isMoving() && !cubeModel->empty()) return; // No need to recompute BBox if immobile
00545     
00546     updateGrid();
00547     
00548     cubeModel->resize(size);
00549     for (int i=0; i<size; i++)
00550     {
00551         //static_cast<DistanceGridCollisionElement*>(elems[i])->recalcBBox();
00552         Vector3 emin, emax;
00553         if (rigid)
00554         {
00555             const RigidTypes::Coord& xform = (*rigid->getX())[i];
00556             elems[i].translation = xform.getCenter();
00557             xform.getOrientation().toMatrix(elems[i].rotation);
00558             elems[i].isTransformed = true;
00559         }
00560         if (elems[i].isTransformed)
00561         {
00562             //std::cout << "Grid "<<i<<" transformation: <"<<elems[i].rotation<<"> x + <"<<elems[i].translation<<">"<<std::endl;
00563             Vector3 corner = elems[i].translation + elems[i].rotation * elems[i].grid->getBBCorner(0);
00564             emin = corner;
00565             emax = emin;
00566             for (int j=1; j<8; j++)
00567             {
00568                 corner = elems[i].translation + elems[i].rotation * elems[i].grid->getBBCorner(j);
00569                 for(int c=0; c<3; c++)
00570                     if (corner[c] < emin[c]) emin[c] = corner[c];
00571                     else if (corner[c] > emax[c]) emax[c] = corner[c];
00572             }
00573         }
00574         else
00575         {
00576             emin = elems[i].grid->getBBMin();
00577             emax = elems[i].grid->getBBMax();
00578         }
00579         cubeModel->setParentOf(i, emin, emax); // define the bounding box of the current element
00580         //std::cout << "Grid "<<i<<" within  <"<<emin<<">-<"<<emax<<">"<<std::endl;
00581     }
00582     cubeModel->computeBoundingTree(maxDepth);
00583     modified = false;
00584 }
00585 
00586 void CudaRigidDistanceGridCollisionModel::updateGrid()
00587 {
00588 }
00589 
00590 void CudaRigidDistanceGridCollisionModel::draw()
00591 {
00592     if (!isActive()) return;
00593     if (getContext()->getShowCollisionModels())
00594     {
00595         if (getContext()->getShowWireFrame())
00596             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00597         glDisable(GL_LIGHTING);
00598         glColor4fv(getColor4f());
00599         glPointSize(3);
00600         for (unsigned int i=0;i<elems.size();i++)
00601         {
00602             draw(i);
00603         }
00604         glPointSize(1);
00605         if (getContext()->getShowWireFrame())
00606             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00607     }
00608     if (getPrevious()!=NULL)
00609         getPrevious()->draw();
00610 }
00611 
00612 void CudaRigidDistanceGridCollisionModel::draw(int index)
00613 {
00614     if (elems[index].isTransformed)
00615     {
00616         glPushMatrix();
00617         // float m[16];
00618         // (*rigid->getX())[index].writeOpenGlMatrix( m );
00619         // glMultMatrixf(m);
00620         Matrix4 m;
00621         m.identity();
00622         m = elems[index].rotation;
00623         m.transpose();
00624         m[3] = Vector4(elems[index].translation,1.0);
00625         helper::gl::glMultMatrix(m.ptr());
00626     }
00627 
00628     CudaDistanceGrid* grid = getGrid(index);
00629     CudaDistanceGrid::Coord corners[8];
00630     for(unsigned int i=0; i<8; i++)
00631     corners[i] = grid->getCorner(i);
00632     //glEnable(GL_BLEND);
00633     //glDepthMask(0);
00634     if (!isMoving())
00635     glColor4f(0.25f, 0.25f, 0.25f, 0.1f);
00636     else
00637     glColor4f(0.5f, 0.5f, 0.5f, 0.1f);
00638     glBegin(GL_LINES);
00639     {
00640     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[4].ptr());
00641     glVertex3fv(corners[1].ptr()); glVertex3fv(corners[5].ptr());
00642     glVertex3fv(corners[2].ptr()); glVertex3fv(corners[6].ptr());
00643     glVertex3fv(corners[3].ptr()); glVertex3fv(corners[7].ptr());
00644     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[2].ptr());
00645     glVertex3fv(corners[1].ptr()); glVertex3fv(corners[3].ptr());
00646     glVertex3fv(corners[4].ptr()); glVertex3fv(corners[6].ptr());
00647     glVertex3fv(corners[5].ptr()); glVertex3fv(corners[7].ptr());
00648     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[1].ptr());
00649     glVertex3fv(corners[2].ptr()); glVertex3fv(corners[3].ptr());
00650     glVertex3fv(corners[4].ptr()); glVertex3fv(corners[5].ptr());
00651     glVertex3fv(corners[6].ptr()); glVertex3fv(corners[7].ptr());
00652     }
00653     glEnd();
00654     glDisable(GL_BLEND);
00655     glDepthMask(1);
00656     for(unsigned int i=0; i<8; i++)
00657     corners[i] = grid->getBBCorner(i);
00658     //glEnable(GL_BLEND);
00659     //glDepthMask(0);
00660 
00661     if (!isMoving())
00662     glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
00663     else
00664     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00665     glBegin(GL_LINES);
00666     {
00667     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[4].ptr());
00668     glVertex3fv(corners[1].ptr()); glVertex3fv(corners[5].ptr());
00669     glVertex3fv(corners[2].ptr()); glVertex3fv(corners[6].ptr());
00670     glVertex3fv(corners[3].ptr()); glVertex3fv(corners[7].ptr());
00671     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[2].ptr());
00672     glVertex3fv(corners[1].ptr()); glVertex3fv(corners[3].ptr());
00673     glVertex3fv(corners[4].ptr()); glVertex3fv(corners[6].ptr());
00674     glVertex3fv(corners[5].ptr()); glVertex3fv(corners[7].ptr());
00675     glVertex3fv(corners[0].ptr()); glVertex3fv(corners[1].ptr());
00676     glVertex3fv(corners[2].ptr()); glVertex3fv(corners[3].ptr());
00677     glVertex3fv(corners[4].ptr()); glVertex3fv(corners[5].ptr());
00678     glVertex3fv(corners[6].ptr()); glVertex3fv(corners[7].ptr());
00679     }
00680     glEnd();
00681 
00682     const float mindist = -(grid->getPMax()-grid->getPMin()).norm()*0.1f;
00683     const float maxdist = (grid->getPMax()-grid->getPMin()).norm()*0.025f;
00684 
00685     if (grid->meshPts.empty())
00686     {
00687         glBegin(GL_POINTS);
00688         {
00689             for (int z=0, ind=0; z<grid->getNz(); z++)
00690             for (int y=0; y<grid->getNy(); y++)
00691             for (int x=0; x<grid->getNx(); x++, ind++)
00692             {
00693                 CudaDistanceGrid::Coord p = grid->coord(x,y,z);
00694                 CudaDistanceGrid::Real d = (*grid)[ind];
00695                 if (d < mindist || d > maxdist) continue;
00696                 d /= maxdist;
00697                 if (d<0)
00698                     glColor3d(1+d*0.25, 0, 1+d);
00699                 else
00700                     glColor3d(0, 1-d*0.25, 1-d);
00701                 glVertex3fv(p.ptr());
00702             }
00703         }
00704         glEnd();
00705     }
00706     else
00707     {
00708         glColor3d(1, 1 ,1);
00709         glBegin(GL_POINTS);
00710         for (unsigned int i=0; i<grid->meshPts.size();i++)
00711         {
00712             glVertex3fv(grid->meshPts[i].ptr());
00713         }
00714         glEnd();
00715         glBegin(GL_LINES);
00716         for (unsigned int i=0; i<grid->meshPts.size();i++)
00717         {
00718             CudaDistanceGrid::Coord p ( grid->meshPts[i].ptr() );
00719             glColor3d(1, 1 ,1);
00720             CudaDistanceGrid::Coord grad = grid->grad(p);
00721             grad.normalize();
00722             for (int j = -2; j <= 2; j++)
00723             {
00724                 CudaDistanceGrid::Coord p2 = p + grad * (j*maxdist/2);
00725                 CudaDistanceGrid::Real d = grid->eval(p2);
00726                 //if (rabs(d) > maxdist) continue;
00727                 d /= maxdist;
00728                 if (d<0)
00729                     glColor3d(1+d*0.25, 0, 1+d);
00730                 else
00731                     glColor3d(0, 1-d*0.25, 1-d);
00732                 glVertex3fv(p2.ptr());
00733                 if (j>-2 && j < 2)
00734                     glVertex3fv(p2.ptr());
00735             }
00736         }
00737         glEnd();
00738     }
00739     if (elems[index].isTransformed)
00740     {
00741         glPopMatrix();
00742     }
00743 }
00744 
00745 
00746 
00747 
00748 } // namespace cuda
00749 
00750 } // namespace gpu
00751 
00752 } // namespace sofa

Generated on Sun Nov 23 03:58:24 2008 for Sofa by  doxygen 1.5.7.1