00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef SOFA_HAVE_GLEW
00026 #include <GL/glew.h>
00027 #endif
00028
00029 #include <flowvr/render/mesh.h>
00030
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);
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
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
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
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
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
00338
00339 Real dim2 = dim;
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
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
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
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
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;
00545
00546 updateGrid();
00547
00548 cubeModel->resize(size);
00549 for (int i=0; i<size; i++)
00550 {
00551
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
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);
00580
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
00618
00619
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
00633
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
00659
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
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 }
00749
00750 }
00751
00752 }