Blender  V2.59
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