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 #include <sofa/component/collision/CubeModel.h>
00026 #include <sofa/core/ObjectFactory.h>
00027 #include <algorithm>
00028 #include <math.h>
00029 #include <sofa/helper/system/gl.h>
00030
00031 namespace sofa
00032 {
00033
00034 namespace component
00035 {
00036
00037 namespace collision
00038 {
00039
00040 SOFA_DECL_CLASS(Cube)
00041
00042 using namespace sofa::defaulttype;
00043
00044 int CubeModelClass = core::RegisterObject("Collision model representing a cube")
00045 .add< CubeModel >()
00046 .addAlias("Cube")
00047 ;
00048
00049 CubeModel::CubeModel()
00050 {
00051 }
00052
00053 void CubeModel::resize(int size)
00054 {
00055 int size0 = this->size;
00056 if (size == size0) return;
00057
00058 CollisionModel* parent = getPrevious();
00059 while(parent != NULL)
00060 {
00061 parent->resize(0);
00062 parent = parent->getPrevious();
00063 }
00064 this->core::CollisionModel::resize(size);
00065 this->elems.resize(size);
00066 this->parentOf.resize(size);
00067
00068 for (int i=size0;i<size;++i)
00069 {
00070 this->elems[i].children.first=core::CollisionElementIterator(getNext(), i);
00071 this->elems[i].children.second=core::CollisionElementIterator(getNext(), i+1);
00072 this->parentOf[i] = i;
00073 }
00074 }
00075
00076 void CubeModel::setParentOf(int childIndex, const Vector3& min, const Vector3& max)
00077 {
00078 int i = parentOf[childIndex];
00079 elems[i].minBBox = min;
00080 elems[i].maxBBox = max;
00081 }
00082
00083 void CubeModel::setLeafCube(int cubeIndex, std::pair<core::CollisionElementIterator,core::CollisionElementIterator> children, const Vector3& min, const Vector3& max)
00084 {
00085 elems[cubeIndex].minBBox = min;
00086 elems[cubeIndex].maxBBox = max;
00087 elems[cubeIndex].children = children;
00088 }
00089
00090 int CubeModel::addCube(Cube subcellsBegin, Cube subcellsEnd)
00091 {
00092 int i = size;
00093 this->core::CollisionModel::resize(size+1);
00094 elems.resize(size+1);
00095
00096 elems[i].subcells.first = subcellsBegin;
00097 elems[i].subcells.second = subcellsEnd;
00098 elems[i].children.first = core::CollisionElementIterator();
00099 elems[i].children.second = core::CollisionElementIterator();
00100 updateCube(i);
00101 return i;
00102 }
00103
00104 void CubeModel::updateCube(int index)
00105 {
00106 const std::pair<Cube,Cube>& subcells = elems[index].subcells;
00107 if (subcells.first != subcells.second)
00108 {
00109 Cube c = subcells.first;
00110 Vector3 minBBox = c.minVect();
00111 Vector3 maxBBox = c.maxVect();
00112 ++c;
00113 while(c != subcells.second)
00114 {
00115 const Vector3& cmin = c.minVect();
00116 const Vector3& cmax = c.maxVect();
00117 for (int j=0;j<3;j++)
00118 {
00119 if (cmax[j] > maxBBox[j]) maxBBox[j] = cmax[j];
00120 if (cmin[j] < minBBox[j]) minBBox[j] = cmin[j];
00121 }
00122 ++c;
00123 }
00124 elems[index].minBBox = minBBox;
00125 elems[index].maxBBox = maxBBox;
00126 }
00127 }
00128
00129 void CubeModel::updateCubes()
00130 {
00131 for (int i=0;i<size;i++)
00132 updateCube(i);
00133 }
00134
00135 void CubeModel::draw(int index)
00136 {
00137 const Vector3& vmin = elems[index].minBBox;
00138 const Vector3& vmax = elems[index].maxBBox;
00139
00140 glBegin(GL_LINES);
00141 {
00142 glVertex3d(vmin[0], vmin[1], vmin[2]);
00143 glVertex3d(vmin[0], vmin[1], vmax[2]);
00144 glVertex3d(vmin[0], vmax[1], vmin[2]);
00145 glVertex3d(vmin[0], vmax[1], vmax[2]);
00146 glVertex3d(vmax[0], vmin[1], vmin[2]);
00147 glVertex3d(vmax[0], vmin[1], vmax[2]);
00148 glVertex3d(vmax[0], vmax[1], vmin[2]);
00149 glVertex3d(vmax[0], vmax[1], vmax[2]);
00150
00151 glVertex3d(vmin[0], vmin[1], vmin[2]);
00152 glVertex3d(vmin[0], vmax[1], vmin[2]);
00153 glVertex3d(vmin[0], vmin[1], vmax[2]);
00154 glVertex3d(vmin[0], vmax[1], vmax[2]);
00155 glVertex3d(vmax[0], vmin[1], vmin[2]);
00156 glVertex3d(vmax[0], vmax[1], vmin[2]);
00157 glVertex3d(vmax[0], vmin[1], vmax[2]);
00158 glVertex3d(vmax[0], vmax[1], vmax[2]);
00159
00160 glVertex3d(vmin[0], vmin[1], vmin[2]);
00161 glVertex3d(vmax[0], vmin[1], vmin[2]);
00162 glVertex3d(vmin[0], vmax[1], vmin[2]);
00163 glVertex3d(vmax[0], vmax[1], vmin[2]);
00164 glVertex3d(vmin[0], vmin[1], vmax[2]);
00165 glVertex3d(vmax[0], vmin[1], vmax[2]);
00166 glVertex3d(vmin[0], vmax[1], vmax[2]);
00167 glVertex3d(vmax[0], vmax[1], vmax[2]);
00168 }
00169 glEnd();
00170 }
00171
00172 void CubeModel::draw()
00173 {
00174 if (!isActive() || !((getNext()==NULL)?getContext()->getShowCollisionModels():getContext()->getShowBoundingCollisionModels())) return;
00175 glDisable(GL_LIGHTING);
00176 int level=0;
00177 CollisionModel* m = getPrevious();
00178 float color = 1.0f;
00179 while (m!=NULL)
00180 {
00181 m = m->getPrevious();
00182 ++level;
00183 color *= 0.5f;
00184 }
00185 if (isSimulated())
00186 glColor4f(1.0f, 1.0f, 1.0f, color);
00187 else
00188 glColor4f(1.0f, 1.0f, 0.0f, color);
00189 if (color < 1.0f)
00190 {
00191 glEnable(GL_BLEND);
00192 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00193 glDepthMask(0);
00194 }
00195 for (int i=0;i<size;i++)
00196 {
00197 draw(i);
00198 }
00199 if (color < 1.0f)
00200 {
00201 glDisable(GL_BLEND);
00202 glDepthMask(1);
00203 }
00204 if (getPrevious()!=NULL)
00205 getPrevious()->draw();
00206 }
00207
00208 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> CubeModel::getInternalChildren(int index) const
00209 {
00210 return elems[index].subcells;
00211 }
00212
00213 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> CubeModel::getExternalChildren(int index) const
00214 {
00215 return elems[index].children;
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 }
00229
00230 bool CubeModel::isLeaf( int index ) const
00231 {
00232 return elems[index].children.first.valid();
00233 }
00234
00235 class CubeModel::CubeSortPredicate
00236 {
00237 int axis;
00238 public:
00239 CubeSortPredicate(int axis) : axis(axis) {}
00240 bool operator()(const CubeData& c1,const CubeData& c2) const
00241 {
00242 double v1 = c1.minBBox[axis]+c1.maxBBox[axis];
00243 double v2 = c2.minBBox[axis]+c2.maxBBox[axis];
00244 return v1 < v2;
00245 }
00246 template<int Axis>
00247 static int sortCube(const void* p1, const void* p2)
00248 {
00249 const CubeModel::CubeData* c1 = (const CubeModel::CubeData*)p1;
00250 const CubeModel::CubeData* c2 = (const CubeModel::CubeData*)p2;
00251 double v1 = c1->minBBox[Axis] + c1->maxBBox[Axis];
00252 double v2 = c2->minBBox[Axis] + c2->maxBBox[Axis];
00253
00254 if (v1 < v2)
00255 return -1;
00256 else if (v1 > v2)
00257 return 1;
00258 else
00259 return 0;
00260 }
00261 };
00262
00263 void CubeModel::computeBoundingTree(int maxDepth)
00264 {
00265
00266 std::list<CubeModel*> levels;
00267 levels.push_front(createPrevious<CubeModel>());
00268 for (int i=0;i<maxDepth;i++)
00269 levels.push_front(levels.front()->createPrevious<CubeModel>());
00270 CubeModel* root = levels.front();
00271
00272
00273 if (root->empty() || root->getPrevious() != NULL)
00274 {
00275
00276
00277
00278 while(root->getPrevious()!=NULL)
00279 {
00280 core::CollisionModel* m = root->getPrevious();
00281 root->setPrevious(m->getPrevious());
00282 delete m;
00283 }
00284
00285 {
00286 for (std::list<CubeModel*>::iterator it = levels.begin(); it != levels.end(); ++it)
00287 (*it)->resize(0);
00288 }
00289
00290
00291 root->addCube(Cube(this,0),Cube(this,size));
00292
00293 std::list<CubeModel*>::iterator it = levels.begin();
00294 CubeModel* level = *it;
00295 ++it;
00296 int lvl = 0;
00297 while(it != levels.end())
00298 {
00299
00300 CubeModel* clevel = *it;
00301 clevel->elems.reserve(level->size*2);
00302 for(Cube cell = Cube(level->begin()); level->end() != cell; ++cell)
00303 {
00304 const std::pair<Cube,Cube>& subcells = cell.subcells();
00305 int ncells = subcells.second.getIndex() - subcells.first.getIndex();
00306
00307 if (ncells > 4)
00308 {
00309
00310 int splitAxis;
00311 Vector3 l = cell.maxVect()-cell.minVect();
00312 int middle = subcells.first.getIndex()+(ncells+1)/2;
00313 if(l[0]>l[1])
00314 if (l[0]>l[2])
00315 splitAxis = 0;
00316 else
00317 splitAxis = 2;
00318 else
00319 if (l[1]>l[2])
00320 splitAxis = 1;
00321 else
00322 splitAxis = 2;
00323
00324
00325
00326 #if defined(__GNUC__) && (__GNUC__ == 4)
00327
00328
00329 if (splitAxis == 0)
00330 qsort(&(elems[subcells.first.getIndex()]), subcells.second.getIndex()-subcells.first.getIndex(), sizeof(elems[0]), CubeSortPredicate::sortCube<0>);
00331 else if (splitAxis == 1)
00332 qsort(&(elems[subcells.first.getIndex()]), subcells.second.getIndex()-subcells.first.getIndex(), sizeof(elems[0]), CubeSortPredicate::sortCube<1>);
00333 else
00334 qsort(&(elems[subcells.first.getIndex()]), subcells.second.getIndex()-subcells.first.getIndex(), sizeof(elems[0]), CubeSortPredicate::sortCube<2>);
00335 #else
00336 CubeSortPredicate sortpred(splitAxis);
00337
00338 std::sort(elems.begin()+subcells.first.getIndex(),elems.begin()+subcells.second.getIndex(), sortpred);
00339 #endif
00340
00341
00342 Cube cmiddle(this, middle);
00343 int c1 = clevel->addCube(subcells.first, cmiddle);
00344 int c2 = clevel->addCube(cmiddle, subcells.second);
00345
00346
00347 level->elems[cell.getIndex()].subcells.first = Cube(clevel,c1);
00348 level->elems[cell.getIndex()].subcells.second = Cube(clevel,c2+1);
00349 }
00350 }
00351 ++it;
00352 level = clevel;
00353 ++lvl;
00354 }
00355
00356 for (int i=0;i<size;i++)
00357 parentOf[elems[i].children.first.getIndex()] = i;
00358 }
00359 else
00360 {
00361
00362 int lvl = 0;
00363 for (std::list<CubeModel*>::reverse_iterator it = levels.rbegin(); it != levels.rend(); it++)
00364 {
00365
00366 (*it)->updateCubes();
00367 ++lvl;
00368 }
00369 }
00370
00371 }
00372
00373 }
00374
00375 }
00376
00377 }
00378