Blender V2.61 - r43446

ntl_bsptree.cpp

Go to the documentation of this file.
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