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/TriangleModel.h>
00026 #include <sofa/component/collision/TriangleOctree.h>
00027 #include <sofa/component/collision/CubeModel.h>
00028 #include <sofa/component/collision/RayTriangleIntersection.h>
00029 #include <sofa/component/collision/RayTriangleIntersection.h>
00030
00031 #include <sofa/component/collision/Triangle.h>
00032 #include <sofa/core/CollisionElement.h>
00033 #include <sofa/core/ObjectFactory.h>
00034 #include <vector>
00035 #include <sofa/helper/system/thread/CTime.h>
00036
00037 #include <cmath>
00038 #include <sofa/helper/system/gl.h>
00039 #include <sofa/helper/system/glut.h>
00040
00041
00042 namespace sofa
00043 {
00044
00045 namespace component
00046 {
00047
00048 namespace collision
00049 {
00050
00051 using sofa::helper::system::thread::CTime;
00052 using sofa::helper::system::thread::ctime_t;
00053
00054 TriangleOctree::~TriangleOctree (){
00055 for(int i=0;i<8;i++)
00056 {
00057 if(childVec[i]){
00058 delete childVec[i];
00059 childVec[i]=NULL;
00060 }
00061 }
00062 }
00063 void TriangleOctree::draw ()
00064 {
00065
00066 Vector3 center;
00067 if ( objects.size ())
00068 {
00069 center =
00070 (Vector3 (x, y, z) + Vector3 (size / 2, size / 2, size / 2));
00071 glPushMatrix ();
00072 glTranslatef (center[0], center[1], center[2]);
00073 glutWireCube (size);
00074 glPopMatrix ();
00075 }
00076 for (int i = 0; i < 8; i++)
00077 {
00078 if (childVec[i])
00079 childVec[i]->draw ();
00080 }
00081 }
00082
00083 void TriangleOctree::insert (double _x, double _y, double _z,
00084 double inc, int t)
00085 {
00086
00087
00088 if (inc >= size)
00089 {
00090 objects.push_back (t);
00091 }
00092 else
00093 {
00094
00095 double size2 = size / 2;
00096 int dx = (_x >= (x + size2)) ? 1 : 0;
00097 int dy = (_y >= (y + size2)) ? 1 : 0;
00098 int dz = (_z >= (z + size2)) ? 1 : 0;
00099
00100 int i = dx * 4 + dy * 2 + dz;
00101 if (!childVec[i])
00102 {
00103 is_leaf = false;
00104 childVec[i] =
00105 new TriangleOctree (tm, x + dx * size2, y + dy * size2,
00106 z + dz * size2, size2);
00107 }
00108
00109 childVec[i]->insert (_x, _y, _z, inc, t);
00110 }
00111 }
00112
00113 inline
00114 unsigned int choose_next (double x, double y, double z,
00115 unsigned int a, unsigned int b,
00116 unsigned int c)
00117 {
00118 if (x < y)
00119 {
00120 if (x < z)
00121 return a;
00122 else
00123 return c;
00124 }
00125 else
00126 {
00127 if (y < z)
00128 return b;
00129 else
00130 return c;
00131 }
00132 }
00133
00134 int TriangleOctree::nearestTriangle (int minIndex,
00135 const Vector3 & origin,
00136 const Vector3 & direction, traceResult &result)
00137 {
00138 static RayTriangleIntersection intersectionSolver;
00139 Vector3 P;
00140 Triangle t1 (tm, minIndex);
00141 double minDist;
00142 double t, u, v;
00143 if (intersectionSolver.NewComputation (&t1, origin, direction, t, u, v))
00144 {
00145 result.u=u;
00146 result.v=v;
00147 result.t=minDist = t;
00148
00149 }
00150 else
00151 {
00152 minDist = 10e8;
00153
00154 minIndex = -1;
00155 }
00156 for (unsigned int i = 0; i < objects.size (); i++)
00157 {
00158
00159 Triangle t2 (tm, objects[i]);
00160 if (!intersectionSolver.
00161 NewComputation (&t2, origin, direction, t, u, v))
00162 continue;
00163
00164 if (t < minDist)
00165 {
00166
00167 result.u=u;
00168 result.v=v;
00169 result.t=minDist = t;
00170
00171 minIndex = objects[i];
00172
00173 }
00174
00175
00176 }
00177
00178
00179 if (minIndex < 0) return minIndex;
00180
00181
00182 int pointR=-1;
00183 Triangle t3(tm,minIndex);
00184 if(result.u>0.99)
00185 pointR=t3.p2Index();
00186
00187 if(result.v>0.99)
00188 pointR=t3.p3Index();
00189 if((result.u+result.v)<0.01)
00190 pointR=t3.p1Index();
00191 if(0&&pointR!=-1){
00192
00193 double cosAng=dot(direction,t3.n());
00194
00195 for(unsigned int i=0;i<tm->pTri[pointR].size();i++)
00196 {
00197 Triangle t2(tm,tm->pTri[pointR][i]);
00198 double cosAng2=dot(direction,t2.n());
00199 if(cosAng2>cosAng){
00200 cosAng=cosAng2;
00201 minIndex=tm->pTri[pointR][i];
00202 }
00203
00204
00205 }
00206
00207 }
00208
00209 return minIndex;
00210 }
00211
00212 int TriangleOctree::trace (const Vector3 & origin,
00213 const Vector3 & direction, double tx0,
00214 double ty0, double tz0, double tx1,
00215 double ty1, double tz1, unsigned int a,
00216 unsigned int b,Vector3 &origin1,Vector3 &direction1,traceResult &result)
00217 {
00218
00219
00220 if (tx1 < 0.0 || ty1 < 0.0 || tz1 < 0.0)
00221 return -1;
00222
00223
00224 if (is_leaf)
00225 {
00226 if (objects.size ())
00227 {
00228
00229 return nearestTriangle (objects[0], origin1, direction1,result);
00230
00231 }
00232 else
00233 {
00234 return -1;
00235 }
00236 }
00237
00238 const double &x0 = x;
00239 const double &y0 = y;
00240 const double &z0 = z;
00241 const double &x1 = x + size;
00242 const double &y1 = y + size;
00243 const double &z1 = z + size;
00244 const double INF = 1e9;
00245
00246 double txm=0, tym=0, tzm=0;
00247
00248 switch (b)
00249 {
00250 case 0:
00251 txm = 0.5 * (tx0 + tx1);
00252 tym = 0.5 * (ty0 + ty1);
00253 tzm = 0.5 * (tz0 + tz1);
00254 break;
00255 case 1:
00256 txm = 0.5 * (tx0 + tx1);
00257 tym = 0.5 * (ty0 + ty1);
00258 tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00259 break;
00260 case 2:
00261 txm = 0.5 * (tx0 + tx1);
00262 tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00263 tzm = 0.5 * (tz0 + tz1);
00264 break;
00265 case 3:
00266 txm = 0.5 * (tx0 + tx1);
00267 tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00268 tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00269 break;
00270 case 4:
00271 txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00272 tym = 0.5 * (ty0 + ty1);
00273 tzm = 0.5 * (tz0 + tz1);
00274 break;
00275 case 5:
00276 txm = (origin[0] < (0.5 * (x0 + x1)) )? +INF : -INF;
00277 tym = 0.5 * (ty0 + ty1);
00278 tzm = (origin[2] < (0.5 * (z0 + z1) ))? +INF : -INF;
00279 break;
00280 case 6:
00281 txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00282 tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00283 tzm = 0.5 * (tz0 + tz1);
00284 break;
00285 case 7:
00286 txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00287 tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00288 tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00289 break;
00290 default:
00291 assert (!"Internal failure.");
00292 }
00293 unsigned int current_octant = 0;
00294
00295 if (tx0 > ty0)
00296 {
00297 if (tx0 > tz0)
00298 {
00299
00300 if (tym < tx0)
00301 current_octant |= 2;
00302 if (tzm < tx0)
00303 current_octant |= 1;
00304 }
00305 else
00306 {
00307
00308 if (txm < tz0)
00309 current_octant |= 4;
00310 if (tym < tz0)
00311 current_octant |= 2;
00312 }
00313 }
00314 else
00315 {
00316 if (ty0 > tz0)
00317 {
00318
00319 if (txm < ty0)
00320 current_octant |= 4;
00321 if (tzm < ty0)
00322 current_octant |= 1;
00323 }
00324 else
00325 {
00326
00327 if (txm < tz0)
00328 current_octant |= 4;
00329 if (tym < tz0)
00330 current_octant |= 2;
00331 }
00332 }
00333
00334
00335 const unsigned int END = 8;
00336
00337 while (true)
00338 {
00339 int idxMin=-1;
00340 switch (current_octant)
00341 {
00342 case 0:
00343 if (childVec[a])
00344 {
00345 idxMin =
00346 childVec[a]->trace (origin, direction, tx0, ty0, tz0,
00347 txm, tym, tzm, a, b,origin1,direction1,result);
00348 if (idxMin != -1)
00349 return nearestTriangle (idxMin, origin1, direction1,result);
00350 }
00351 current_octant = choose_next (txm, tym, tzm, 4, 2, 1);
00352 break;
00353
00354
00355
00356
00357 case 1:
00358 if (childVec[1 ^ a])
00359 {
00360 idxMin =
00361 childVec[1 ^ a]->trace (origin, direction, tx0, ty0,
00362 tzm, txm, tym, tz1, a, b,origin1,direction1,result);
00363 if (idxMin != -1)
00364 return nearestTriangle (idxMin, origin1, direction1,result);
00365 }
00366 current_octant = choose_next (txm, tym, tz1, 5, 3, END);
00367 break;
00368
00369
00370
00371 case 2:
00372 if (childVec[2 ^ a])
00373 {
00374 idxMin =
00375 childVec[2 ^ a]->trace (origin, direction, tx0, tym,
00376 tz0, txm, ty1, tzm, a, b,origin1,direction1,result);
00377 if (idxMin != -1)
00378 return nearestTriangle (idxMin, origin1, direction1,result);
00379 }
00380 current_octant = choose_next (txm, ty1, tzm, 6, END, 3);
00381 break;
00382 case 3:
00383 if (childVec[3 ^ a])
00384 {
00385 idxMin =
00386 childVec[3 ^ a]->trace (origin, direction, tx0, tym,
00387 tzm, txm, ty1, tz1, a, b,origin1,direction1,result);
00388 if (idxMin != -1)
00389 return nearestTriangle (idxMin, origin1, direction1,result);
00390 }
00391 current_octant = choose_next (txm, ty1, tz1, 7, END, END);
00392 break;
00393 case 4:
00394 if (childVec[4 ^ a])
00395 {
00396 idxMin =
00397 childVec[4 ^ a]->trace (origin, direction, txm, ty0,
00398 tz0, tx1, tym, tzm, a, b,origin1,direction1,result);
00399 if (idxMin != -1)
00400 return nearestTriangle (idxMin, origin1, direction1,result);
00401 }
00402 current_octant = choose_next (tx1, tym, tzm, END, 6, 5);
00403 break;
00404 case 5:
00405 if (childVec[5 ^ a])
00406 {
00407 idxMin =
00408 childVec[5 ^ a]->trace (origin, direction, txm, ty0,
00409 tzm, tx1, tym, tz1, a, b,origin1,direction1,result);
00410 if (idxMin != -1)
00411 return nearestTriangle (idxMin, origin1, direction1,result);
00412 }
00413 current_octant = choose_next (tx1, tym, tz1, END, 7, END);
00414 break;
00415 case 6:
00416 if (childVec[6 ^ a])
00417 {
00418 idxMin =
00419 childVec[6 ^ a]->trace (origin, direction, txm, tym,
00420 tz0, tx1, ty1, tzm, a, b,origin1,direction1,result);
00421 if (idxMin != -1)
00422 return nearestTriangle (idxMin, origin1, direction1,result);
00423 }
00424 current_octant = choose_next (tx1, ty1, tzm, END, END, 7);
00425 break;
00426 case 7:
00427 if (childVec[7 ^ a])
00428 {
00429 idxMin =
00430 childVec[7 ^ a]->trace (origin, direction, txm, tym,
00431 tzm, tx1, ty1, tz1, a, b,origin1,direction1,result);
00432 if (idxMin != -1)
00433 return nearestTriangle (idxMin, origin1, direction1,result);
00434 }
00435 case END:
00436 if(idxMin==-1&&objects.size())
00437 return nearestTriangle (objects[0], origin1, direction1,result);
00438 return idxMin;
00439 }
00440 }
00441
00442
00443 }
00444
00445
00446 int TriangleOctree::trace (Vector3 origin, Vector3 direction,traceResult &result)
00447 {
00448 unsigned int a = 0;
00449 unsigned int b = 0;
00450
00451 const double EPSILON = 0;
00452 Vector3 origin1=origin;
00453 Vector3 direction1=direction;
00454
00455 if (direction[0] == 0.0)
00456 {
00457 direction[0]=EPSILON;
00458 b |= 4;
00459 }
00460 else if (direction[0] < 0.0)
00461 {
00462
00463 origin[0] = -origin[0];
00464 direction[0] = -direction[0];
00465 a |= 4;
00466 }
00467
00468 if (direction[1] == 0.0)
00469 {
00470 direction[1]=EPSILON;
00471 b |= 2;
00472 }
00473 else if (direction[1] < 0.0)
00474 {
00475 origin[1] = -origin[1];
00476 direction[1] = -direction[1];
00477 a |= 2;
00478 }
00479
00480 if (direction[2] == 0.0)
00481 {
00482 direction[2]=EPSILON;
00483 b |= 1;
00484 }
00485 else if (direction[2] < 0.0)
00486 {
00487 origin[2] = -origin[2];
00488 direction[2] = -direction[2];
00489 a |= 1;
00490 }
00491 double tx0 = (-CUBE_SIZE - origin[0]) / direction[0];
00492 double tx1 = (CUBE_SIZE - origin[0]) / direction[0];
00493 double ty0 = (-CUBE_SIZE - origin[1]) / direction[1];
00494 double ty1 = (CUBE_SIZE - origin[1]) / direction[1];
00495 double tz0 = (-CUBE_SIZE - origin[2]) / direction[2];
00496 double tz1 = (CUBE_SIZE - origin[2]) / direction[2];
00497 if (bb_max3 (tx0, ty0, tz0) < bb_min3 (tx1, ty1, tz1))
00498 return trace (origin, direction, tx0, ty0, tz0, tx1, ty1, tz1, a, b,origin1,direction1,result);
00499 return -1;
00500
00501 }
00502
00503
00504
00505
00506
00507 }
00508
00509 }
00510
00511 }