Blender V2.61 - r43446
|
00001 00004 /****************************************************************************** 00005 * 00006 * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method 00007 * Copyright 2003-2006 Nils Thuerey 00008 * 00009 * Tree container for fast triangle intersects 00010 * 00011 *****************************************************************************/ 00012 00013 00014 #include "ntl_bsptree.h" 00015 #include "utilities.h" 00016 00017 #include <algorithm> 00018 00020 int globalSortingAxis; 00022 vector<ntlVec3Gfx> *globalSortingPoints; 00023 00024 #define TREE_DOUBLEI 300 00025 00026 /* try axis selection? */ 00027 bool chooseAxis = 0; 00028 /* do median search? */ 00029 int doSort = 0; 00030 00031 00033 class BSPNode { 00034 public: 00035 BSPNode() {}; 00036 00037 ntlVec3Gfx min,max; /* AABB for node */ 00038 vector<ntlTriangle *> *members; /* stored triangles */ 00039 BSPNode *child[2]; /* pointer to children nodes */ 00040 char axis; /* division axis */ 00041 char cloneVec; /* is this vector a clone? */ 00042 00044 inline bool isLeaf() const { 00045 return (child[0] == NULL); 00046 } 00047 }; 00048 00049 00051 class BSPStackElement { 00052 public: 00054 BSPNode *node; 00056 gfxReal mindist, maxdist; 00057 }; 00058 00060 class BSPStack { 00061 public: 00063 int stackPtr; 00065 BSPStackElement elem[ BSP_STACK_SIZE ]; 00066 }; 00067 00069 class TriangleBBox { 00070 public: 00072 ntlVec3Gfx start, end; 00073 }; 00074 00075 00076 /****************************************************************************** 00077 * calculate tree statistics 00078 *****************************************************************************/ 00079 void calcStats(BSPNode *node, int depth, int &noLeafs, gfxReal &avgDepth, gfxReal &triPerLeaf,int &totalTris) 00080 { 00081 if(node->members != NULL) { 00082 totalTris += node->members->size(); 00083 } 00084 //depth = 15; // DBEUG! 00085 00086 if( (node->child[0]==NULL) && (node->child[1]==NULL) ) { 00087 // leaf 00088 noLeafs++; 00089 avgDepth += depth; 00090 triPerLeaf += node->members->size(); 00091 } else { 00092 for(int i=0;i<2;i++) 00093 calcStats(node->child[i], depth+1, noLeafs, avgDepth, triPerLeaf, totalTris); 00094 } 00095 } 00096 00097 00098 00099 /****************************************************************************** 00100 * triangle comparison function for median search 00101 *****************************************************************************/ 00102 bool lessTriangleAverage(const ntlTriangle *x, const ntlTriangle *y) 00103 { 00104 return x->getAverage(globalSortingAxis) < y->getAverage(globalSortingAxis); 00105 } 00106 00107 00108 /****************************************************************************** 00109 * triangle AABB intersection 00110 *****************************************************************************/ 00111 bool ntlTree::checkAABBTriangle(ntlVec3Gfx &min, ntlVec3Gfx &max, ntlTriangle *tri) 00112 { 00113 // test only BB of triangle 00114 TriangleBBox *bbox = &mpTBB[ tri->getBBoxId() ]; 00115 if( bbox->end[0] < min[0] ) return false; 00116 if( bbox->start[0] > max[0] ) return false; 00117 if( bbox->end[1] < min[1] ) return false; 00118 if( bbox->start[1] > max[1] ) return false; 00119 if( bbox->end[2] < min[2] ) return false; 00120 if( bbox->start[2] > max[2] ) return false; 00121 return true; 00122 } 00123 00124 00125 00126 00127 00128 00129 00130 /****************************************************************************** 00131 * Default constructor 00132 *****************************************************************************/ 00133 ntlTree::ntlTree() : 00134 mStart(0.0), mEnd(0.0), mMaxDepth( 5 ), mMaxListLength( 5 ), mpRoot( NULL) , 00135 mpNodeStack( NULL), mpVertices( NULL ), mpVertNormals( NULL ), mpTriangles( NULL ), 00136 mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0) 00137 { 00138 errFatal( "ntlTree","Uninitialized BSP Tree!\n",SIMWORLD_INITERROR ); 00139 return; 00140 } 00141 00142 00143 /****************************************************************************** 00144 * Constructor with init 00145 *****************************************************************************/ 00146 //ntlTree::ntlTree(int depth, int objnum, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, vector<ntlTriangle> *trilist) : 00147 ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : 00148 mStart(0.0), mEnd(0.0), mMaxDepth( depth ), mMaxListLength( objnum ), mpRoot( NULL) , 00149 mpNodeStack( NULL), mpTBB( NULL ), 00150 mTriangleMask( 0xFFFF ), 00151 mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0) 00152 { 00153 // init scene data pointers 00154 mpVertices = scene->getVertexPointer(); 00155 mpVertNormals = scene->getVertexNormalPointer(); 00156 mpTriangles = scene->getTrianglePointer(); 00157 mTriangleMask = triFlagMask; 00158 00159 if(mpTriangles == NULL) { 00160 errFatal( "ntlTree Cons","no triangle list!\n",SIMWORLD_INITERROR); 00161 return; 00162 } 00163 if(mpTriangles->size() == 0) { 00164 warnMsg( "ntlTree::ntlTree","No triangles ("<< mpTriangles->size() <<")!\n"); 00165 mStart = mEnd = ntlVec3Gfx(0,0,0); 00166 return; 00167 } 00168 if(depth>=BSP_STACK_SIZE) { 00169 errFatal( "ntlTree::ntlTree","Depth to high ("<< mMaxDepth <<")!\n", SIMWORLD_INITERROR ); 00170 return; 00171 } 00172 00173 /* check triangles (a bit inefficient, but we dont know which vertices belong 00174 to this tree), and generate bounding boxes */ 00175 mppTriangles = new vector<ntlTriangle *>; 00176 int noOfTriangles = mpTriangles->size(); 00177 mpTBB = new TriangleBBox[ noOfTriangles ]; 00178 int bbCount = 0; 00179 mStart = mEnd = (*mpVertices)[ mpTriangles->front().getPoints()[0] ]; 00180 //errMsg("TreeDebug","Start"); 00181 for (vector<ntlTriangle>::iterator iter = mpTriangles->begin(); 00182 iter != mpTriangles->end(); 00183 iter++ ) { 00184 //errorOut(" d "<< convertFlags2String((int)(*iter).getFlags()) <<" "<< convertFlags2String( (int)mTriangleMask)<<" add? "<<( ((int)(*iter).getFlags() & (int)mTriangleMask) != 0 ) ); 00185 // discard triangles that dont match mask 00186 if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) { 00187 continue; 00188 } 00189 00190 // test? TODO 00191 ntlVec3Gfx tnormal = (*mpVertNormals)[ (*iter).getPoints()[0] ]+ 00192 (*mpVertNormals)[ (*iter).getPoints()[1] ]+ 00193 (*mpVertNormals)[ (*iter).getPoints()[2] ]; 00194 ntlVec3Gfx triangleNormal = (*iter).getNormal(); 00195 if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) continue; 00196 if( equal( tnormal, ntlVec3Gfx(0.0)) ) continue; 00197 // */ 00198 00199 ntlVec3Gfx bbs, bbe; 00200 //errMsg("TreeDebug","Triangle"); 00201 for(int i=0;i<3;i++) { 00202 int index = (*iter).getPoints()[i]; 00203 ntlVec3Gfx tp = (*mpVertices)[ index ]; 00204 //errMsg("TreeDebug"," Point "<<i<<" = "<<tp<<" "); 00205 if(tp[0] < mStart[0]) mStart[0]= tp[0]; 00206 if(tp[0] > mEnd[0]) mEnd[0]= tp[0]; 00207 if(tp[1] < mStart[1]) mStart[1]= tp[1]; 00208 if(tp[1] > mEnd[1]) mEnd[1]= tp[1]; 00209 if(tp[2] < mStart[2]) mStart[2]= tp[2]; 00210 if(tp[2] > mEnd[2]) mEnd[2]= tp[2]; 00211 if(i==0) { 00212 bbs = bbe = tp; 00213 } else { 00214 if( tp[0] < bbs[0] ) bbs[0] = tp[0]; 00215 if( tp[0] > bbe[0] ) bbe[0] = tp[0]; 00216 if( tp[1] < bbs[1] ) bbs[1] = tp[1]; 00217 if( tp[1] > bbe[1] ) bbe[1] = tp[1]; 00218 if( tp[2] < bbs[2] ) bbs[2] = tp[2]; 00219 if( tp[2] > bbe[2] ) bbe[2] = tp[2]; 00220 } 00221 } 00222 mppTriangles->push_back( &(*iter) ); 00223 //errMsg("TreeDebug","Triangle "<<(*mpVertices)[(*iter).getPoints()[0]]<<" "<<(*mpVertices)[(*iter).getPoints()[1]]<<" "<<(*mpVertices)[(*iter).getPoints()[2]]<<" "); 00224 00225 // add BB 00226 mpTBB[ bbCount ].start = bbs; 00227 mpTBB[ bbCount ].end = bbe; 00228 (*iter).setBBoxId( bbCount ); 00229 bbCount++; 00230 } 00231 00232 00233 00234 /* slighlty enlarge bounding tolerance for tree 00235 to avoid problems with triangles paralell to slabs */ 00236 mStart -= ntlVec3Gfx( getVecEpsilon() ); 00237 mEnd += ntlVec3Gfx( getVecEpsilon() ); 00238 00239 /* init root node and stack */ 00240 mpNodeStack = new BSPStack; 00241 mpRoot = new BSPNode; 00242 mpRoot->min = mStart; 00243 mpRoot->max = mEnd; 00244 mpRoot->axis = AXIS_X; 00245 mpRoot->members = mppTriangles; 00246 mpRoot->child[0] = mpRoot->child[1] = NULL; 00247 mpRoot->cloneVec = 0; 00248 globalSortingPoints = mpVertices; 00249 mpTriDist = new char[ mppTriangles->size() ]; 00250 mNumNodes = 1; 00251 mAbortSubdiv = 0; 00252 00253 /* create tree */ 00254 debugOutInter( "Generating BSP Tree... (Nodes "<< mCurrentNodes << 00255 ", Depth "<<mCurrentDepth<< ") ", 2, 2000 ); 00256 subdivide(mpRoot, 0, AXIS_X); 00257 debMsgStd("ntlTree::ntlTree",DM_MSG,"Generated Tree: Nodes "<< mCurrentNodes << 00258 ", Depth "<<mCurrentDepth<< " with "<<noOfTriangles<<" triangles", 2 ); 00259 00260 delete [] mpTriDist; 00261 delete [] mpTBB; 00262 mpTriDist = NULL; 00263 mpTBB = NULL; 00264 00265 /* calculate some stats about tree */ 00266 int noLeafs = 0; 00267 gfxReal avgDepth = 0.0; 00268 gfxReal triPerLeaf = 0.0; 00269 int totalTris = 0; 00270 00271 calcStats(mpRoot,0, noLeafs, avgDepth, triPerLeaf, totalTris); 00272 avgDepth /= (gfxReal)noLeafs; 00273 triPerLeaf /= (gfxReal)noLeafs; 00274 debMsgStd("ntlTree::ntlTree",DM_MSG,"Tree ("<<doSort<<","<<chooseAxis<<") Stats: Leafs:"<<noLeafs<<", avgDepth:"<<avgDepth<< 00275 ", triPerLeaf:"<<triPerLeaf<<", triDoubles:"<<mTriDoubles<<", totalTris:"<<totalTris 00276 <<" nodes:"<<mNumNodes 00277 //<<" T"<< (totalTris%3) // 0=ich, 1=f, 2=a 00278 , 2 ); 00279 00280 if(mAbortSubdiv) { 00281 errMsg("ntlTree::ntlTree","Aborted... "<<mNumNodes); 00282 deleteNode(mpRoot); 00283 mpRoot = NULL; 00284 } 00285 } 00286 00287 /****************************************************************************** 00288 * Destructor 00289 *****************************************************************************/ 00290 ntlTree::~ntlTree() 00291 { 00292 /* delete tree, and all members except for the root node */ 00293 deleteNode(mpRoot); 00294 if(mpNodeStack) delete mpNodeStack; 00295 } 00296 00297 00298 /****************************************************************************** 00299 * subdivide tree 00300 *****************************************************************************/ 00301 void ntlTree::subdivide(BSPNode *node, int depth, int axis) 00302 { 00303 int nextAxis=0; /* next axis to partition */ 00304 int allTriDistSet = (1<<0)|(1<<1); // all mpTriDist flags set? 00305 //errorOut(" "<<node<<" depth:"<<depth<<" m:"<<node->members->size() <<" "<<node->min<<" - "<<node->max ); 00306 00307 if(depth>mCurrentDepth) mCurrentDepth = depth; 00308 node->child[0] = node->child[1] = NULL; 00309 if( ( (int)node->members->size() > mMaxListLength) && 00310 (depth < mMaxDepth ) 00311 && (node->cloneVec<10) 00312 && (!mAbortSubdiv) 00313 ) { 00314 00315 gfxReal planeDiv = 0.499999; // position of plane division 00316 00317 // determine next subdivision axis 00318 int newaxis = 0; 00319 gfxReal extX = node->max[0]-node->min[0]; 00320 gfxReal extY = node->max[1]-node->min[1]; 00321 gfxReal extZ = node->max[2]-node->min[2]; 00322 00323 if( extY>extX ) { 00324 if( extZ>extY ) { 00325 newaxis = 2; 00326 } else { 00327 newaxis = 1; 00328 } 00329 } else { 00330 if( extZ>extX ) { 00331 newaxis = 2; 00332 } else { 00333 newaxis = 0; 00334 } 00335 } 00336 axis = node->axis = newaxis; 00337 00338 // init child nodes 00339 for( int i=0; i<2; i++) { 00340 /* status output */ 00341 mCurrentNodes++; 00342 if(mCurrentNodes % 13973 ==0) { 00343 debugOutInter( "NTL Generating BSP Tree ("<<doSort<<","<<chooseAxis<<") ... (Nodes "<< mCurrentNodes << 00344 ", Depth "<<mCurrentDepth<< ") " , 2, 2000); 00345 } 00346 00347 /* create new node */ 00348 node->child[i] = new BSPNode; 00349 node->child[i]->min = node->min; 00350 node->child[i]->max = node->max; 00351 node->child[i]->max = node->max; 00352 node->child[i]->child[0] = NULL; 00353 node->child[i]->child[1] = NULL; 00354 node->child[i]->members = NULL; 00355 nextAxis = (axis+1)%3; 00356 node->child[i]->axis = nextAxis; 00357 mNumNodes++; 00358 // abort when using 256MB only for tree... 00359 if(mNumNodes*sizeof(BSPNode)> 1024*1024*512) mAbortSubdiv = 1; 00360 00361 /* current division plane */ 00362 if(!i) { 00363 node->child[i]->min[axis] = node->min[axis]; 00364 node->child[i]->max[axis] = node->min[axis] + planeDiv* 00365 (node->max[axis]-node->min[axis]); 00366 } else { 00367 node->child[i]->min[axis] = node->min[axis] + planeDiv* 00368 (node->max[axis]-node->min[axis]); 00369 node->child[i]->max[axis] = node->max[axis]; 00370 } 00371 } 00372 00373 00374 /* process the two children */ 00375 int thisTrisFor[2] = {0,0}; 00376 int thisTriDoubles[2] = {0,0}; 00377 for(int t=0;t<(int)node->members->size();t++) mpTriDist[t] = 0; 00378 for( int i=0; i<2; i++) { 00379 /* distribute triangles */ 00380 int t = 0; 00381 for (vector<ntlTriangle *>::iterator iter = node->members->begin(); 00382 iter != node->members->end(); iter++ ) { 00383 00384 /* add triangle, check bounding box axis */ 00385 TriangleBBox *bbox = &mpTBB[ (*iter)->getBBoxId() ]; 00386 bool isintersect = true; 00387 if( bbox->end[axis] < node->child[i]->min[axis] ) isintersect = false; 00388 else if( bbox->start[axis] > node->child[i]->max[axis] ) isintersect = false; 00389 if(isintersect) { 00390 // add flag to vector 00391 mpTriDist[t] |= (1<<i); 00392 // count no. of triangles for vector init 00393 thisTrisFor[i]++; 00394 } 00395 00396 if(mpTriDist[t] == allTriDistSet) { 00397 thisTriDoubles[i]++; 00398 mTriDoubles++; // TODO check for small geo tree?? 00399 } 00400 t++; 00401 } /* end of loop over all triangles */ 00402 } // i 00403 00404 /* distribute triangles */ 00405 bool haveCloneVec[2] = {false, false}; 00406 for( int i=0; i<2; i++) { 00407 node->child[i]->members = new vector<ntlTriangle *>( thisTrisFor[i] ); 00408 node->child[i]->cloneVec = 0; 00409 } 00410 00411 int tind0 = 0; 00412 int tind1 = 0; 00413 if( (!haveCloneVec[0]) || (!haveCloneVec[1]) ){ 00414 int t = 0; // triangle index counter 00415 for (vector<ntlTriangle *>::iterator iter = node->members->begin(); 00416 iter != node->members->end(); iter++ ) { 00417 if(!haveCloneVec[0]) { 00418 if( (mpTriDist[t] & 1) == 1) { 00419 (*node->child[0]->members)[tind0] = (*iter); // dont use push_back for preinited size! 00420 tind0++; 00421 } 00422 } 00423 if(!haveCloneVec[1]) { 00424 if( (mpTriDist[t] & 2) == 2) { 00425 (*node->child[1]->members)[tind1] = (*iter); // dont use push_back for preinited size! 00426 tind1++; 00427 } 00428 } 00429 t++; 00430 } /* end of loop over all triangles */ 00431 } 00432 00433 // subdivide children 00434 for( int i=0; i<2; i++) { 00435 /* recurse */ 00436 subdivide( node->child[i], depth+1, nextAxis ); 00437 } 00438 00439 /* if we are here, this are childs, so we dont need the members any more... */ 00440 /* delete unecessary members */ 00441 if( (!haveCloneVec[0]) && (!haveCloneVec[1]) && (node->cloneVec == 0) ){ 00442 delete node->members; 00443 } 00444 node->members = NULL; 00445 00446 } /* subdivision necessary */ 00447 } 00448 00449 /****************************************************************** 00450 * triangle intersection with triangle pointer, 00451 * returns t,u,v by references 00452 */ 00453 #if GFX_PRECISION==1 00454 // float values 00456 #define RAY_TRIANGLE_EPSILON (1e-07) 00457 00458 #else 00459 // double values 00461 #define RAY_TRIANGLE_EPSILON (1e-15) 00462 00463 #endif 00464 00465 00466 /****************************************************************************** 00467 * intersect ray with BSPtree 00468 *****************************************************************************/ 00469 inline void ntlRay::intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const 00470 { 00471 /* (cf. moeller&haines, page 305) */ 00472 t = GFX_REAL_MAX; 00473 ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ]; 00474 ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0; 00475 ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0; 00476 ntlVec3Gfx p = cross( mDirection, e2 ); 00477 gfxReal divisor = dot(e1, p); 00478 if((divisor > -RAY_TRIANGLE_EPSILON)&&(divisor < RAY_TRIANGLE_EPSILON)) return; 00479 00480 gfxReal invDivisor = 1/divisor; 00481 ntlVec3Gfx s = mOrigin - e0; 00482 u = invDivisor * dot(s, p); 00483 if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return; 00484 00485 ntlVec3Gfx q = cross( s,e1 ); 00486 v = invDivisor * dot(mDirection, q); 00487 if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return; 00488 00489 t = invDivisor * dot(e2, q); 00490 } 00491 void ntlTree::intersect(const ntlRay &ray, gfxReal &distance, 00492 ntlVec3Gfx &normal, 00493 ntlTriangle *&tri, 00494 int flags, bool forceNonsmooth) const 00495 { 00496 gfxReal mint = GFX_REAL_MAX; /* current minimal t */ 00497 ntlVec3Gfx retnormal; /* intersection (interpolated) normal */ 00498 gfxReal mintu=0.0, mintv=0.0; /* u,v for min t intersection */ 00499 00500 BSPNode *curr, *nearChild, *farChild; /* current node and children */ 00501 gfxReal planedist, mindist, maxdist; 00502 ntlVec3Gfx pos; 00503 00504 ntlTriangle *hit = NULL; 00505 tri = NULL; 00506 00507 ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist); 00508 00509 if((maxdist < 0.0) || 00510 (!mpRoot) || 00511 (mindist == GFX_REAL_MAX) || 00512 (maxdist == GFX_REAL_MAX) ) { 00513 distance = -1.0; 00514 return; 00515 } 00516 mindist -= getVecEpsilon(); 00517 maxdist += getVecEpsilon(); 00518 00519 /* stack init */ 00520 mpNodeStack->elem[0].node = NULL; 00521 mpNodeStack->stackPtr = 1; 00522 00523 curr = mpRoot; 00524 mint = GFX_REAL_MAX; 00525 while(curr != NULL) { 00526 00527 while( !curr->isLeaf() ) { 00528 planedist = distanceToPlane(curr, curr->child[0]->max, ray ); 00529 getChildren(curr, ray.getOrigin(), nearChild, farChild ); 00530 00531 // check ray direction for small plane distances 00532 if( (planedist>-getVecEpsilon() )&&(planedist< getVecEpsilon() ) ) { 00533 // ray origin on intersection plane 00534 planedist = 0.0; 00535 if(ray.getDirection()[curr->axis]>getVecEpsilon() ) { 00536 // larger coords 00537 curr = curr->child[1]; 00538 } else if(ray.getDirection()[curr->axis]<-getVecEpsilon() ) { 00539 // smaller coords 00540 curr = curr->child[0]; 00541 } else { 00542 // paralell, order doesnt really matter are min/max/plane ok? 00543 mpNodeStack->elem[ mpNodeStack->stackPtr ].node = curr->child[0]; 00544 mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist; 00545 mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist; 00546 (mpNodeStack->stackPtr)++; 00547 curr = curr->child[1]; 00548 maxdist = planedist; 00549 } 00550 } else { 00551 // normal ray 00552 if( (planedist>maxdist) || (planedist<0.0-getVecEpsilon() ) ) { 00553 curr = nearChild; 00554 } else if(planedist < mindist) { 00555 curr = farChild; 00556 } else { 00557 mpNodeStack->elem[ mpNodeStack->stackPtr ].node = farChild; 00558 mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist; 00559 mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist; 00560 (mpNodeStack->stackPtr)++; 00561 00562 curr = nearChild; 00563 maxdist = planedist; 00564 } 00565 } 00566 } 00567 00568 00569 /* intersect with current node */ 00570 for (vector<ntlTriangle *>::iterator iter = curr->members->begin(); 00571 iter != curr->members->end(); iter++ ) { 00572 00573 /* check for triangle flags before intersecting */ 00574 if((!flags) || ( ((*iter)->getFlags() & flags) > 0 )) { 00575 00576 if( ((*iter)->getLastRay() == ray.getID() )&&((*iter)->getLastRay()>0) ) { 00577 // was already intersected... 00578 } else { 00579 // we still need to intersect this triangle 00580 gfxReal u=0.0,v=0.0, t=-1.0; 00581 ray.intersectTriangle( mpVertices, (*iter), t,u,v); 00582 (*iter)->setLastRay( ray.getID() ); 00583 00584 if( (t > 0.0) && (t<mint) ) { 00585 mint = t; 00586 hit = (*iter); 00587 mintu = u; mintv = v; 00588 } 00589 } 00590 00591 } // flags check 00592 } 00593 00594 /* check if intersection is valid */ 00595 if( (mint>0.0) && (mint < GFX_REAL_MAX) ) { 00596 pos = ray.getOrigin() + ray.getDirection()*mint; 00597 00598 if( (pos[0] >= curr->min[0]) && (pos[0] <= curr->max[0]) && 00599 (pos[1] >= curr->min[1]) && (pos[1] <= curr->max[1]) && 00600 (pos[2] >= curr->min[2]) && (pos[2] <= curr->max[2]) ) 00601 { 00602 00603 if(forceNonsmooth) { 00604 // calculate triangle normal 00605 ntlVec3Gfx e0,e1,e2; 00606 e0 = (*mpVertices)[ hit->getPoints()[0] ]; 00607 e1 = (*mpVertices)[ hit->getPoints()[1] ]; 00608 e2 = (*mpVertices)[ hit->getPoints()[2] ]; 00609 retnormal = cross( -(e2-e0), (e1-e0) ); 00610 } else { 00611 // calculate interpolated normal 00612 retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ 00613 (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + 00614 (*mpVertNormals)[ hit->getPoints()[2] ]*mintv; 00615 } 00616 normalize(retnormal); 00617 normal = retnormal; 00618 distance = mint; 00619 tri = hit; 00620 return; 00621 } 00622 } 00623 00624 (mpNodeStack->stackPtr)--; 00625 curr = mpNodeStack->elem[ mpNodeStack->stackPtr ].node; 00626 mindist = mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist; 00627 maxdist = mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist; 00628 } /* traverse tree */ 00629 00630 if(mint == GFX_REAL_MAX) { 00631 distance = -1.0; 00632 } else { 00633 // intersection outside the BSP bounding volumes might occur due to roundoff... 00634 //retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + (*mpVertNormals)[ hit->getPoints()[2] ]*mintv; 00635 if(forceNonsmooth) { 00636 // calculate triangle normal 00637 ntlVec3Gfx e0,e1,e2; 00638 e0 = (*mpVertices)[ hit->getPoints()[0] ]; 00639 e1 = (*mpVertices)[ hit->getPoints()[1] ]; 00640 e2 = (*mpVertices)[ hit->getPoints()[2] ]; 00641 retnormal = cross( -(e2-e0), (e1-e0) ); 00642 } else { 00643 // calculate interpolated normal 00644 retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ 00645 (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + 00646 (*mpVertNormals)[ hit->getPoints()[2] ]*mintv; 00647 } 00648 00649 normalize(retnormal); 00650 normal = retnormal; 00651 distance = mint; 00652 tri = hit; 00653 } 00654 return; 00655 } 00656 00657 inline void ntlRay::intersectTriangleX(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const 00658 { 00659 /* (cf. moeller&haines, page 305) */ 00660 t = GFX_REAL_MAX; 00661 ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ]; 00662 ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0; 00663 ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0; 00664 00665 //ntlVec3Gfx p = cross( mDirection, e2 ); 00666 //ntlVector3Dim<Scalar> cp( (-), (- (1.0 *v[2])), ((1.0 *v[1]) -) ); 00667 ntlVec3Gfx p(0.0, -e2[2], e2[1]); 00668 00669 gfxReal divisor = dot(e1, p); 00670 if((divisor > -RAY_TRIANGLE_EPSILON)&&(divisor < RAY_TRIANGLE_EPSILON)) return; 00671 00672 gfxReal invDivisor = 1/divisor; 00673 ntlVec3Gfx s = mOrigin - e0; 00674 u = invDivisor * dot(s, p); 00675 if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return; 00676 00677 ntlVec3Gfx q = cross( s,e1 ); 00678 //v = invDivisor * dot(mDirection, q); 00679 v = invDivisor * q[0]; 00680 if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return; 00681 00682 t = invDivisor * dot(e2, q); 00683 } 00684 void ntlTree::intersectX(const ntlRay &ray, gfxReal &distance, 00685 ntlVec3Gfx &normal, 00686 ntlTriangle *&tri, 00687 int flags, bool forceNonsmooth) const 00688 { 00689 gfxReal mint = GFX_REAL_MAX; /* current minimal t */ 00690 ntlVec3Gfx retnormal; /* intersection (interpolated) normal */ 00691 gfxReal mintu=0.0, mintv=0.0; /* u,v for min t intersection */ 00692 00693 BSPNode *curr, *nearChild, *farChild; /* current node and children */ 00694 gfxReal planedist, mindist, maxdist; 00695 ntlVec3Gfx pos; 00696 00697 ntlTriangle *hit = NULL; 00698 tri = NULL; 00699 00700 ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist); // +X 00701 00702 if((maxdist < 0.0) || 00703 (!mpRoot) || 00704 (mindist == GFX_REAL_MAX) || 00705 (maxdist == GFX_REAL_MAX) ) { 00706 distance = -1.0; 00707 return; 00708 } 00709 mindist -= getVecEpsilon(); 00710 maxdist += getVecEpsilon(); 00711 00712 /* stack init */ 00713 mpNodeStack->elem[0].node = NULL; 00714 mpNodeStack->stackPtr = 1; 00715 00716 curr = mpRoot; 00717 mint = GFX_REAL_MAX; 00718 while(curr != NULL) { // +X 00719 00720 while( !curr->isLeaf() ) { 00721 planedist = distanceToPlane(curr, curr->child[0]->max, ray ); 00722 getChildren(curr, ray.getOrigin(), nearChild, farChild ); 00723 00724 // check ray direction for small plane distances 00725 if( (planedist>-getVecEpsilon() )&&(planedist< getVecEpsilon() ) ) { 00726 // ray origin on intersection plane 00727 planedist = 0.0; 00728 if(ray.getDirection()[curr->axis]>getVecEpsilon() ) { 00729 // larger coords 00730 curr = curr->child[1]; 00731 } else if(ray.getDirection()[curr->axis]<-getVecEpsilon() ) { 00732 // smaller coords 00733 curr = curr->child[0]; 00734 } else { 00735 // paralell, order doesnt really matter are min/max/plane ok? 00736 mpNodeStack->elem[ mpNodeStack->stackPtr ].node = curr->child[0]; 00737 mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist; 00738 mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist; 00739 (mpNodeStack->stackPtr)++; 00740 curr = curr->child[1]; 00741 maxdist = planedist; 00742 } 00743 } else { 00744 // normal ray 00745 if( (planedist>maxdist) || (planedist<0.0-getVecEpsilon() ) ) { 00746 curr = nearChild; 00747 } else if(planedist < mindist) { 00748 curr = farChild; 00749 } else { 00750 mpNodeStack->elem[ mpNodeStack->stackPtr ].node = farChild; 00751 mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist; 00752 mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist; 00753 (mpNodeStack->stackPtr)++; 00754 00755 curr = nearChild; 00756 maxdist = planedist; 00757 } 00758 } 00759 } // +X 00760 00761 00762 /* intersect with current node */ 00763 for (vector<ntlTriangle *>::iterator iter = curr->members->begin(); 00764 iter != curr->members->end(); iter++ ) { 00765 00766 /* check for triangle flags before intersecting */ 00767 if((!flags) || ( ((*iter)->getFlags() & flags) > 0 )) { 00768 00769 if( ((*iter)->getLastRay() == ray.getID() )&&((*iter)->getLastRay()>0) ) { 00770 // was already intersected... 00771 } else { 00772 // we still need to intersect this triangle 00773 gfxReal u=0.0,v=0.0, t=-1.0; 00774 ray.intersectTriangleX( mpVertices, (*iter), t,u,v); 00775 (*iter)->setLastRay( ray.getID() ); 00776 00777 if( (t > 0.0) && (t<mint) ) { 00778 mint = t; 00779 hit = (*iter); 00780 mintu = u; mintv = v; 00781 } 00782 } 00783 00784 } // flags check 00785 } // +X 00786 00787 /* check if intersection is valid */ 00788 if( (mint>0.0) && (mint < GFX_REAL_MAX) ) { 00789 pos = ray.getOrigin() + ray.getDirection()*mint; 00790 00791 if( (pos[0] >= curr->min[0]) && (pos[0] <= curr->max[0]) && 00792 (pos[1] >= curr->min[1]) && (pos[1] <= curr->max[1]) && 00793 (pos[2] >= curr->min[2]) && (pos[2] <= curr->max[2]) ) 00794 { 00795 00796 if(forceNonsmooth) { 00797 // calculate triangle normal 00798 ntlVec3Gfx e0,e1,e2; 00799 e0 = (*mpVertices)[ hit->getPoints()[0] ]; 00800 e1 = (*mpVertices)[ hit->getPoints()[1] ]; 00801 e2 = (*mpVertices)[ hit->getPoints()[2] ]; 00802 retnormal = cross( -(e2-e0), (e1-e0) ); 00803 } else { 00804 // calculate interpolated normal 00805 retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ 00806 (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + 00807 (*mpVertNormals)[ hit->getPoints()[2] ]*mintv; 00808 } 00809 normalize(retnormal); 00810 normal = retnormal; 00811 distance = mint; 00812 tri = hit; 00813 return; 00814 } 00815 } // +X 00816 00817 (mpNodeStack->stackPtr)--; 00818 curr = mpNodeStack->elem[ mpNodeStack->stackPtr ].node; 00819 mindist = mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist; 00820 maxdist = mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist; 00821 } /* traverse tree */ 00822 00823 if(mint == GFX_REAL_MAX) { 00824 distance = -1.0; 00825 } else { 00826 00827 // intersection outside the BSP bounding volumes might occur due to roundoff... 00828 if(forceNonsmooth) { 00829 // calculate triangle normal 00830 ntlVec3Gfx e0,e1,e2; 00831 e0 = (*mpVertices)[ hit->getPoints()[0] ]; 00832 e1 = (*mpVertices)[ hit->getPoints()[1] ]; 00833 e2 = (*mpVertices)[ hit->getPoints()[2] ]; 00834 retnormal = cross( -(e2-e0), (e1-e0) ); 00835 } else { 00836 // calculate interpolated normal 00837 retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ 00838 (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + 00839 (*mpVertNormals)[ hit->getPoints()[2] ]*mintv; 00840 } 00841 00842 normalize(retnormal); 00843 normal = retnormal; 00844 distance = mint; 00845 tri = hit; 00846 } // +X 00847 return; 00848 } 00849 00850 00851 00852 /****************************************************************************** 00853 * distance to plane function for nodes 00854 *****************************************************************************/ 00855 gfxReal ntlTree::distanceToPlane(BSPNode *curr, ntlVec3Gfx plane, ntlRay ray) const 00856 { 00857 return ( (plane[curr->axis]-ray.getOrigin()[curr->axis]) / ray.getDirection()[curr->axis] ); 00858 } 00859 00860 00861 /****************************************************************************** 00862 * return ordering of children nodes relatice to origin point 00863 *****************************************************************************/ 00864 void ntlTree::getChildren(BSPNode *curr, ntlVec3Gfx origin, BSPNode *&node_near, BSPNode *&node_far) const 00865 { 00866 if(curr->child[0]->max[ curr->axis ] >= origin[ curr->axis ]) { 00867 node_near = curr->child[0]; 00868 node_far = curr->child[1]; 00869 } else { 00870 node_near = curr->child[1]; 00871 node_far = curr->child[0]; 00872 } 00873 } 00874 00875 00876 /****************************************************************************** 00877 * delete a node of the tree with all sub nodes 00878 * dont delete root members 00879 *****************************************************************************/ 00880 void ntlTree::deleteNode(BSPNode *curr) 00881 { 00882 if(!curr) return; 00883 00884 if(curr->child[0] != NULL) 00885 deleteNode(curr->child[0]); 00886 if(curr->child[1] != NULL) 00887 deleteNode(curr->child[1]); 00888 00889 if(curr->members != NULL) delete curr->members; 00890 delete curr; 00891 } 00892 00893 00894 00895 /****************************************************************** 00896 * intersect only front or backsides 00897 * currently unused 00898 */ 00899 inline void ntlRay::intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const 00900 { 00901 t = GFX_REAL_MAX; 00902 ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ]; 00903 ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0; 00904 ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0; 00905 ntlVec3Gfx p = cross( mDirection, e2 ); 00906 gfxReal a = dot(e1, p); 00907 //if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return; 00908 if(a < RAY_TRIANGLE_EPSILON) return; // cull backsides 00909 00910 gfxReal f = 1/a; 00911 ntlVec3Gfx s = mOrigin - e0; 00912 u = f * dot(s, p); 00913 if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return; 00914 00915 ntlVec3Gfx q = cross( s,e1 ); 00916 v = f * dot(mDirection, q); 00917 if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return; 00918 00919 t = f * dot(e2, q); 00920 } 00921 inline void ntlRay::intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const 00922 { 00923 t = GFX_REAL_MAX; 00924 ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ]; 00925 ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0; 00926 ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0; 00927 ntlVec3Gfx p = cross( mDirection, e2 ); 00928 gfxReal a = dot(e1, p); 00929 //if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return; 00930 if(a > -RAY_TRIANGLE_EPSILON) return; // cull frontsides 00931 00932 gfxReal f = 1/a; 00933 ntlVec3Gfx s = mOrigin - e0; 00934 u = f * dot(s, p); 00935 if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return; 00936 00937 ntlVec3Gfx q = cross( s,e1 ); 00938 v = f * dot(mDirection, q); 00939 if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return; 00940 00941 t = f * dot(e2, q); 00942 } 00943 00944 00945