Changeset 408 for trunk/VUT


Ignore:
Timestamp:
11/14/05 11:12:38 (19 years ago)
Author:
mattausch
Message:
 
Location:
trunk/VUT/GtpVisibilityPreprocessor
Files:
2 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj

    r406 r408  
    291291                        </File> 
    292292                        <File 
    293                                 RelativePath="..\src\ViewCellKd.cpp"> 
    294                         </File> 
    295                         <File 
    296                                 RelativePath="..\src\ViewCellKd.h"> 
     293                                RelativePath="..\src\VspKdTree.cpp"> 
     294                        </File> 
     295                        <File 
     296                                RelativePath="..\src\VspKdTree.h"> 
    297297                        </File> 
    298298                        <File 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp

    r406 r408  
    13221322 
    13231323 
    1324         RegisterOption("VssTree.maxDepth", optInt, "kd_depth=", "12"); 
     1324        RegisterOption("VspKdTree.maxDepth", optInt, "kd_depth=", "12"); 
     1325  RegisterOption("VspKdTree.minPvs", optInt, "kd_minpvs=", "1"); 
     1326  RegisterOption("VspKdTree.minRays", optInt, "kd_minrays=", "10"); 
     1327        RegisterOption("VspKdTree.maxCostRatio", optFloat, "maxcost=", "0.95"); 
     1328        RegisterOption("VspKdTree.maxRayContribution", optFloat, "maxraycontrib=", "0.5"); 
     1329 
     1330        RegisterOption("VspKdTree.epsilon", optFloat, "kd_eps=", "1e-6"); 
     1331  RegisterOption("VspKdTree.ct_div_ci", optFloat, "kd_ctdivci=", "1.0"); 
     1332  RegisterOption("VspKdTree.randomize", optBool, "randomize", "false"); 
     1333  RegisterOption("VspKdTree.splitType", optString, "split=", "queries"); 
     1334  RegisterOption("VspKdTree.numberOfEndPointDomains", optInt, "endpoints=", "10000"); 
     1335 
     1336  RegisterOption("VspKdTree.minSize", optFloat, "minsize=", "0.001"); 
     1337 
     1338  RegisterOption("VspKdTree.maxTotalMemory", optFloat, "mem=", "60.0"); 
     1339  RegisterOption("VspKdTree.maxStaticMemory", optFloat, "statmem=", "8.0"); 
     1340 
     1341  RegisterOption("VspKdTree.queryType", optString, "qtype=", "static"); 
     1342 
     1343  RegisterOption("VspKdTree.queryPosWeight", optFloat, "qposweight=", "0.0"); 
     1344  RegisterOption("VspKdTree.useRefDirSplits", optBool, "refdir", "false"); 
     1345  RegisterOption("VspKdTree.refDirAngle", optFloat, "refangle=", "10"); 
     1346  RegisterOption("VspKdTree.refDirBoxMaxSize", optFloat, "refboxsize=", "0.1"); 
     1347  RegisterOption("VspKdTree.accessTimeThreshold", optInt, "accesstime=", "1000"); 
     1348  RegisterOption("VspKdTree.minCollapseDepth", optInt, "colldepth=", "4"); 
     1349 
     1350 
     1351 
     1352 
     1353 
     1354 
     1355 
     1356 
     1357 
     1358 
     1359        RegisterOption("VssTree.maxDepth", optInt, "kd_depth=", "12"); 
    13251360  RegisterOption("VssTree.minPvs", optInt, "kd_minpvs=", "1"); 
    13261361  RegisterOption("VssTree.minRays", optInt, "kd_minrays=", "10"); 
     
    13471382  RegisterOption("VssTree.accessTimeThreshold", optInt, "accesstime=", "1000"); 
    13481383  RegisterOption("VssTree.minCollapseDepth", optInt, "colldepth=", "4"); 
    1349  
    13501384} 
    13511385 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp

    r406 r408  
     1 
     2// ================================================================ 
     3// $Id: lsds_kdtree.cpp,v 1.18 2005/04/16 09:34:21 bittner Exp $ 
     4// **************************************************************** 
     5/** 
     6   The KD tree based LSDS 
     7*/ 
     8// Initial coding by 
     9/** 
     10   @author Jiri Bittner 
     11*/ 
     12 
     13// Standard headers 
    114#include <stack> 
     15#include <queue> 
    216#include <algorithm> 
    3 #include <queue> 
     17#include <fstream> 
     18#include <string> 
     19 
     20#include "VspKdTree.h" 
     21 
    422#include "Environment.h" 
    5 #include "Mesh.h" 
    6 #include "ViewCellKd.h" 
    7  
    8  
    9 int ViewCellKdNode::mailID = 1; 
    10  
    11  
    12 ViewCellKdNode::ViewCellKdNode(ViewCellKdInterior *parent):mParent(parent), mailbox(0) 
    13 { 
    14   if (parent) 
    15     mDepth = parent->mDepth+1; 
     23#include "VssRay.h" 
     24#include "Intersectable.h" 
     25#include "Ray.h" 
     26 
     27 
     28#define DEBUG_DIR_SPLIT 0 
     29 
     30 
     31 
     32// Static variables 
     33int 
     34VspKdTreeLeaf::mailID = 0; 
     35 
     36inline void 
     37AddObject2Pvs(Intersectable *object, 
     38                                                        const int side, 
     39                                                        int &pvsBack, 
     40                                                        int &pvsFront) 
     41{ 
     42 
     43        if (!object) 
     44                return; 
     45                 
     46        if (side <= 0) { 
     47                if (!object->Mailed() && !object->Mailed(2)) { 
     48                        pvsBack++; 
     49                        if (object->Mailed(1)) 
     50                                object->Mail(2); 
     51                        else 
     52                                object->Mail(); 
     53                } 
     54        } 
     55         
     56        if (side >= 0) { 
     57                if (!object->Mailed(1) && !object->Mailed(2)) { 
     58                        pvsFront++; 
     59                        if (object->Mailed()) 
     60                                object->Mail(2); 
     61                        else 
     62                                object->Mail(1); 
     63                } 
     64        } 
     65} 
     66 
     67 
     68// Constructor 
     69VspKdTree::VspKdTree() 
     70{ 
     71  environment->GetIntValue("VspKdTree.maxDepth", termMaxDepth); 
     72        environment->GetIntValue("VspKdTree.minPvs", termMinPvs); 
     73        environment->GetIntValue("VspKdTree.minRays", termMinRays); 
     74        environment->GetFloatValue("VspKdTree.maxRayContribution", termMaxRayContribution); 
     75  environment->GetFloatValue("VspKdTree.maxCostRatio", termMaxCostRatio); 
     76 
     77  environment->GetFloatValue("VspKdTree.minSize", termMinSize); 
     78  termMinSize = sqr(termMinSize); 
     79         
     80  environment->GetFloatValue("VspKdTree.refDirBoxMaxSize", refDirBoxMaxSize); 
     81  refDirBoxMaxSize = sqr(refDirBoxMaxSize); 
     82   
     83  environment->GetFloatValue("VspKdTree.epsilon", epsilon); 
     84  environment->GetFloatValue("VspKdTree.ct_div_ci", ct_div_ci); 
     85         
     86  environment->GetFloatValue("VspKdTree.maxTotalMemory", maxTotalMemory); 
     87  environment->GetFloatValue("VspKdTree.maxStaticMemory", maxStaticMemory); 
     88   
     89   
     90 
     91 
     92  float refDirAngle; 
     93  environment->GetFloatValue("VspKdTree.refDirAngle", refDirAngle); 
     94 
     95  environment->GetIntValue("VspKdTree.accessTimeThreshold", accessTimeThreshold); 
     96  //= 1000; 
     97  environment->GetIntValue("VspKdTree.minCollapseDepth", minCollapseDepth); 
     98  //  int minCollapseDepth = 4; 
     99 
     100  //  pRefDirThresh = cos(0.5*M_PI - M_PI*refDirAngle/180.0); 
     101        //  cosRefDir = cos(M_PI*refDirAngle/180.0); 
     102        //  sinRefDir = sin(M_PI*refDirAngle/180.0); 
     103   
     104   
     105  // split type 
     106        char sname[128]; 
     107        environment->GetStringValue("VspKdTree.splitType", sname); 
     108  string name(sname); 
     109         
     110  if (name.compare("regular") == 0) 
     111    splitType = ESplitRegular; 
    16112  else 
    17     mDepth = 0; 
    18 } 
    19  
    20 ViewCellKd::ViewCellKd() 
    21 { 
    22   mRoot = new ViewCellKdLeaf(NULL, 0); 
    23   environment->GetIntValue("ViewCellKd.Termination.maxDepth", mTermMaxDepth); 
    24   environment->GetIntValue("ViewCellKd.Termination.minCost", mTermMinCost); 
    25   environment->GetFloatValue("ViewCellKd.Termination.maxCostRatio", mMaxCostRatio); 
    26   environment->GetFloatValue("ViewCellKd.Termination.ct_div_ci", mCt_div_ci); 
    27   environment->GetFloatValue("ViewCellKd.splitBorder", mSplitBorder); 
    28  
    29   environment->GetBoolValue("ViewCellKd.sahUseFaces", mSahUseFaces); 
    30  
    31   char splitType[64]; 
    32   environment->GetStringValue("ViewCellKd.splitMethod", splitType); 
    33    
    34   mSplitMethod = SPLIT_SPATIAL_MEDIAN; 
    35   if (strcmp(splitType, "spatialMedian") == 0) 
    36     mSplitMethod = SPLIT_SPATIAL_MEDIAN; 
    37   else 
    38     if (strcmp(splitType, "objectMedian") == 0) 
    39       mSplitMethod = SPLIT_OBJECT_MEDIAN; 
    40     else 
    41       if (strcmp(splitType, "SAH") == 0) 
    42         mSplitMethod = SPLIT_SAH; 
    43       else { 
    44         cerr<<"Wrong kd split type "<<splitType<<endl; 
    45         exit(1); 
    46       } 
    47   splitCandidates = NULL; 
    48 } 
    49  
    50 bool 
    51 ViewCellKd::Construct() 
    52 { 
    53   if (!splitCandidates) 
     113    if (name.compare("heuristic") == 0) 
     114      splitType = ESplitHeuristic; 
     115                else { 
     116                        cerr<<"Invalid VspKdTree split type "<<name<<endl; 
     117                        exit(1); 
     118                } 
     119         
     120  environment->GetBoolValue("VspKdTree.randomize", randomize); 
     121 
     122  root = NULL; 
     123   
     124  splitCandidates = new vector<SortableEntry>; 
     125} 
     126 
     127 
     128VspKdTree::~VspKdTree() 
     129{ 
     130  if (root) 
     131    delete root; 
     132} 
     133 
     134 
     135 
     136 
     137void 
     138VspKdStatistics::Print(ostream &app) const 
     139{ 
     140  app << "===== VspKdTree statistics ===============\n"; 
     141 
     142  app << "#N_RAYS ( Number of rays )\n" 
     143      << rays <<endl; 
     144 
     145        app << "#N_INITPVS ( Initial PVS size )\n" 
     146      << initialPvsSize <<endl; 
     147   
     148  app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 
     149 
     150  app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 
     151 
     152  app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n"; 
     153  for (int i=0; i<7; i++) 
     154    app << splits[i] <<" "; 
     155  app <<endl; 
     156 
     157  app << "#N_RAYREFS ( Number of rayRefs )\n" << 
     158    rayRefs << "\n"; 
     159 
     160  app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" << 
     161    rayRefs/(double)rays << "\n"; 
     162 
     163  app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" << 
     164    rayRefs/(double)Leaves() << "\n"; 
     165 
     166  app << "#N_MAXRAYREFS  ( Max number of rayRefs / leaf )\n" << 
     167    maxRayRefs << "\n"; 
     168 
     169 
     170  //  app << setprecision(4); 
     171 
     172  app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<< 
     173    maxDepthNodes*100/(double)Leaves()<<endl; 
     174 
     175  app << "#N_PMINPVSLEAVES  ( Percentage of leaves with minCost )\n"<< 
     176    minPvsNodes*100/(double)Leaves()<<endl; 
     177 
     178  app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minCost )\n"<< 
     179    minRaysNodes*100/(double)Leaves()<<endl; 
     180         
     181        app << "#N_PMINSIZELEAVES  ( Percentage of leaves with minSize )\n"<< 
     182    minSizeNodes*100/(double)Leaves()<<endl; 
     183 
     184        app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n"<< 
     185    maxRayContribNodes*100/(double)Leaves()<<endl; 
     186 
     187  app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<< 
     188    addedRayRefs<<endl; 
     189 
     190  app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<< 
     191    removedRayRefs<<endl; 
     192 
     193  //  app << setprecision(4); 
     194 
     195  app << "#N_CTIME  ( Construction time [s] )\n" 
     196      << Time() << " \n"; 
     197 
     198  app << "===== END OF VspKdTree statistics ==========\n"; 
     199 
     200} 
     201 
     202 
     203void 
     204VspKdTreeLeaf::UpdatePvsSize() 
     205{ 
     206        if (!mValidPvs) { 
     207                Intersectable::NewMail(); 
     208                int pvsSize = 0; 
     209                for(VspKdTreeNode::RayInfoContainer::iterator ri = rays.begin(); 
     210                                ri != rays.end(); 
     211                                ri++) 
     212                        if ((*ri).mRay->IsActive()) { 
     213                                Intersectable *object; 
     214#if BIDIRECTIONAL_RAY 
     215                                object = (*ri).mRay->mOriginObject; 
     216                                if (object && !object->Mailed()) { 
     217                                        pvsSize++; 
     218                                        object->Mail(); 
     219                                } 
     220#endif 
     221                                object = (*ri).mRay->mTerminationObject; 
     222                                if (object && !object->Mailed()) { 
     223                                        pvsSize++; 
     224                                        object->Mail(); 
     225                                } 
     226                        } 
     227                mPvsSize = pvsSize; 
     228                mValidPvs = true; 
     229        } 
     230} 
     231 
     232 
     233void 
     234VspKdTree::Construct( 
     235                                                                         VssRayContainer &rays, 
     236                                                                         AxisAlignedBox3 *forcedBoundingBox 
     237                                                                         ) 
     238{ 
     239  stat.Start(); 
     240   
     241        maxMemory = maxStaticMemory; 
     242 
     243  if (root) 
     244    delete root; 
     245 
     246  root = new VspKdTreeLeaf(NULL, rays.size()); 
     247  // first construct a leaf that will get subdivide 
     248  VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) root; 
     249 
     250  stat.nodes = 1; 
     251   
     252  bbox.Initialize(); 
     253  dirBBox.Initialize(); 
     254   
     255  for(VssRayContainer::const_iterator ri = rays.begin(); 
     256      ri != rays.end(); 
     257      ri++) { 
     258    leaf->AddRay(VspKdTreeNode::RayInfo(*ri)); 
     259 
     260    bbox.Include((*ri)->GetOrigin()); 
     261    bbox.Include((*ri)->GetTermination()); 
     262     
     263                 
     264                dirBBox.Include(Vector3( 
     265                                                                                                                (*ri)->GetDirParametrization(0), 
     266                                                                                                                (*ri)->GetDirParametrization(1), 
     267                                                                                                                0 
     268                                                                                                                ) 
     269                                                                                ); 
     270        } 
     271         
     272         
     273        if ( forcedBoundingBox ) 
     274                bbox = *forcedBoundingBox; 
     275 
     276        cout<<"Bbox = "<<bbox<<endl; 
     277        cout<<"Dirr Bbox = "<<dirBBox<<endl; 
     278 
     279  stat.rays = leaf->rays.size(); 
     280        leaf->UpdatePvsSize(); 
     281  stat.initialPvsSize = leaf->GetPvsSize(); 
     282  // Subdivide(); 
     283  root = Subdivide(TraversalData(leaf, bbox, 0)); 
     284 
     285  if (splitCandidates) { 
     286    // force realease of this vector 
     287    delete splitCandidates; 
    54288    splitCandidates = new vector<SortableEntry>; 
    55  
    56   // first construct a leaf that will get subdivide 
    57   ViewCellKdLeaf *leaf = (ViewCellKdLeaf *) mRoot; 
    58  
    59   mStat.nodes = 1; 
    60  
    61   mBox.Initialize(); 
    62    
    63   ObjectContainer::const_iterator mi; 
    64   for ( mi = leaf->mObjects.begin(); 
    65         mi != leaf->mObjects.end(); 
    66         mi++) { 
    67     mBox.Include((*mi)->GetBox()); 
    68   } 
    69  
    70   cout <<"ViewCellKd Root Box:"<< mBox<<endl; 
    71   mRoot = Subdivide(TraversalData(leaf, mBox, 0)); 
    72  
    73   // remove the allocated array 
    74   delete splitCandidates; 
    75  
    76   return true; 
    77 } 
    78  
    79 ViewCellKdNode * 
    80 ViewCellKd::Subdivide(const TraversalData &tdata) 
    81 { 
    82  
    83   ViewCellKdNode *result = NULL; 
     289  } 
     290   
     291  stat.Stop(); 
     292 
     293        stat.Print(cout); 
     294        cout<<"#Total memory="<<GetMemUsage()<<endl; 
     295 
     296} 
     297 
     298 
     299 
     300VspKdTreeNode * 
     301VspKdTree::Subdivide(const TraversalData &tdata) 
     302{ 
     303  VspKdTreeNode *result = NULL; 
    84304 
    85305  priority_queue<TraversalData> tStack; 
    86   //  stack<STraversalData> tStack; 
     306  //  stack<TraversalData> tStack; 
    87307   
    88308  tStack.push(tdata); 
    89   AxisAlignedBox3 backBox, frontBox; 
    90  
    91    
     309 
     310  AxisAlignedBox3 backBox; 
     311  AxisAlignedBox3 frontBox; 
     312 
     313   
     314        int lastMem = 0; 
    92315  while (!tStack.empty()) { 
    93316 
    94 #if 0 
    95     if ( GetMemUsage() > maxMemory ) { 
     317                float mem = GetMemUsage(); 
     318                 
     319                if ( lastMem/10 != ((int)mem)/10) { 
     320                        cout<<mem<<" MB"<<endl; 
     321                } 
     322                lastMem = (int)mem; 
     323                 
     324                if (  mem > maxMemory ) { 
    96325      // count statistics on unprocessed leafs 
    97326      while (!tStack.empty()) { 
    98         EvaluateLeafStats(tStack.top()); 
    99         tStack.pop(); 
     327                                EvaluateLeafStats(tStack.top()); 
     328                                tStack.pop(); 
    100329      } 
    101330      break; 
    102331    } 
    103 #endif 
    104  
     332     
    105333    TraversalData data = tStack.top(); 
    106334    tStack.pop(); 
    107335     
    108     ViewCellKdNode *node = SubdivideNode((ViewCellKdLeaf *) data.mNode, 
    109                                  data.mBox, 
    110                                  backBox, 
    111                                  frontBox 
    112                                  ); 
     336    VspKdTreeNode *node = SubdivideNode((VspKdTreeLeaf *) data.node, 
     337                                                                                                                                                        data.bbox, 
     338                                                                                                                                                        backBox, 
     339                                                                                                                                                        frontBox 
     340                                                                                                                                                        ); 
    113341    if (result == NULL) 
    114342      result = node; 
    115343     
    116344    if (!node->IsLeaf()) { 
    117  
    118       ViewCellKdInterior *interior = (ViewCellKdInterior *) node; 
     345                         
     346      VspKdTreeInterior *interior = (VspKdTreeInterior *) node; 
    119347      // push the children on the stack 
    120       tStack.push(TraversalData(interior->mBack, backBox, data.mDepth+1)); 
    121       tStack.push(TraversalData(interior->mFront, frontBox, data.mDepth+1)); 
    122        
     348      tStack.push(TraversalData(interior->back, backBox, data.depth+1)); 
     349      tStack.push(TraversalData(interior->front, frontBox, data.depth+1)); 
     350                         
    123351    } else { 
    124352      EvaluateLeafStats(data); 
    125353    } 
    126354  } 
    127    
     355 
    128356  return result; 
    129  
    130 } 
    131  
    132  
    133  
    134 bool 
    135 ViewCellKd::TerminationCriteriaMet(const ViewCellKdLeaf *leaf) 
    136 { 
    137   //  cerr<<"\n OBJECTS="<<leaf->mObjects.size()<<endl; 
    138   return 
    139     (leaf->mObjects.size() <= mTermMinCost) || 
    140     (leaf->mDepth >= mTermMaxDepth); 
    141    
    142 } 
    143  
    144  
     357} 
     358 
     359 
     360// returns selected plane for subdivision 
    145361int 
    146 ViewCellKd::SelectPlane(ViewCellKdLeaf *leaf, 
    147                     const AxisAlignedBox3 &box, 
    148                     float &position 
    149                     ) 
    150 { 
    151   int axis = -1; 
    152    
    153   switch (mSplitMethod) 
    154     { 
    155     case SPLIT_SPATIAL_MEDIAN: { 
    156       axis = box.Size().DrivingAxis(); 
    157       position = (box.Min()[axis] + box.Max()[axis])*0.5f; 
    158       break; 
     362VspKdTree::SelectPlane( 
     363                                                                                 VspKdTreeLeaf *leaf, 
     364                                                                                 const AxisAlignedBox3 &box, 
     365                                                                                 float &position, 
     366                                                                                 int &raysBack, 
     367                                                                                 int &raysFront, 
     368                                                                                 int &pvsBack, 
     369                                                                                 int &pvsFront 
     370                                                                                 ) 
     371{ 
     372 
     373  int minDirDepth = 6; 
     374  int axis; 
     375        float costRatio; 
     376         
     377  if (splitType == ESplitRegular) { 
     378                costRatio = BestCostRatioRegular(leaf, 
     379                                                                                                                                                 axis, 
     380                                                                                                                                                 position, 
     381                                                                                                                                                 raysBack, 
     382                                                                                                                                                 raysFront, 
     383                                                                                                                                                 pvsBack, 
     384                                                                                                                                                 pvsFront 
     385                                                                                                                                                 ); 
     386 
     387        } else { 
     388    if (splitType == ESplitHeuristic) 
     389      costRatio = BestCostRatioHeuristic(leaf, 
     390                                                                                                                                                                 axis, 
     391                                                                                                                                                                 position, 
     392                                                                                                                                                                 raysBack, 
     393                                                                                                                                                                 raysFront, 
     394                                                                                                                                                                 pvsBack, 
     395                                                                                                                                                                 pvsFront 
     396                                                                                                                                                                 ); 
     397                else { 
     398                        cerr<<"VspKdTree: Unknown split heuristics\n"; 
     399                        exit(1); 
     400                } 
     401  } 
     402 
     403        if (costRatio > termMaxCostRatio) { 
     404                //              cout<<"Too big cost ratio "<<costRatio<<endl; 
     405                return -1; 
     406        } 
     407 
     408#if 0    
     409        cout<< 
     410                "pvs="<<leaf->mPvsSize<< 
     411                " rays="<<leaf->rays.size()<< 
     412                " rc="<<leaf->GetAvgRayContribution()<< 
     413                " axis="<<axis<<endl; 
     414#endif 
     415         
     416        return axis; 
     417} 
     418 
     419 
     420                                                         
     421 
     422float 
     423VspKdTree::EvalCostRatio( 
     424                                                                                         VspKdTreeLeaf *leaf, 
     425                                                                                         const int axis, 
     426                                                                                         const float position, 
     427                                                                                         int &raysBack, 
     428                                                                                         int &raysFront, 
     429                                                                                         int &pvsBack, 
     430                                                                                         int &pvsFront 
     431                                                                                         ) 
     432{ 
     433        raysBack = 0; 
     434        raysFront = 0; 
     435        pvsFront = 0; 
     436        pvsBack = 0; 
     437 
     438        float newCost; 
     439 
     440        Intersectable::NewMail(3); 
     441         
     442        // eval pvs size 
     443        int pvsSize = leaf->GetPvsSize(); 
     444 
     445        Intersectable::NewMail(3); 
     446 
     447        if (axis <= VspKdTreeNode::SPLIT_Z) { 
     448    // this is the main ray classification loop! 
     449    for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     450                                ri != leaf->rays.end(); 
     451                                ri++) 
     452      if ((*ri).mRay->IsActive()) { 
     453                                 
     454                                // determine the side of this ray with respect to the plane 
     455                                int side = (*ri).ComputeRayIntersection(axis, position, (*ri).mRay->mT); 
     456                                //                              (*ri).mRay->mSide = side; 
     457                                 
     458                                if (side <= 0) 
     459                                        raysBack++; 
     460                                 
     461                                if (side >= 0) 
     462                                        raysFront++; 
     463                                 
     464                                AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 
     465      } 
     466                 
     467                AxisAlignedBox3 box = GetBBox(leaf); 
     468                 
     469                float minBox = box.Min(axis); 
     470                float maxBox = box.Max(axis); 
     471                float sizeBox = maxBox - minBox; 
     472                 
     473                //              float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 
     474                float sum = pvsBack*(position - minBox) + pvsFront*(maxBox - position); 
     475 
     476                newCost = ct_div_ci + sum/sizeBox; 
     477                 
     478  } else { 
     479                 
     480                // directional split 
     481    for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     482                                ri != leaf->rays.end(); 
     483                                ri++) 
     484      if ((*ri).mRay->IsActive()) { 
     485                                 
     486                                // determine the side of this ray with respect to the plane 
     487                                int side; 
     488                                if ((*ri).mRay->GetDirParametrization(axis - 3) > position) 
     489                                        side = 1; 
     490                                else 
     491                                        side = -1; 
     492 
     493                                if (side <= 0) 
     494                                        raysBack++; 
     495                                 
     496                                if (side >= 0) 
     497                                        raysFront++; 
     498 
     499                                //                              (*ri).mRay->mSide = side; 
     500                                AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 
     501 
     502      } 
     503                 
     504                AxisAlignedBox3 box = GetDirBBox(leaf); 
     505                 
     506                float minBox = box.Min(axis-3); 
     507                float maxBox = box.Max(axis-3); 
     508                float sizeBox = maxBox - minBox; 
     509                 
     510                //              float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 
     511                float sum = 
     512                        pvsBack*(position - minBox) + 
     513                        pvsFront*(maxBox - position); 
     514                //              float sum = pvsBack + pvsFront; 
     515                newCost = ct_div_ci + sum/sizeBox; 
     516  } 
     517 
     518        //      cout<<axis<<" "<<pvsSize<<" "<<pvsBack<<" "<<pvsFront<<endl; 
     519        //  float oldCost = leaf->rays.size(); 
     520        float oldCost = pvsSize; 
     521  float ratio = newCost/oldCost; 
     522        //      cout<<"ratio="<<ratio<<endl; 
     523        return ratio; 
     524} 
     525 
     526float 
     527VspKdTree::BestCostRatioRegular( 
     528                                                                                                                        VspKdTreeLeaf *leaf, 
     529                                                                                                                        int &axis, 
     530                                                                                                                        float &position, 
     531                                                                                                                        int &raysBack, 
     532                                                                                                                        int &raysFront, 
     533                                                                                                                        int &pvsBack, 
     534                                                                                                                        int &pvsFront 
     535                                                                                                                        ) 
     536{ 
     537        int nRaysBack[6], nRaysFront[6]; 
     538        int nPvsBack[6], nPvsFront[6]; 
     539        float nPosition[6]; 
     540        float nCostRatio[6]; 
     541        int bestAxis = -1; 
     542         
     543        AxisAlignedBox3 sBox = GetBBox(leaf); 
     544        AxisAlignedBox3 dBox = GetDirBBox(leaf); 
     545        // int sAxis = box.Size().DrivingAxis(); 
     546        int sAxis = sBox.Size().DrivingAxis(); 
     547        int dAxis = dBox.Size().DrivingAxis() + 3; 
     548 
     549        bool onlyDrivingAxis = true;  
     550 
     551        for (axis = 0; axis < 6; axis++) { 
     552                if (!onlyDrivingAxis || axis == sAxis || axis == dAxis) { 
     553                        if (axis < 3) 
     554                                nPosition[axis] = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f; 
     555                        else 
     556                                nPosition[axis] = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f; 
     557                         
     558                        nCostRatio[axis] = EvalCostRatio(leaf, 
     559                                                                                                                                                         axis, 
     560                                                                                                                                                         nPosition[axis], 
     561                                                                                                                                                         nRaysBack[axis], 
     562                                                                                                                                                         nRaysFront[axis], 
     563                                                                                                                                                         nPvsBack[axis], 
     564                                                                                                                                                         nPvsFront[axis] 
     565                                                                                                                                                         ); 
     566                         
     567                        if ( bestAxis == -1) 
     568                                bestAxis = axis; 
     569                        else 
     570                                if ( nCostRatio[axis] < nCostRatio[bestAxis] ) 
     571                                        bestAxis = axis; 
     572                } 
     573        } 
     574 
     575        axis = bestAxis; 
     576        position = nPosition[bestAxis]; 
     577 
     578        raysBack = nRaysBack[bestAxis]; 
     579        raysFront = nRaysFront[bestAxis]; 
     580 
     581        pvsBack = nPvsBack[bestAxis]; 
     582        pvsFront = nPvsFront[bestAxis]; 
     583         
     584        return nCostRatio[bestAxis]; 
     585} 
     586 
     587float 
     588VspKdTree::BestCostRatioHeuristic( 
     589                                                                                                                                VspKdTreeLeaf *leaf, 
     590                                                                                                                                int &axis, 
     591                                                                                                                                float &position, 
     592                                                                                                                                int &raysBack, 
     593                                                                                                                                int &raysFront, 
     594                                                                                                                                int &pvsBack, 
     595                                                                                                                                int &pvsFront 
     596                                                                                                                                ) 
     597{ 
     598        AxisAlignedBox3 box = GetBBox(leaf); 
     599        //      AxisAlignedBox3 dirBox = GetDirBBox(node); 
     600         
     601        axis = box.Size().DrivingAxis(); 
     602                 
     603        SortSplitCandidates(leaf, axis); 
     604   
     605        // go through the lists, count the number of objects left and right 
     606        // and evaluate the following cost funcion: 
     607        // C = ct_div_ci  + (ql*rl + qr*rr)/queries 
     608         
     609        int rl=0, rr = leaf->rays.size(); 
     610        int pl=0, pr = leaf->GetPvsSize(); 
     611        float minBox = box.Min(axis); 
     612        float maxBox = box.Max(axis); 
     613        float sizeBox = maxBox - minBox; 
     614         
     615        float minBand = minBox + 0.1*(maxBox - minBox); 
     616        float maxBand = minBox + 0.9*(maxBox - minBox); 
     617         
     618        float sum = rr*sizeBox; 
     619        float minSum = 1e20; 
     620         
     621        Intersectable::NewMail(); 
     622        // set all object as belonging to the fron pvs 
     623        for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     624                        ri != leaf->rays.end(); 
     625                        ri++) 
     626                if ((*ri).mRay->IsActive()) { 
     627                        Intersectable *object = (*ri).mRay->mTerminationObject; 
     628                        if (object) 
     629                                if (!object->Mailed()) { 
     630                                        object->Mail(); 
     631                                        object->mCounter = 1; 
     632                                } else 
     633                                        object->mCounter++; 
     634                } 
     635         
     636        Intersectable::NewMail(); 
     637         
     638        for(vector<SortableEntry>::const_iterator ci = splitCandidates->begin(); 
     639                        ci < splitCandidates->end(); 
     640                        ci++) { 
     641                VssRay *ray; 
     642                switch ((*ci).type) { 
     643                case SortableEntry::ERayMin: { 
     644                        rl++; 
     645                        ray = (VssRay *) (*ci).data; 
     646                        Intersectable *object = ray->mTerminationObject; 
     647                        if (object && !object->Mailed()) { 
     648                                object->Mail(); 
     649                                pl++; 
     650                        } 
     651                        break; 
     652                } 
     653                case SortableEntry::ERayMax: { 
     654                        rr--; 
     655                        ray = (VssRay *) (*ci).data; 
     656                        Intersectable *object = ray->mTerminationObject; 
     657                        if (object) { 
     658                                if (--object->mCounter == 0) 
     659                                        pr--; 
     660                        } 
     661                        break; 
     662                } 
     663                } 
     664                if ((*ci).value > minBand && (*ci).value < maxBand) { 
     665                         
     666                        sum = pl*((*ci).value - minBox) + pr*(maxBox - (*ci).value); 
     667                         
     668                        //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl; 
     669                        //      cout<<"cost= "<<sum<<endl; 
     670                         
     671                        if (sum < minSum) { 
     672                                minSum = sum; 
     673                                position = (*ci).value; 
     674                                 
     675                                raysBack = rl; 
     676                                raysFront = rr; 
     677                                 
     678                                pvsBack = pl; 
     679                                pvsFront = pr; 
     680                                 
     681      } 
    159682    } 
    160     case SPLIT_SAH: { 
    161       int objectsBack, objectsFront; 
    162       float costRatio; 
    163       bool mOnlyDrivingAxis = false; 
    164       if (mOnlyDrivingAxis) { 
    165                                 axis = box.Size().DrivingAxis(); 
    166                                 costRatio = BestCostRatio(leaf, 
    167                                                                                                                                         box, 
    168                                                                                                                                         axis, 
    169                                                                                                                                         position, 
    170                                                                                                                                         objectsBack, 
    171                                                                                                                                         objectsFront); 
    172       } else { 
    173                                 costRatio = MAX_FLOAT; 
    174                                 for (int i=0; i < 3; i++) { 
    175                                         float p; 
    176                                         float r = BestCostRatio(leaf, 
    177                                                                                                                                         box, 
    178                                                                                                                                         i, 
    179                                                                                                                                         p, 
    180                                                                                                                                         objectsBack, 
    181                                                                                                                                         objectsFront); 
    182                                         if (r < costRatio) { 
    183                                                 costRatio = r; 
    184                                                 axis = i; 
    185                                                 position = p; 
    186                                         } 
    187                                 } 
    188       } 
    189        
    190       if (costRatio > mMaxCostRatio) { 
    191                                 //      cout<<"Too big cost ratio "<<costRatio<<endl; 
    192                                 axis = -1; 
    193       } 
    194       break; 
    195     } 
    196      
    197     } 
    198   return axis; 
    199 } 
    200  
    201 ViewCellKdNode * 
    202 ViewCellKd::SubdivideNode( 
    203                       ViewCellKdLeaf *leaf, 
    204                       const AxisAlignedBox3 &box, 
    205                       AxisAlignedBox3 &backBBox, 
    206                       AxisAlignedBox3 &frontBBox 
    207                       ) 
    208 { 
    209    
    210   if (TerminationCriteriaMet(leaf)) 
    211     return leaf; 
    212    
    213   float position; 
    214    
    215   // select subdivision axis 
    216   int axis = SelectPlane( leaf, box, position ); 
    217  
    218   if (axis == -1) { 
    219     return leaf; 
    220   } 
    221    
    222   mStat.nodes+=2; 
    223   mStat.splits[axis]++; 
    224    
    225   // add the new nodes to the tree 
    226   ViewCellKdInterior *node = new ViewCellKdInterior(leaf->mParent); 
    227  
    228   node->mAxis = axis; 
    229   node->mPosition = position; 
    230   node->mBox = box; 
    231    
    232   backBBox = box; 
    233   frontBBox = box; 
    234    
    235   // first count ray sides 
    236   int objectsBack = 0; 
    237   int objectsFront = 0; 
    238    
    239   backBBox.SetMax(axis, position); 
    240   frontBBox.SetMin(axis, position); 
    241  
    242   ObjectContainer::const_iterator mi; 
    243  
    244   for ( mi = leaf->mObjects.begin(); 
    245         mi != leaf->mObjects.end(); 
    246         mi++) { 
    247     // determine the side of this ray with respect to the plane 
    248     AxisAlignedBox3 box = (*mi)->GetBox(); 
    249     if (box.Max(axis) > position )  
    250       objectsFront++; 
    251      
    252     if (box.Min(axis) < position ) 
    253       objectsBack++; 
    254   } 
    255  
    256    
    257   ViewCellKdLeaf *back = new ViewCellKdLeaf(node, objectsBack); 
    258   ViewCellKdLeaf *front = new ViewCellKdLeaf(node, objectsFront); 
    259  
    260   // replace a link from node's parent 
    261   if (  leaf->mParent ) 
    262     leaf->mParent->ReplaceChildLink(leaf, node); 
    263  
    264   // and setup child links 
    265   node->SetupChildLinks(back, front); 
    266    
    267   for (mi = leaf->mObjects.begin(); 
    268        mi != leaf->mObjects.end(); 
    269        mi++) { 
    270     // determine the side of this ray with respect to the plane 
    271     AxisAlignedBox3 box = (*mi)->GetBox(); 
    272  
    273     if (box.Max(axis) >= position ) 
    274       front->mObjects.push_back(*mi); 
    275      
    276     if (box.Min(axis) < position ) 
    277       back->mObjects.push_back(*mi); 
    278      
    279     mStat.objectRefs -= (int)leaf->mObjects.size(); 
    280     mStat.objectRefs += objectsBack + objectsFront; 
    281   } 
    282    
    283   delete leaf; 
    284   return node; 
    285 } 
    286  
    287  
     683  } 
     684   
     685  float oldCost = leaf->GetPvsSize(); 
     686  float newCost = ct_div_ci + minSum/sizeBox; 
     687  float ratio = newCost/oldCost; 
     688   
     689  //  cout<<"===================="<<endl; 
     690  //  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox) 
     691  //      <<"\t q=("<<queriesBack<<","<<queriesFront<<")\t r=("<<raysBack<<","<<raysFront<<")"<<endl; 
     692        return ratio; 
     693} 
    288694 
    289695void 
    290 ViewCellKdTreeStatistics::Print(ostream &app) const 
    291 { 
    292   app << "===== ViewCellKd statistics ===============\n"; 
    293  
    294   app << "#N_RAYS Number of rays )\n" 
    295       << rays <<endl; 
    296   app << "#N_DOMAINS  ( Number of query domains )\n" 
    297       << queryDomains <<endl; 
    298    
    299   app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 
    300  
    301   app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 
    302  
    303   app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n"; 
    304   for (int i=0; i<7; i++) 
    305     app << splits[i] <<" "; 
    306   app <<endl; 
    307  
    308   app << "#N_RAYREFS ( Number of rayRefs )\n" << 
    309     rayRefs << "\n"; 
    310  
    311   app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" << 
    312     rayRefs/(double)rays << "\n"; 
    313  
    314   app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" << 
    315     rayRefs/(double)Leaves() << "\n"; 
    316  
    317   app << "#N_MAXOBJECTREFS  ( Max number of rayRefs / leaf )\n" << 
    318     maxObjectRefs << "\n"; 
    319  
    320   app << "#N_NONEMPTYRAYREFS  ( Number of rayRefs in nonEmpty leaves / non empty leaf )\n" << 
    321     rayRefsNonZeroQuery/(double)(Leaves() - zeroQueryNodes) << "\n"; 
    322  
    323   app << "#N_LEAFDOMAINREFS  ( Number of query domain Refs / leaf )\n" << 
    324     objectRefs/(double)Leaves() << "\n"; 
    325  
    326   //  app << setprecision(4); 
    327  
    328   app << "#N_PEMPTYLEAVES  ( Percentage of leaves with zero query domains )\n"<< 
    329     zeroQueryNodes*100/(double)Leaves()<<endl; 
    330  
    331   app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<< 
    332     maxDepthNodes*100/(double)Leaves()<<endl; 
    333  
    334   app << "#N_PMINCOSTLEAVES  ( Percentage of leaves with minCost )\n"<< 
    335     minCostNodes*100/(double)Leaves()<<endl; 
    336  
    337   app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<< 
    338     addedRayRefs<<endl; 
    339  
    340   app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<< 
    341     removedRayRefs<<endl; 
    342  
    343   //  app << setprecision(4); 
    344  
    345   //  app << "#N_CTIME  ( Construction time [s] )\n" 
    346   //      << Time() << " \n"; 
    347  
    348   app << "===== END OF ViewCellKd statistics ==========\n"; 
    349  
    350 } 
    351  
    352  
    353  
    354 void 
    355 ViewCellKd::EvaluateLeafStats(const TraversalData &data) 
    356 { 
    357  
    358   // the node became a leaf -> evaluate stats for leafs 
    359   ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)data.mNode; 
    360  
    361   if (data.mDepth > mTermMaxDepth) 
    362     mStat.maxDepthNodes++; 
    363    
    364   if ( (int)(leaf->mObjects.size()) < mTermMinCost) 
    365     mStat.minCostNodes++; 
    366    
    367    
    368   if ( (int)(leaf->mObjects.size()) > mStat.maxObjectRefs) 
    369     mStat.maxObjectRefs = (int)leaf->mObjects.size(); 
    370    
    371 } 
    372  
    373  
    374  
    375 void 
    376 ViewCellKd::SortSplitCandidates( 
    377                             ViewCellKdLeaf *node, 
    378                             const int axis 
    379                             ) 
    380 { 
     696VspKdTree::SortSplitCandidates( 
     697                                                                                                                 VspKdTreeLeaf *node, 
     698                                                                                                                 const int axis 
     699                                                                                                                 ) 
     700{ 
     701   
    381702  splitCandidates->clear(); 
    382703   
    383   int requestedSize = 2 * (int)node->mObjects.size(); 
     704  int requestedSize = 2*(node->rays.size()); 
    384705  // creates a sorted split candidates array 
    385706  if (splitCandidates->capacity() > 500000 && 
    386707      requestedSize < (int)(splitCandidates->capacity()/10) ) { 
     708     
    387709    delete splitCandidates; 
    388710    splitCandidates = new vector<SortableEntry>; 
     
    390712   
    391713  splitCandidates->reserve(requestedSize); 
    392    
     714 
    393715  // insert all queries  
    394   for(ObjectContainer::const_iterator mi = node->mObjects.begin(); 
    395       mi != node->mObjects.end(); 
    396       mi++) { 
    397     AxisAlignedBox3 box = (*mi)->GetBox(); 
    398  
    399     splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MIN, 
    400                                              box.Min(axis), 
    401                                              *mi) 
    402                                ); 
     716  for(VspKdTreeNode::RayInfoContainer::const_iterator ri = node->rays.begin(); 
     717      ri < node->rays.end(); 
     718      ri++) { 
     719    bool positive = (*ri).mRay->HasPosDir(axis); 
     720    splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : 
     721                                                                                                                                                                                 SortableEntry::ERayMax, 
     722                                                                                                                                                                                 (*ri).ExtrapOrigin(axis), 
     723                                                                                                                                                                                 (void *)&*ri) 
     724                                                                                                                         ); 
     725                 
     726    splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : 
     727                                                                                                                                                                                 SortableEntry::ERayMin, 
     728                                                                                                                                                                                 (*ri).ExtrapTermination(axis), 
     729                                                                                                                                                                                 (void *)&*ri) 
     730                                                                                                                         ); 
     731  } 
     732         
     733  stable_sort(splitCandidates->begin(), splitCandidates->end()); 
     734} 
     735 
     736 
     737void 
     738VspKdTree::EvaluateLeafStats(const TraversalData &data) 
     739{ 
     740 
     741  // the node became a leaf -> evaluate stats for leafs 
     742  VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 
     743 
     744  if (data.depth >= termMaxDepth) 
     745    stat.maxDepthNodes++; 
     746   
     747        //  if ( (int)(leaf->rays.size()) < termMinCost) 
     748        //    stat.minCostNodes++; 
     749        if ( leaf->GetPvsSize() < termMinPvs) 
     750                stat.minPvsNodes++; 
     751 
     752        if ( leaf->GetPvsSize() < termMinRays) 
     753                stat.minRaysNodes++; 
     754 
     755        if (0 && leaf->GetAvgRayContribution() > termMaxRayContribution ) 
     756                stat.maxRayContribNodes++; 
     757         
     758        if (SqrMagnitude(data.bbox.Size()) <= termMinSize) { 
     759                stat.minSizeNodes++; 
     760        } 
     761 
     762        if ( (int)(leaf->rays.size()) > stat.maxRayRefs) 
     763    stat.maxRayRefs = leaf->rays.size(); 
     764 
     765} 
     766 
     767 
     768 
     769VspKdTreeNode * 
     770VspKdTree::SubdivideNode( 
     771                                                                                         VspKdTreeLeaf *leaf, 
     772                                                                                         const AxisAlignedBox3 &box, 
     773                                                                                         AxisAlignedBox3 &backBBox, 
     774                                                                                         AxisAlignedBox3 &frontBBox 
     775                                                                                         ) 
     776{ 
     777   
     778  if ( (leaf->GetPvsSize() < termMinPvs) || 
     779                         (leaf->rays.size() < termMinRays) || 
     780                         //                      (leaf->GetAvgRayContribution() > termMaxRayContribution ) || 
     781       (leaf->depth >= termMaxDepth) || 
     782                         SqrMagnitude(box.Size()) <= termMinSize ) { 
     783 
     784#if 0 
     785                if (leaf->depth >= termMaxDepth) { 
     786                        cout<<"Warning: max depth reached depth="<<(int)leaf->depth<<" rays="<<leaf->rays.size()<<endl; 
     787                        cout<<"Bbox: "<<GetBBox(leaf)<<" dirbbox:"<<GetDirBBox(leaf)<<endl; 
     788                } 
     789#endif 
     790                 
     791                return leaf; 
     792        } 
     793         
     794        float position; 
     795         
     796        // first count ray sides 
     797  int raysBack; 
     798  int raysFront; 
     799        int pvsBack; 
     800        int pvsFront; 
     801         
     802  // select subdivision axis 
     803  int axis = SelectPlane( leaf, box, position, raysBack, raysFront, pvsBack, pvsFront); 
     804 
     805        //      cout<<"rays back="<<raysBack<<" rays front="<<raysFront<<" pvs back="<<pvsBack<<" pvs front="<< 
     806        //              pvsFront<<endl; 
     807 
     808  if (axis == -1) { 
     809    return leaf; 
     810  } 
     811   
     812  stat.nodes+=2; 
     813  stat.splits[axis]++; 
     814 
     815  // add the new nodes to the tree 
     816  VspKdTreeInterior *node = new VspKdTreeInterior(leaf->parent); 
     817 
     818  node->axis = axis; 
     819  node->position = position; 
     820  node->bbox = box; 
     821  node->dirBBox = GetDirBBox(leaf); 
     822   
     823  backBBox = box; 
     824  frontBBox = box; 
     825 
     826  VspKdTreeLeaf *back = new VspKdTreeLeaf(node, raysBack); 
     827        back->SetPvsSize(pvsBack); 
     828  VspKdTreeLeaf *front = new VspKdTreeLeaf(node, raysFront); 
     829        front->SetPvsSize(pvsFront); 
     830 
     831  // replace a link from node's parent 
     832  if (  leaf->parent ) 
     833    leaf->parent->ReplaceChildLink(leaf, node); 
     834  // and setup child links 
     835  node->SetupChildLinks(back, front); 
     836         
     837  if (axis <= VspKdTreeNode::SPLIT_Z) { 
     838                backBBox.SetMax(axis, position); 
     839    frontBBox.SetMin(axis, position); 
     840                 
     841                for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     842                                ri != leaf->rays.end(); 
     843                                ri++) { 
     844      if ((*ri).mRay->IsActive()) { 
     845                                 
     846                                // first unref ray from the former leaf 
     847                                (*ri).mRay->Unref(); 
     848 
     849                                // determine the side of this ray with respect to the plane 
     850                                int side = node->ComputeRayIntersection(*ri, (*ri).mRay->mT); 
     851 
     852                                if (side == 0) { 
     853                                        if ((*ri).mRay->HasPosDir(axis)) { 
     854                                                back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 
     855                                                                                                                                                                                        (*ri).mMinT, 
     856                                                                                                                                                                                        (*ri).mRay->mT) 
     857                                                                                                 ); 
     858                                                front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 
     859                                                                                                                                                                                         (*ri).mRay->mT, 
     860                                                                                                                                                                                         (*ri).mMaxT)); 
     861                                        } else { 
     862                                                back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 
     863                                                                                                                                                                                        (*ri).mRay->mT, 
     864                                                                                                                                                                                        (*ri).mMaxT)); 
     865                                                front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 
     866                                                                                                                                                                                         (*ri).mMinT, 
     867                                                                                                                                                                                         (*ri).mRay->mT)); 
     868                                        } 
     869                                } else 
     870                                        if (side == 1)  
     871                                                front->AddRay(*ri); 
     872                                        else 
     873                                                back->AddRay(*ri); 
     874      } else 
     875                                (*ri).mRay->Unref(); 
     876    } 
     877  } else { 
     878    // rays front/back 
    403879     
    404880     
    405     splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MAX, 
    406                                              box.Max(axis), 
    407                                              *mi) 
    408                                ); 
    409   } 
    410    
    411   stable_sort(splitCandidates->begin(), splitCandidates->end()); 
    412 } 
    413  
    414  
    415 float 
    416 ViewCellKd::BestCostRatio( 
    417                                                                                         ViewCellKdLeaf *node, 
    418                                                                                         const AxisAlignedBox3 &box, 
    419                                                                                         const int axis, 
    420                                                                                         float &position, 
    421                                                                                         int &objectsBack, 
    422                                                                                         int &objectsFront 
    423                                                                                         ) 
    424 { 
    425  
    426   SortSplitCandidates(node, axis); 
    427    
    428   // go through the lists, count the number of objects left and right 
    429   // and evaluate the following cost funcion: 
    430   // C = ct_div_ci  + (ol + or)/queries 
    431  
    432   float totalIntersections = 0.0f; 
    433   vector<SortableEntry>::const_iterator ci; 
    434  
    435   for(ci = splitCandidates->begin(); 
    436       ci < splitCandidates->end(); 
    437       ci++)  
    438     if ((*ci).type == SortableEntry::BOX_MIN) { 
    439       totalIntersections += (*ci).intersectable->IntersectionComplexity(); 
     881    for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     882                                ri != leaf->rays.end(); 
     883                                ri++) { 
     884      if ((*ri).mRay->IsActive()) { 
     885                                // first unref ray from the former leaf 
     886                                (*ri).mRay->Unref(); 
     887 
     888                                int side; 
     889                                if ((*ri).mRay->GetDirParametrization(axis - 3) > position) 
     890                                        side = 1; 
     891                                else 
     892                                        side = -1; 
     893                                 
     894                                if (side == 1) 
     895                                        front->AddRay(*ri); 
     896                                else 
     897                                        back->AddRay(*ri); 
     898                                 
     899      } else 
     900                                (*ri).mRay->Unref(); 
    440901    } 
    441          
    442   float intersectionsLeft = 0; 
    443   float intersectionsRight = totalIntersections; 
    444          
    445   int objectsLeft = 0, objectsRight = (int)node->mObjects.size(); 
    446    
    447   float minBox = box.Min(axis); 
    448   float maxBox = box.Max(axis); 
    449   float boxArea = box.SurfaceArea(); 
    450    
    451   float minBand = minBox + mSplitBorder*(maxBox - minBox); 
    452   float maxBand = minBox + (1.0f - mSplitBorder)*(maxBox - minBox); 
    453    
    454   float minSum = 1e20; 
    455    
    456   for(ci = splitCandidates->begin(); 
    457       ci < splitCandidates->end(); 
    458       ci++) { 
    459     switch ((*ci).type) { 
    460     case SortableEntry::BOX_MIN: 
    461       objectsLeft++; 
    462       intersectionsLeft += (*ci).intersectable->IntersectionComplexity(); 
    463       break; 
    464     case SortableEntry::BOX_MAX: 
    465       objectsRight--; 
    466       intersectionsRight -= (*ci).intersectable->IntersectionComplexity(); 
    467       break; 
    468     } 
    469  
    470     if ((*ci).value > minBand && (*ci).value < maxBand) { 
    471       AxisAlignedBox3 lbox = box; 
    472       AxisAlignedBox3 rbox = box; 
    473       lbox.SetMax(axis, (*ci).value); 
    474       rbox.SetMin(axis, (*ci).value); 
    475  
    476       float sum; 
    477       if (mSahUseFaces) 
    478                                 sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea(); 
    479       else 
    480                                 sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea(); 
     902  } 
     903         
     904  // update stats 
     905  stat.rayRefs -= leaf->rays.size(); 
     906  stat.rayRefs += raysBack + raysFront; 
     907 
     908   
     909  delete leaf; 
     910  return node; 
     911} 
     912 
     913 
     914 
     915 
     916 
     917 
     918int 
     919VspKdTree::ReleaseMemory(const int time) 
     920{ 
     921  stack<VspKdTreeNode *> tstack; 
     922   
     923  // find a node in the tree which subtree will be collapsed 
     924  int maxAccessTime = time - accessTimeThreshold; 
     925  int released; 
     926 
     927  tstack.push(root); 
     928 
     929  while (!tstack.empty()) { 
     930    VspKdTreeNode *node = tstack.top(); 
     931    tstack.pop(); 
     932     
     933  
     934    if (!node->IsLeaf()) { 
     935      VspKdTreeInterior *in = (VspKdTreeInterior *)node; 
     936      //      cout<<"depth="<<(int)in->depth<<" time="<<in->lastAccessTime<<endl; 
     937      if (in->depth >= minCollapseDepth && 
     938          in->lastAccessTime <= maxAccessTime) { 
     939        released = CollapseSubtree(node, time); 
     940        break; 
     941      } 
    481942       
    482       //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl; 
    483       //      cout<<"cost= "<<sum<<endl; 
    484        
    485       if (sum < minSum) { 
    486                                 minSum = sum; 
    487                                 position = (*ci).value; 
    488                                  
    489                                 objectsBack = objectsLeft; 
    490                                 objectsFront = objectsRight; 
     943      if (in->back->GetAccessTime() <   
     944          in->front->GetAccessTime()) { 
     945        tstack.push(in->front); 
     946        tstack.push(in->back); 
     947      } else { 
     948        tstack.push(in->back); 
     949        tstack.push(in->front); 
    491950      } 
    492951    } 
    493952  } 
    494    
    495   float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size(); 
    496   float newCost = mCt_div_ci + minSum/boxArea; 
    497   float ratio = newCost/oldCost; 
    498    
    499 #if 0 
    500   cout<<"===================="<<endl; 
    501   cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox) 
    502       <<"\t o=("<<objectsBack<<","<<objectsFront<<")"<<endl; 
     953 
     954  while (tstack.empty()) { 
     955    // could find node to collaps... 
     956    //    cout<<"Could not find a node to release "<<endl; 
     957    break; 
     958  } 
     959   
     960  return released; 
     961} 
     962 
     963 
     964 
     965 
     966VspKdTreeNode * 
     967VspKdTree::SubdivideLeaf( 
     968                                                                                         VspKdTreeLeaf *leaf, 
     969                                                                                         const float sizeThreshold 
     970                                                                                         ) 
     971{ 
     972  VspKdTreeNode *node = leaf; 
     973 
     974  AxisAlignedBox3 leafBBox = GetBBox(leaf); 
     975 
     976        static int pass = 0; 
     977        pass ++; 
     978         
     979  // check if we should perform a dynamic subdivision of the leaf 
     980  if ( 
     981                        //      leaf->rays.size() > (unsigned)termMinCost && 
     982                        (leaf->GetPvsSize() >= termMinPvs) && 
     983      SqrMagnitude(leafBBox.Size()) > sizeThreshold) { 
     984     
     985                // memory check and realese... 
     986    if (GetMemUsage() > maxTotalMemory) { 
     987      ReleaseMemory( pass ); 
     988    } 
     989     
     990    AxisAlignedBox3 backBBox, frontBBox; 
     991 
     992    // subdivide the node 
     993    node = 
     994      SubdivideNode(leaf, 
     995                                                                                leafBBox, 
     996                                                                                backBBox, 
     997                                                                                frontBBox 
     998                                                                                ); 
     999  } 
     1000  return node; 
     1001} 
     1002 
     1003 
     1004 
     1005void 
     1006VspKdTree::UpdateRays(VssRayContainer &remove, 
     1007                                                                                VssRayContainer &add 
     1008                                                                                ) 
     1009{ 
     1010  VspKdTreeLeaf::NewMail(); 
     1011 
     1012  // schedule rays for removal 
     1013  for(VssRayContainer::const_iterator ri = remove.begin(); 
     1014      ri != remove.end(); 
     1015      ri++) { 
     1016    (*ri)->ScheduleForRemoval(); 
     1017  } 
     1018 
     1019  int inactive=0; 
     1020 
     1021  for(VssRayContainer::const_iterator ri = remove.begin(); 
     1022      ri != remove.end(); 
     1023      ri++) { 
     1024    if ((*ri)->ScheduledForRemoval()) 
     1025//      RemoveRay(*ri, NULL, false); 
     1026// !!! BUG - with true it does not work correctly - aggreated delete 
     1027      RemoveRay(*ri, NULL, true); 
     1028    else 
     1029      inactive++; 
     1030  } 
     1031 
     1032 
     1033  //  cout<<"all/inactive"<<remove.size()<<"/"<<inactive<<endl; 
     1034   
     1035  for(VssRayContainer::const_iterator ri = add.begin(); 
     1036      ri != add.end(); 
     1037      ri++) { 
     1038    AddRay(*ri); 
     1039  } 
     1040   
     1041 
     1042} 
     1043 
     1044 
     1045void 
     1046VspKdTree::RemoveRay(VssRay *ray, 
     1047                                                                         vector<VspKdTreeLeaf *> *affectedLeaves, 
     1048                                                                         const bool removeAllScheduledRays 
     1049                                                                         ) 
     1050{ 
     1051         
     1052  stack<RayTraversalData> tstack; 
     1053 
     1054  tstack.push(RayTraversalData(root, VspKdTreeNode::RayInfo(ray))); 
     1055   
     1056  RayTraversalData data; 
     1057 
     1058  // cout<<"Number of ray refs = "<<ray->RefCount()<<endl; 
     1059 
     1060  while (!tstack.empty()) { 
     1061    data = tstack.top(); 
     1062    tstack.pop(); 
     1063 
     1064    if (!data.node->IsLeaf()) { 
     1065      // split the set of rays in two groups intersecting the 
     1066      // two subtrees 
     1067 
     1068      TraverseInternalNode(data, tstack); 
     1069       
     1070    } else { 
     1071      // remove the ray from the leaf 
     1072      // find the ray in the leaf and swap it with the last ray... 
     1073      VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 
     1074       
     1075      if (!leaf->Mailed()) { 
     1076        leaf->Mail(); 
     1077        if (affectedLeaves) 
     1078          affectedLeaves->push_back(leaf); 
     1079         
     1080        if (removeAllScheduledRays) { 
     1081          int tail = leaf->rays.size()-1; 
     1082 
     1083          for (int i=0; i < (int)(leaf->rays.size()); i++) { 
     1084            if (leaf->rays[i].mRay->ScheduledForRemoval()) { 
     1085              // find a ray to replace it with 
     1086              while (tail >= i && leaf->rays[tail].mRay->ScheduledForRemoval()) { 
     1087                stat.removedRayRefs++; 
     1088                leaf->rays[tail].mRay->Unref(); 
     1089                leaf->rays.pop_back(); 
     1090                tail--; 
     1091              } 
     1092 
     1093              if (tail < i) 
     1094                break; 
     1095               
     1096              stat.removedRayRefs++; 
     1097              leaf->rays[i].mRay->Unref(); 
     1098              leaf->rays[i] = leaf->rays[tail]; 
     1099              leaf->rays.pop_back(); 
     1100              tail--; 
     1101            } 
     1102          } 
     1103        } 
     1104      } 
     1105       
     1106      if (!removeAllScheduledRays) 
     1107        for (int i=0; i < (int)leaf->rays.size(); i++) { 
     1108          if (leaf->rays[i].mRay == ray) { 
     1109            stat.removedRayRefs++; 
     1110            ray->Unref(); 
     1111            leaf->rays[i] = leaf->rays[leaf->rays.size()-1]; 
     1112            leaf->rays.pop_back(); 
     1113            // check this ray again 
     1114            break; 
     1115          } 
     1116        } 
     1117       
     1118    } 
     1119  } 
     1120 
     1121  if (ray->RefCount() != 0) { 
     1122    cerr<<"Error: Number of remaining refs = "<<ray->RefCount()<<endl; 
     1123    exit(1); 
     1124  } 
     1125   
     1126} 
     1127 
     1128 
     1129void 
     1130VspKdTree::AddRay(VssRay *ray) 
     1131{ 
     1132 
     1133  stack<RayTraversalData> tstack; 
     1134   
     1135  tstack.push(RayTraversalData(root, VspKdTreeNode::RayInfo(ray))); 
     1136   
     1137  RayTraversalData data; 
     1138   
     1139  while (!tstack.empty()) { 
     1140    data = tstack.top(); 
     1141    tstack.pop(); 
     1142 
     1143    if (!data.node->IsLeaf()) { 
     1144      TraverseInternalNode(data, tstack); 
     1145    } else { 
     1146      // remove the ray from the leaf 
     1147      // find the ray in the leaf and swap it with the last ray... 
     1148      VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 
     1149      leaf->AddRay(data.rayData); 
     1150      stat.addedRayRefs++; 
     1151    } 
     1152  } 
     1153} 
     1154 
     1155void 
     1156VspKdTree::TraverseInternalNode( 
     1157                                                                                                                        RayTraversalData &data, 
     1158                                                                                                                        stack<RayTraversalData> &tstack) 
     1159{ 
     1160  VspKdTreeInterior *in =  (VspKdTreeInterior *) data.node; 
     1161   
     1162  if (in->axis <= VspKdTreeNode::SPLIT_Z) { 
     1163 
     1164    // determine the side of this ray with respect to the plane 
     1165    int side = in->ComputeRayIntersection(data.rayData, 
     1166                                                                                                                                                                        data.rayData.mRay->mT); 
     1167     
     1168   
     1169    if (side == 0) { 
     1170      if (data.rayData.mRay->HasPosDir(in->axis)) { 
     1171                                tstack.push(RayTraversalData(in->back, 
     1172                                                                                                                                                 VspKdTreeNode::RayInfo(data.rayData.mRay, 
     1173                                                                                                                                                                                                                                        data.rayData.mMinT, 
     1174                                                                                                                                                                                                                                        data.rayData.mRay->mT)) 
     1175                                                                                ); 
     1176                                 
     1177                                tstack.push(RayTraversalData(in->front, 
     1178                                                                                                                                                 VspKdTreeNode::RayInfo(data.rayData.mRay, 
     1179                                                                                                                                                                                                                                        data.rayData.mRay->mT, 
     1180                                                                                                                                                                                                                                        data.rayData.mMaxT 
     1181                                                                                                                                                                                                                                        )) 
     1182                                                                                ); 
     1183         
     1184      } else { 
     1185                                tstack.push(RayTraversalData(in->back, 
     1186                                                                                                                                                 VspKdTreeNode::RayInfo(data.rayData.mRay, 
     1187                                                                                                                                                                                                                                        data.rayData.mRay->mT, 
     1188                                                                                                                                                                                                                                        data.rayData.mMaxT 
     1189                                                                                                                                                                                                                                        )) 
     1190                                                                                ); 
     1191                                 
     1192                                tstack.push(RayTraversalData(in->front, 
     1193                                                                                                                                                 VspKdTreeNode::RayInfo(data.rayData.mRay, 
     1194                                                                                                                                                                                                                                        data.rayData.mMinT, 
     1195                                                                                                                                                                                                                                        data.rayData.mRay->mT)) 
     1196                                                                                ); 
     1197                                 
     1198                                 
     1199      } 
     1200    } else 
     1201      if (side == 1) 
     1202                                tstack.push(RayTraversalData(in->front, data.rayData)); 
     1203      else 
     1204                                tstack.push(RayTraversalData(in->back, data.rayData)); 
     1205  }  
     1206  else { 
     1207    // directional split 
     1208                if (data.rayData.mRay->GetDirParametrization(in->axis - 3) > in->position) 
     1209                        tstack.push(RayTraversalData(in->front, data.rayData)); 
     1210                else 
     1211                        tstack.push(RayTraversalData(in->back, data.rayData)); 
     1212  } 
     1213} 
     1214 
     1215 
     1216int 
     1217VspKdTree::CollapseSubtree(VspKdTreeNode *sroot, const int time) 
     1218{ 
     1219  // first count all rays in the subtree 
     1220  // use mail 1 for this purpose 
     1221  stack<VspKdTreeNode *> tstack; 
     1222  int rayCount = 0; 
     1223  int totalRayCount = 0; 
     1224  int collapsedNodes = 0; 
     1225 
     1226#if DEBUG_COLLAPSE 
     1227  cout<<"Collapsing subtree"<<endl; 
     1228  cout<<"acessTime="<<sroot->GetAccessTime()<<endl; 
     1229  cout<<"depth="<<(int)sroot->depth<<endl; 
    5031230#endif 
    504   return ratio; 
    505 } 
    506  
    507 int 
    508 ViewCellKd::CastRay( 
    509                                                                 Ray &ray 
    510                                                                 ) 
    511 { 
    512   int hits = 0; 
    513    
    514   stack<RayTraversalData> tStack; 
    515    
    516   float maxt = 1e6; 
    517   float mint = 0; 
    518  
    519   Intersectable::NewMail(); 
    520  
    521   if (!mBox.GetMinMaxT(ray, &mint, &maxt)) 
    522     return 0; 
    523  
    524   if (mint < 0) 
    525     mint = 0; 
    526    
    527   maxt += Limits::Threshold; 
    528    
    529   Vector3 entp = ray.Extrap(mint); 
    530   Vector3 extp = ray.Extrap(maxt); 
    531    
    532   ViewCellKdNode *node = mRoot; 
    533   ViewCellKdNode *farChild; 
    534   float position; 
    535   int axis; 
    536    
    537   while (1) { 
    538     if (!node->IsLeaf()) { 
    539       ViewCellKdInterior *in = (ViewCellKdInterior *) node; 
    540       position = in->mPosition; 
    541       axis = in->mAxis; 
    542  
    543       if (entp[axis] <= position) { 
    544                                 if (extp[axis] <= position) { 
    545                                         node = in->mBack; 
    546                                         // cases N1,N2,N3,P5,Z2,Z3 
    547                                         continue; 
    548                                 } else { 
    549                                         // case N4 
    550                                         node = in->mBack; 
    551                                         farChild = in->mFront; 
    552                                 } 
    553       } 
    554       else { 
    555                                 if (position <= extp[axis]) { 
    556                                         node = in->mFront; 
    557                                         // cases P1,P2,P3,N5,Z1 
    558                                         continue; 
    559                                 } else { 
    560                                         node = in->mFront; 
    561                                         farChild = in->mBack; 
    562                                         // case P4 
    563                                 } 
    564                         } 
    565       // $$ modification 3.5.2004 - hints from Kamil Ghais 
    566       // case N4 or P4 
    567       float tdist = (position - ray.GetLoc(axis)) / ray.GetDir(axis); 
    568       tStack.push(RayTraversalData(farChild, extp, maxt)); 
    569       extp = ray.GetLoc() + ray.GetDir()*tdist; 
    570       maxt = tdist; 
    571                 } else { 
    572                         // compute intersection with all objects in this leaf 
    573                         ViewCellKdLeaf *leaf = (ViewCellKdLeaf *) node; 
    574 //                      if (ray.mFlags & Ray::STORE_KDLEAVES) 
    575 //                              ray.kdLeaves.push_back(leaf); 
    576                          
    577                         ObjectContainer::const_iterator mi; 
    578                         for ( mi = leaf->mObjects.begin(); 
    579                                                 mi != leaf->mObjects.end(); 
    580                                                 mi++) { 
    581                                 Intersectable *object = *mi; 
    582                                 if (!object->Mailed() ) { 
    583                                         object->Mail(); 
    584                                         if (ray.mFlags & Ray::STORE_TESTED_OBJECTS) 
    585                                                 ray.testedObjects.push_back(object); 
    586                                         hits += object->CastRay(ray); 
    587                                 } 
    588                         } 
    589                          
    590                         if (hits && ray.GetType() == Ray::LOCAL_RAY) 
    591                                 if (ray.intersections[0].mT <= maxt) 
    592                                         break; 
    593                          
    594                         // get the next node from the stack 
    595                         if (tStack.empty()) 
    596                                 break; 
    597                          
    598                         entp = extp; 
    599                         mint = maxt; 
    600                         if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f) 
    601                                 break; 
    602                          
    603                         RayTraversalData &s  = tStack.top(); 
    604                         node = s.mNode; 
    605                         extp = s.mExitPoint; 
    606                         maxt = s.mMaxT; 
    607                         tStack.pop(); 
    608                 } 
    609   } 
    610   return hits; 
    611 } 
    612  
    613 void 
    614 ViewCellKd::CollectObjects(ViewCellKdNode *n, ObjectContainer &objects) 
    615 { 
    616   stack<ViewCellKdNode *> nodeStack; 
    617  
    618   nodeStack.push(n); 
    619  
    620   while (!nodeStack.empty()) { 
    621     ViewCellKdNode *node = nodeStack.top(); 
    622     nodeStack.pop(); 
     1231 
     1232//    tstat.collapsedSubtrees++; 
     1233//    tstat.collapseDepths += (int)sroot->depth; 
     1234//    tstat.collapseAccessTimes += time - sroot->GetAccessTime(); 
     1235   
     1236  tstack.push(sroot); 
     1237  VssRay::NewMail(); 
     1238         
     1239  while (!tstack.empty()) { 
     1240    collapsedNodes++; 
     1241    VspKdTreeNode *node = tstack.top(); 
     1242    tstack.pop(); 
     1243 
    6231244    if (node->IsLeaf()) { 
    624       ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 
    625       for (int j=0; j < leaf->mObjects.size(); j++) { 
    626                                 Intersectable *object = leaf->mObjects[j]; 
    627                                 if (!object->Mailed()) { 
    628                                         object->Mail(); 
    629                                         objects.push_back(object); 
     1245      VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) node; 
     1246      for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     1247                                        ri != leaf->rays.end(); 
     1248                                        ri++) { 
     1249                                 
     1250                                totalRayCount++; 
     1251                                if ((*ri).mRay->IsActive() && !(*ri).mRay->Mailed()) { 
     1252                                        (*ri).mRay->Mail(); 
     1253                                        rayCount++; 
    6301254                                } 
    6311255      } 
    6321256    } else { 
    633       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    634       nodeStack.push(interior->mFront); 
    635       nodeStack.push(interior->mBack); 
     1257      tstack.push(((VspKdTreeInterior *)node)->back); 
     1258      tstack.push(((VspKdTreeInterior *)node)->front); 
    6361259    } 
    6371260  } 
    638 } 
    639  
    640 // Find random neighbor which was not mailed 
    641 ViewCellKdNode * 
    642 ViewCellKd::FindRandomNeighbor(ViewCellKdNode *n, 
    643                                                                                                          bool onlyUnmailed 
    644                                                                                                          ) 
    645 { 
    646   stack<ViewCellKdNode *> nodeStack; 
    647    
    648   nodeStack.push(mRoot); 
    649  
    650   AxisAlignedBox3 box = GetBox(n); 
    651   int mask = rand(); 
    652  
    653   while (!nodeStack.empty()) { 
    654     ViewCellKdNode *node = nodeStack.top(); 
    655     nodeStack.pop(); 
     1261   
     1262  VssRay::NewMail(); 
     1263 
     1264  // create a new node that will hold the rays 
     1265  VspKdTreeLeaf *newLeaf = new VspKdTreeLeaf( sroot->parent, rayCount ); 
     1266  if (  newLeaf->parent ) 
     1267    newLeaf->parent->ReplaceChildLink(sroot, newLeaf); 
     1268   
     1269 
     1270  tstack.push( sroot ); 
     1271 
     1272  while (!tstack.empty()) { 
     1273 
     1274    VspKdTreeNode *node = tstack.top(); 
     1275    tstack.pop(); 
     1276 
    6561277    if (node->IsLeaf()) { 
    657       if ( node != n && (!onlyUnmailed || !node->Mailed()) ) 
    658         return node; 
    659     } else { 
    660       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    661       if (interior->mPosition > box.Max(interior->mAxis)) 
    662         nodeStack.push(interior->mBack); 
    663       else 
    664         if (interior->mPosition < box.Min(interior->mAxis)) 
    665           nodeStack.push(interior->mFront); 
    666         else { 
    667           // random decision 
    668           if (mask&1) 
    669             nodeStack.push(interior->mBack); 
    670           else 
    671             nodeStack.push(interior->mFront); 
    672           mask = mask>>1; 
    673         } 
    674     } 
    675   } 
    676    
    677   return NULL; 
    678 } 
    679  
    680 int 
    681 ViewCellKd::FindNeighbors(ViewCellKdNode *n, 
    682                       vector<ViewCellKdNode *> &neighbors, 
    683                       bool onlyUnmailed 
    684                       ) 
    685 { 
    686   stack<ViewCellKdNode *> nodeStack; 
    687    
    688   nodeStack.push(mRoot); 
    689  
    690   AxisAlignedBox3 box = GetBox(n); 
    691  
    692   while (!nodeStack.empty()) { 
    693     ViewCellKdNode *node = nodeStack.top(); 
    694     nodeStack.pop(); 
    695     if (node->IsLeaf()) { 
    696       if ( node != n && (!onlyUnmailed || !node->Mailed()) )  
    697         neighbors.push_back(node); 
    698     } else { 
    699       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    700       if (interior->mPosition > box.Max(interior->mAxis)) 
    701                                 nodeStack.push(interior->mBack); 
    702       else 
    703                                 if (interior->mPosition < box.Min(interior->mAxis)) 
    704                                         nodeStack.push(interior->mFront); 
    705                                 else { 
    706                                         // random decision 
    707                                         nodeStack.push(interior->mBack); 
    708                                         nodeStack.push(interior->mFront); 
    709                                 } 
    710     } 
    711   } 
    712    
    713   return (int)neighbors.size(); 
    714 } 
    715  
    716 // Find random neighbor which was not mailed 
    717 ViewCellKdNode * 
    718 ViewCellKd::GetRandomLeaf(const Plane3 &plane) 
    719 { 
    720   stack<ViewCellKdNode *> nodeStack; 
    721    
    722   nodeStack.push(mRoot); 
    723    
    724   int mask = rand(); 
    725    
    726   while (!nodeStack.empty()) { 
    727     ViewCellKdNode *node = nodeStack.top(); 
    728     nodeStack.pop(); 
    729     if (node->IsLeaf()) { 
    730       return node; 
    731     } else { 
    732       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    733       ViewCellKdNode *next; 
    734         if (GetBox(interior->mBack).Side(plane) < 0) 
    735           next = interior->mFront; 
    736         else 
    737           if (GetBox(interior->mFront).Side(plane) < 0) 
    738             next = interior->mBack; 
    739           else { 
    740             // random decision 
    741             if (mask&1) 
    742               next = interior->mBack; 
    743             else 
    744               next = interior->mFront; 
    745             mask = mask>>1; 
    746           } 
    747         nodeStack.push(next); 
    748     } 
    749   } 
    750    
    751    
    752   return NULL; 
    753 } 
    754  
    755 void 
    756 ViewCellKd::CollectLeaves(vector<ViewCellKdLeaf *> &leaves) 
    757 { 
    758   stack<ViewCellKdNode *> nodeStack; 
    759   nodeStack.push(mRoot); 
    760  
    761   while (!nodeStack.empty()) { 
    762     ViewCellKdNode *node = nodeStack.top(); 
    763     nodeStack.pop(); 
    764     if (node->IsLeaf()) { 
    765       ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 
    766       leaves.push_back(leaf); 
    767     } else { 
    768       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    769       nodeStack.push(interior->mBack); 
    770       nodeStack.push(interior->mFront); 
    771     } 
    772   } 
    773 } 
    774  
    775  
    776 int 
    777 ViewCellKd::CollectLeafPvs() 
    778 { 
    779   int totalPvsSize = 0; 
    780   stack<ViewCellKdNode *> nodeStack; 
    781    
    782   nodeStack.push(mRoot); 
    783    
    784   while (!nodeStack.empty()) { 
    785     ViewCellKdNode *node = nodeStack.top(); 
    786     nodeStack.pop(); 
    787     if (node->IsLeaf()) { 
    788       ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 
    789       for (int j=0; j < leaf->mObjects.size(); j++) { 
    790         Intersectable *object = leaf->mObjects[j]; 
    791         if (!object->Mailed()) { 
    792           object->Mail(); 
    793           // add this node to pvs of all nodes it can see 
    794          /* ViewCellKdPvsMap::iterator ni = object->mKdPvs.mEntries.begin(); 
    795           for (; ni != object->mKdPvs.mEntries.end(); ni++) { 
    796             ViewCellKdNode *node = (*ni).first; 
    797             // $$ JB TEMPORARY solution -> should add object PVS or explictly computed 
    798             // kd tree PVS 
    799             if (leaf->mKdPvs.AddSample(node)) 
    800               totalPvsSize++; 
    801           }*/ 
    802         } 
     1278      VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) node; 
     1279       
     1280      for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     1281                                        ri != leaf->rays.end(); 
     1282                                        ri++) { 
     1283                                 
     1284                                // unref this ray from the old node 
     1285                                 
     1286                                if ((*ri).mRay->IsActive()) { 
     1287                                        (*ri).mRay->Unref(); 
     1288                                        if (!(*ri).mRay->Mailed()) { 
     1289                                                (*ri).mRay->Mail(); 
     1290                                                newLeaf->AddRay(*ri); 
     1291                                        } 
     1292                                } else 
     1293                                        (*ri).mRay->Unref(); 
     1294                                 
    8031295      } 
    8041296    } else { 
    805       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    806       nodeStack.push(interior->mFront); 
    807       nodeStack.push(interior->mBack); 
     1297      tstack.push(((VspKdTreeInterior *)node)->back); 
     1298      tstack.push(((VspKdTreeInterior *)node)->front); 
    8081299    } 
    8091300  } 
    810  
    811   return totalPvsSize; 
    812 } 
    813  
    814  
    815 ViewCellKdNode * 
    816 ViewCellKd::GetRandomLeaf(const bool onlyUnmailed) 
    817 { 
    818         stack<ViewCellKdNode *> nodeStack; 
    819   nodeStack.push(mRoot); 
    820  
    821         int mask = rand(); 
    822          
    823   while (!nodeStack.empty()) { 
    824     ViewCellKdNode *node = nodeStack.top(); 
    825     nodeStack.pop(); 
     1301   
     1302  // delete the node and all its children 
     1303  delete sroot; 
     1304   
     1305//   for(VspKdTreeNode::SRayContainer::iterator ri = newLeaf->rays.begin(); 
     1306//       ri != newLeaf->rays.end(); 
     1307//       ri++) 
     1308//     (*ri).ray->UnMail(2); 
     1309 
     1310 
     1311#if DEBUG_COLLAPSE 
     1312  cout<<"Total memory before="<<GetMemUsage()<<endl; 
     1313#endif 
     1314 
     1315  stat.nodes -= collapsedNodes - 1; 
     1316  stat.rayRefs -= totalRayCount - rayCount; 
     1317   
     1318#if DEBUG_COLLAPSE 
     1319  cout<<"collapsed nodes"<<collapsedNodes<<endl; 
     1320  cout<<"collapsed rays"<<totalRayCount - rayCount<<endl; 
     1321  cout<<"Total memory after="<<GetMemUsage()<<endl; 
     1322  cout<<"================================"<<endl; 
     1323#endif 
     1324 
     1325        //  tstat.collapsedNodes += collapsedNodes; 
     1326        //  tstat.collapsedRays += totalRayCount - rayCount; 
     1327     
     1328  return totalRayCount - rayCount; 
     1329} 
     1330 
     1331 
     1332int 
     1333VspKdTree::GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const 
     1334{ 
     1335        stack<VspKdTreeNode *> tstack; 
     1336  tstack.push(root); 
     1337 
     1338        Intersectable::NewMail(); 
     1339        int pvsSize = 0; 
     1340         
     1341  while (!tstack.empty()) { 
     1342    VspKdTreeNode *node = tstack.top(); 
     1343    tstack.pop(); 
     1344     
     1345  
    8261346    if (node->IsLeaf()) { 
    827       if ( (!onlyUnmailed || !node->Mailed()) ) 
    828                                 return node; 
    829     } else { 
    830       ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 
    831                         // random decision 
    832                         if (mask&1) 
    833                                 nodeStack.push(interior->mBack); 
    834                         else 
    835                                 nodeStack.push(interior->mFront); 
    836                         mask = mask>>1; 
     1347                        VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 
     1348                        for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 
     1349                                        ri != leaf->rays.end(); 
     1350                                        ri++) 
     1351                                if ((*ri).mRay->IsActive()) { 
     1352                                        Intersectable *object; 
     1353#if BIDIRECTIONAL_RAY 
     1354                                        object = (*ri).mRay->mOriginObject; 
     1355                                        if (object && !object->Mailed()) { 
     1356                                                pvsSize++; 
     1357                                                object->Mail(); 
     1358                                        } 
     1359#endif 
     1360                                        object = (*ri).mRay->mTerminationObject; 
     1361                                        if (object && !object->Mailed()) { 
     1362                                                pvsSize++; 
     1363                                                object->Mail(); 
     1364                                        } 
     1365                                } 
     1366                } else { 
     1367                        VspKdTreeInterior *in = (VspKdTreeInterior *)node; 
     1368                        if (in->axis < 3) { 
     1369                                if (box.Max(in->axis) >= in->position ) 
     1370                                        tstack.push(in->front); 
     1371                                 
     1372                                if (box.Min(in->axis) <= in->position ) 
     1373                                        tstack.push(in->back); 
     1374                        } else { 
     1375                                // both nodes for directional splits 
     1376                                tstack.push(in->front); 
     1377                                tstack.push(in->back); 
     1378                        } 
    8371379                } 
    8381380        } 
    839   return NULL; 
    840 } 
     1381        return pvsSize; 
     1382} 
     1383 
     1384void 
     1385VspKdTree::GetRayContributionStatistics( 
     1386                                                                                                                                                        float &minRayContribution, 
     1387                                                                                                                                                        float &maxRayContribution, 
     1388                                                                                                                                                        float &avgRayContribution 
     1389                                                                                                                                                        ) 
     1390{ 
     1391        stack<VspKdTreeNode *> tstack; 
     1392  tstack.push(root); 
     1393         
     1394        minRayContribution = 1.0f; 
     1395        maxRayContribution = 0.0f; 
     1396        float sumRayContribution = 0.0f; 
     1397        int leaves = 0; 
     1398 
     1399  while (!tstack.empty()) { 
     1400    VspKdTreeNode *node = tstack.top(); 
     1401    tstack.pop(); 
     1402                 
     1403    if (node->IsLeaf()) { 
     1404                        leaves++; 
     1405                        VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 
     1406                        float c = leaf->GetAvgRayContribution(); 
     1407                        if (c > maxRayContribution) 
     1408                                maxRayContribution = c; 
     1409                        if (c < minRayContribution) 
     1410                                minRayContribution = c; 
     1411                        sumRayContribution += c; 
     1412                         
     1413                } else { 
     1414                        VspKdTreeInterior *in = (VspKdTreeInterior *)node; 
     1415                        // both nodes for directional splits 
     1416                        tstack.push(in->front); 
     1417                        tstack.push(in->back); 
     1418                } 
     1419        } 
     1420         
     1421        cout<<"sum="<<sumRayContribution<<endl; 
     1422        cout<<"leaves="<<leaves<<endl; 
     1423        avgRayContribution = sumRayContribution/(float)leaves; 
     1424} 
     1425 
     1426 
     1427int 
     1428VspKdTree::GenerateRays(const float ratioPerLeaf, 
     1429                                                                                        SimpleRayContainer &rays) 
     1430{ 
     1431        stack<VspKdTreeNode *> tstack; 
     1432  tstack.push(root); 
     1433         
     1434  while (!tstack.empty()) { 
     1435    VspKdTreeNode *node = tstack.top(); 
     1436    tstack.pop(); 
     1437                 
     1438    if (node->IsLeaf()) { 
     1439                        VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 
     1440                        float c = leaf->GetAvgRayContribution(); 
     1441                        int num = (c*ratioPerLeaf + 0.5); 
     1442                        //                      cout<<num<<" "; 
     1443 
     1444                        for (int i=0; i < num; i++) { 
     1445                                Vector3 origin = GetBBox(leaf).GetRandomPoint(); 
     1446                                Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint(); 
     1447                                Vector3 direction = Vector3(sin(dirVector.x), sin(dirVector.y), cos(dirVector.x)); 
     1448                                //cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl; 
     1449                                rays.push_back(SimpleRay(origin, direction)); 
     1450                        } 
     1451                         
     1452                } else { 
     1453                        VspKdTreeInterior *in = (VspKdTreeInterior *)node; 
     1454                        // both nodes for directional splits 
     1455                        tstack.push(in->front); 
     1456                        tstack.push(in->back); 
     1457                } 
     1458        } 
     1459 
     1460        return rays.size(); 
     1461} 
     1462 
     1463 
     1464float 
     1465VspKdTree::GetAvgPvsSize() 
     1466{ 
     1467        stack<VspKdTreeNode *> tstack; 
     1468  tstack.push(root); 
     1469 
     1470        int sumPvs = 0; 
     1471        int leaves = 0; 
     1472  while (!tstack.empty()) { 
     1473    VspKdTreeNode *node = tstack.top(); 
     1474    tstack.pop(); 
     1475                 
     1476    if (node->IsLeaf()) { 
     1477                        VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 
     1478                        // update pvs size 
     1479                        leaf->UpdatePvsSize(); 
     1480                        sumPvs += leaf->GetPvsSize(); 
     1481                        leaves++; 
     1482                } else { 
     1483                        VspKdTreeInterior *in = (VspKdTreeInterior *)node; 
     1484                        // both nodes for directional splits 
     1485                        tstack.push(in->front); 
     1486                        tstack.push(in->back); 
     1487                } 
     1488        } 
     1489 
     1490 
     1491        return sumPvs/(float)leaves; 
     1492} 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h

    r406 r408  
    1 #ifndef _ViewCellKdTree_H__ 
    2 #define _ViewCellKdTree_H__ 
    3  
     1// ================================================================ 
     2// $Id$ 
     3// **************************************************************** 
     4//  
     5// Initial coding by 
     6/** 
     7   @author Jiri Bittner 
     8*/ 
     9 
     10#ifndef __VSPKDTREE_H__ 
     11#define __VSPKDTREE_H__ 
     12 
     13// Standard headers 
     14#include <iomanip> 
     15#include <vector> 
    416#include <functional> 
    5 using namespace std; 
    6  
    7 #include "Containers.h" 
     17#include <stack> 
     18 
     19 
     20// User headers 
     21#include "VssRay.h" 
    822#include "AxisAlignedBox3.h" 
     23 
     24 
     25#define USE_KDNODE_VECTORS 1 
     26#define _RSS_STATISTICS 
     27#define _RSS_TRAVERSAL_STATISTICS 
     28 
     29 
     30#include "Statistics.h" 
    931#include "Ray.h" 
    10 #include "Pvs.h" 
    11  
    12    
    13 class ViewCellKdNode; 
    14 class ViewCellKdLeaf; 
    15 class ViewCellKdInterior; 
    16 class Intersectable; 
    17  
    1832 
    1933// -------------------------------------------------------------- 
    2034// Static statistics for kd-tree search 
    2135// -------------------------------------------------------------- 
    22 class ViewCellKdTreeStatistics  
     36class VspKdStatistics:  public StatisticsBase 
    2337{ 
    2438public:   
     
    2943  // totals number of rays 
    3044  int rays; 
    31   // total number of query domains 
     45        // initial size of the pvs 
     46  int initialPvsSize; 
     47        // total number of query domains 
    3248  int queryDomains; 
    3349  // total number of ray references 
    3450  int rayRefs; 
    35   // refs in non empty leafs 
    36   int rayRefsNonZeroQuery; 
    37   // total number of query references 
    38   int objectRefs; 
    39   // nodes with zero queries 
    40   int zeroQueryNodes; 
    41   // max depth nodes 
     51 
     52        // max depth nodes 
    4253  int maxDepthNodes; 
    4354  // max depth nodes 
    44   int minCostNodes; 
     55  int minPvsNodes; 
     56  int minRaysNodes; 
     57        // max ray contribution nodes 
     58  int maxRayContribNodes; 
     59        // max depth nodes 
     60  int minSizeNodes; 
     61         
    4562  // max number of rays per node 
    46   int maxObjectRefs; 
     63  int maxRayRefs; 
    4764  // number of dynamically added ray refs 
    4865  int addedRayRefs; 
     
    5168   
    5269  // Constructor 
    53   ViewCellKdTreeStatistics() { 
     70  VspKdStatistics() { 
    5471    Reset(); 
    5572  } 
     
    6481      splits[i] = 0; 
    6582    rays = queryDomains = 0; 
    66     rayRefs = rayRefsNonZeroQuery = objectRefs = 0; 
    67     zeroQueryNodes = 0; 
     83    rayRefs = 0; 
    6884    maxDepthNodes = 0; 
    69     minCostNodes = 0; 
    70     maxObjectRefs = 0; 
     85    minPvsNodes = 0; 
     86    minRaysNodes = 0; 
     87    maxRayRefs = 0; 
    7188    addedRayRefs = removedRayRefs = 0; 
    72   } 
    73  
     89                initialPvsSize = 0; 
     90                maxRayContribNodes = 0; 
     91                minSizeNodes = 0; 
     92  } 
     93 
     94   
    7495  void 
    7596  Print(ostream &app) const; 
    7697 
    77   friend ostream &operator<<(ostream &s, const ViewCellKdTreeStatistics &stat) { 
     98  friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) { 
    7899    stat.Print(s); 
    79100    return s; 
     
    82103}; 
    83104 
    84    
    85 class ViewCellKdInterior; 
    86 /** Abstract class for kd-tree node */ 
    87 class ViewCellKdNode { 
     105 
     106// -------------------------------------------------------------- 
     107// For sorting rays 
     108// -------------------------------------------------------------- 
     109struct  SortableEntry 
     110{ 
     111  enum EType { 
     112    ERayMin, 
     113    ERayMax 
     114  }; 
     115 
     116  int type; 
     117  float value; 
     118  void *data; 
     119   
     120  SortableEntry() {} 
     121  SortableEntry(const int t, const float v, void *d):type(t), 
     122                                                                                                                                                                                                                 value(v), 
     123                                                                                                                                                                                                                 data(d) {} 
     124         
     125  friend bool operator<(const SortableEntry &a, const SortableEntry &b) { 
     126    return a.value < b.value; 
     127  } 
     128}; 
     129 
     130 
     131class VspKdTreeInterior; 
     132 
     133 
     134// -------------------------------------------------------------- 
     135// KD-tree node - abstract class 
     136// -------------------------------------------------------------- 
     137class VspKdTreeNode 
     138{ 
     139public: 
     140 
     141#define USE_FIXEDPOINT_T 1 
     142 
     143struct RayInfo 
     144{ 
     145        // pointer to the actual ray 
     146        VssRay *mRay; 
     147         
     148        // endpoints  - do we need them? 
     149#if USE_FIXEDPOINT_T 
     150        short mMinT, mMaxT; 
     151#else 
     152        float mMinT, mMaxT; 
     153#endif 
     154         
     155        RayInfo():mRay(NULL) {} 
     156         
     157        RayInfo(VssRay *r):mRay(r), mMinT(0), 
     158#if USE_FIXEDPOINT_T 
     159#define FIXEDPOINT_ONE 0x7FFE 
     160                                                                                                //                        mMaxT(0xFFFF) 
     161                                                                                                                                                        mMaxT(FIXEDPOINT_ONE) 
     162#else 
     163                mMaxT(1.0f) 
     164#endif 
     165        {} 
     166         
     167        RayInfo(VssRay *r, 
     168                                                                                const float _min, 
     169                                                                                const float _max 
     170                                                                                ):mRay(r) { 
     171                SetMinT(_min); 
     172                SetMaxT(_max); 
     173        } 
     174         
     175        RayInfo(VssRay *r, 
     176                                                                                const short _min, 
     177                                                                                const float _max 
     178                                                                                ):mRay(r), mMinT(_min) { 
     179                SetMaxT(_max); 
     180        } 
     181         
     182        RayInfo(VssRay *r, 
     183                                                                                const float _min, 
     184                                                                                const short _max 
     185                                                                                ):mRay(r), mMaxT(_max) { 
     186                SetMinT(_min); 
     187        } 
     188         
     189        friend bool operator<(const RayInfo &a, const RayInfo &b) { 
     190                return a.mRay < b.mRay; 
     191        } 
     192   
     193         
     194        float ExtrapOrigin(const int axis) const { 
     195                return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis); 
     196        } 
     197         
     198        float ExtrapTermination(const int axis) const { 
     199                return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis); 
     200        } 
     201         
     202#if USE_FIXEDPOINT_T 
     203        float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); } 
     204        float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); } 
     205         
     206        void SetMinT (const float t) { 
     207                mMinT = (short) (t*(float)(FIXEDPOINT_ONE)); 
     208        } 
     209         
     210        void SetMaxT (const float t) { 
     211                mMaxT = (short) (t*(float)(FIXEDPOINT_ONE)); 
     212                mMaxT++; 
     213                //      if (mMaxT!=0xFFFF) 
     214                //      mMaxT++; 
     215        } 
     216#else 
     217        float GetMinT () const { return mMinT; } 
     218        float GetMaxT () const { return mMaxT; } 
     219         
     220        void SetMinT (const float t) { mMinT = t; } 
     221        void SetMaxT (const float t) { mMaxT = t; } 
     222#endif  
     223 
     224 
     225  int ComputeRayIntersection(const float axis, 
     226                                                                                                                 const float position, 
     227                                                                                                                 float &t 
     228                                                                                                                 ) const { 
     229                 
     230                // intersect the ray with the plane 
     231    float denom = mRay->GetDir(axis); 
     232     
     233    if (fabs(denom) < 1e-20) 
     234      //if (denom == 0.0f) 
     235      return (mRay->GetOrigin(axis) > position) ? 1 : -1; 
     236     
     237    t = (position - mRay->GetOrigin(axis))/denom; 
     238 
     239    if (t < GetMinT()) 
     240      return (denom > 0) ? 1 : -1; 
     241 
     242    if (t > GetMaxT()) 
     243      return (denom > 0) ? -1 : 1; 
     244 
     245                return 0; 
     246        } 
     247 
     248 
     249}; 
     250 
     251 
     252        typedef vector<RayInfo> RayInfoContainer; 
     253         
     254  enum { EInterior, ELeaf }; 
     255 
     256  ///////////////////////////////// 
     257  // The actual data goes here 
     258   
     259  // link to the parent 
     260  VspKdTreeInterior *parent; 
     261 
     262  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ}; 
     263   
     264  // splitting axis 
     265  char axis; 
     266         
     267  // depth 
     268  unsigned char depth; 
     269   
     270  //  short depth; 
     271  // 
     272  ///////////////////////////////// 
     273   
     274  inline VspKdTreeNode(VspKdTreeInterior *p); 
     275 
     276   
     277  virtual ~VspKdTreeNode() {}; 
     278  virtual int Type() const  = 0; 
     279   
     280 
     281  bool IsLeaf() const { return axis == -1; } 
     282   
     283  virtual void Print(ostream &s) const = 0; 
     284 
     285  virtual int GetAccessTime() { 
     286    return 0x7FFFFFF; 
     287  } 
     288 
     289   
     290         
     291}; 
     292 
     293// -------------------------------------------------------------- 
     294// KD-tree node - interior node 
     295// -------------------------------------------------------------- 
     296class VspKdTreeInterior : 
     297  public VspKdTreeNode 
     298{ 
     299public: 
     300  // plane in local modelling coordinates 
     301  float position; 
     302 
     303  // pointers to children 
     304  VspKdTreeNode *back, *front; 
     305 
     306  // the bbox of the node 
     307  AxisAlignedBox3 bbox; 
     308 
     309  // the bbox of the node 
     310  AxisAlignedBox3 dirBBox; 
     311   
     312  // data for caching 
     313  long accesses; 
     314  long lastAccessTime; 
     315   
     316  VspKdTreeInterior(VspKdTreeInterior *p):VspKdTreeNode(p), 
     317                                        back(NULL), 
     318                                        front(NULL), 
     319                                        accesses(0), 
     320                                        lastAccessTime(-1) 
     321  { } 
     322 
     323  virtual int GetAccessTime() { 
     324    return lastAccessTime; 
     325  } 
     326 
     327  void SetupChildLinks(VspKdTreeNode *b, VspKdTreeNode *f) { 
     328    back = b; 
     329    front = f; 
     330    b->parent = f->parent = this; 
     331  } 
     332 
     333  void ReplaceChildLink(VspKdTreeNode *oldChild, VspKdTreeNode *newChild) { 
     334    if (back == oldChild) 
     335      back = newChild; 
     336    else 
     337      front = newChild; 
     338  } 
     339 
     340  virtual int Type() const  { return EInterior; } 
     341   
     342  virtual ~VspKdTreeInterior() { 
     343    if (back) 
     344      delete back; 
     345    if (front) 
     346      delete front; 
     347  } 
     348   
     349  virtual void Print(ostream &s) const { 
     350    if (axis == 0) 
     351      s<<"x "; 
     352    else 
     353      if (axis == 1) 
     354        s<<"y "; 
     355      else 
     356        s<<"z "; 
     357    s<<position<<" "; 
     358    back->Print(s); 
     359    front->Print(s); 
     360  } 
     361 
     362   
     363         
     364  int ComputeRayIntersection(const RayInfo &rayData, 
     365                                                                                                                 float &t 
     366                                                                                                                 ) { 
     367                return rayData.ComputeRayIntersection(axis, position, t); 
     368  } 
     369 
     370}; 
     371 
     372 
     373// -------------------------------------------------------------- 
     374// KD-tree node - leaf node 
     375// -------------------------------------------------------------- 
     376class VspKdTreeLeaf : 
     377  public VspKdTreeNode 
     378{ 
     379private: 
     380        int mPvsSize; 
    88381public: 
    89382  static int mailID; 
    90383  int mailbox; 
    91384   
     385  RayInfoContainer rays; 
     386        bool mValidPvs; 
     387         
     388  VspKdTreeLeaf(VspKdTreeInterior *p, 
     389                                                        const int nRays 
     390                                                        ):VspKdTreeNode(p), rays(), mPvsSize(0), mValidPvs(false) { 
     391    rays.reserve(nRays); 
     392  } 
     393   
     394  virtual ~VspKdTreeLeaf() { } 
     395 
     396  virtual int Type() const  { return ELeaf; } 
     397 
     398  virtual void Print(ostream &s) const { 
     399    s<<endl<<"L: r="<<rays.size()<<endl; 
     400  }; 
     401   
     402  void AddRay(const RayInfo &data) { 
     403                mValidPvs = false; 
     404    rays.push_back(data); 
     405    data.mRay->Ref(); 
     406  } 
     407         
     408        int GetPvsSize() const { 
     409                return mPvsSize; 
     410        } 
     411        void SetPvsSize(const int s) { 
     412                mPvsSize = s; 
     413        } 
     414 
     415        void 
     416        UpdatePvsSize(); 
     417 
    92418  void Mail() { mailbox = mailID; } 
    93419  static void NewMail() { mailID++; } 
    94420  bool Mailed() const { return mailbox == mailID; } 
    95  
    96  
    97   ViewCellKdNode(ViewCellKdInterior *parent); 
    98  
    99   /** Determines whether this node is a leaf or interior node 
    100       @return true if leaf 
    101   */ 
    102   virtual bool IsLeaf() const = 0; 
    103  
    104   /** Determines whether this node is the root of the tree 
    105       @return true if root 
    106   */ 
    107   virtual bool IsRoot() const { 
    108     return mParent == NULL; 
    109   } 
    110  
    111   /** Parent of the node - the parent is a little overhead for maintanance of the tree, 
    112       but allows various optimizations of tree traversal algorithms */ 
    113   ViewCellKdInterior *mParent; 
    114   int mDepth; 
     421   
     422  bool Mailed(const int mail) { 
     423    return mailbox >= mailID + mail; 
     424  } 
     425 
     426        float GetAvgRayContribution() const { 
     427                return GetPvsSize()/((float)rays.size() + Limits::Small); 
     428        } 
     429 
     430        float GetSqrRayContribution() const { 
     431                return sqr(GetPvsSize()/((float)rays.size() + Limits::Small)); 
     432        } 
     433 
    115434}; 
    116435 
    117 /** Implementation of the kd-tree interior node */ 
    118 class ViewCellKdInterior : public ViewCellKdNode { 
    119  
    120 public: 
    121      
    122   ViewCellKdInterior(ViewCellKdInterior *parent):ViewCellKdNode(parent), mBack(NULL), mFront(NULL) {} 
    123  
    124   /** \sa ViewCellKdNode::IsLeaf() */ 
    125   virtual bool IsLeaf() const { return false; } 
    126  
    127   /** splitting axis */ 
    128   int mAxis; 
    129   /** splitting position, absolute position within the bounding box of this node */ 
    130   float mPosition; 
    131   /** bounding box of interior node */ 
    132   AxisAlignedBox3 mBox; 
    133  
    134   /** back node */ 
    135   ViewCellKdNode *mBack; 
    136   /** front node */ 
    137   ViewCellKdNode *mFront; 
    138  
    139   void SetupChildLinks(ViewCellKdNode *b, ViewCellKdNode *f) { 
    140     mBack = b; 
    141     mFront = f; 
    142     b->mParent = f->mParent = this; 
    143   } 
    144    
    145   void ReplaceChildLink(ViewCellKdNode *oldChild, ViewCellKdNode *newChild) { 
    146     if (mBack == oldChild) 
    147       mBack = newChild; 
    148     else 
    149       mFront = newChild; 
    150   } 
    151    
    152    
    153 }; 
    154    
    155    
    156 /** Implementation of the kd-tree leaf node */ 
    157 class ViewCellKdLeaf : public ViewCellKdNode { 
    158 public: 
    159   ViewCellKdLeaf(ViewCellKdInterior *parent, const int objects):ViewCellKdNode(parent) { 
    160     mObjects.reserve(objects); 
    161   } 
    162    
    163   void AddPassingRay(const Ray &ray, 
    164                                                                                  const int contributions) { 
    165     mPassingRays.AddRay(ray, contributions); 
    166                 //              Debug << "adding passing ray" << endl; 
    167   } 
    168  
    169          
    170         void AddPassingRay2(const Ray &ray, 
    171                                                                                         const int objects, 
    172                                                                                         const int viewcells 
    173                                                                                         ) { 
    174     mPassingRays.AddRay2(ray, objects, viewcells); 
    175                 //              Debug << "adding passing ray" << endl; 
    176   } 
    177  
    178   /** \sa ViewCellKdNode::IsLeaf() */ 
    179   virtual bool IsLeaf() const { return true; } 
    180    
    181  
    182    
    183  
    184   /** pointers to occluders contained in this node */ 
    185   ObjectContainer mObjects; 
    186    
    187   /** pointers to viewcells contained in this node */ 
    188   //  ViewCellContainer mViewCells; 
    189  
    190   /** Ray set description of the rays passing through this node */ 
    191   PassingRaySet mPassingRays; 
    192          
    193   /** PVS consisting of visible ViewCellKd nodes */ 
    194   ViewCellKdPvs mKdPvs; 
    195          
    196         /** PVS consisting of visible objects */ 
    197   ViewCellPvs mPvs; 
    198 }; 
    199  
    200    
    201  
    202 /** ViewCellKd for indexing scene entities - occluders/occludees/viewcells */ 
    203 class ViewCellKd { 
    204  
    205 protected: 
     436// Inline functions 
     437inline 
     438VspKdTreeNode::VspKdTreeNode(VspKdTreeInterior *p): 
     439  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {} 
     440 
     441 
     442 
     443// --------------------------------------------------------------- 
     444// Main LSDS search class 
     445// --------------------------------------------------------------- 
     446class VspKdTree 
     447{ 
    206448  struct TraversalData 
    207449  {   
    208     ViewCellKdNode *mNode; 
    209     AxisAlignedBox3 mBox; 
    210     int mDepth; 
    211     float mPriority; 
     450    VspKdTreeNode *node; 
     451    AxisAlignedBox3 bbox; 
     452    int depth; 
     453    float priority; 
    212454     
    213455    TraversalData() {} 
    214456 
    215     TraversalData(ViewCellKdNode *n, const float p): 
    216       mNode(n), mPriority(p) 
     457    TraversalData(VspKdTreeNode *n, const float p): 
     458      node(n), priority(p) 
    217459    {} 
    218      
    219     TraversalData(ViewCellKdNode *n, 
     460 
     461    TraversalData(VspKdTreeNode *n, 
    220462                   const AxisAlignedBox3 &b, 
    221463                   const int d): 
    222       mNode(n), mBox(b), mDepth(d) {} 
     464      node(n), bbox(b), depth(d) {} 
    223465     
    224  
    225     bool operator<( 
    226                    const TraversalData &b) const { 
    227       ViewCellKdLeaf *leafa = (ViewCellKdLeaf *) mNode; 
    228       ViewCellKdLeaf *leafb = (ViewCellKdLeaf *) b.mNode; 
    229       return  
    230         leafa->mObjects.size()*mBox.SurfaceArea() 
    231         < 
    232         leafb->mObjects.size()*b.mBox.SurfaceArea(); 
    233     } 
    234  
    235  
     466                 
    236467    // comparator for the  
    237468    struct less_priority : public 
    238469    binary_function<const TraversalData, const TraversalData, bool> { 
    239        
     470                         
    240471      bool operator()(const TraversalData a, const TraversalData b) { 
    241                                 return a.mPriority < b.mPriority; 
     472                                return a.priority < b.priority; 
    242473      } 
    243474       
    244475    }; 
    245476 
     477    //    ~TraversalData() {} 
     478    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {} 
     479     
     480    friend bool operator<(const TraversalData &a, 
     481                                                                                                        const TraversalData &b) { 
     482      //      return a.node->queries.size() < b.node->queries.size(); 
     483      VspKdTreeLeaf *leafa = (VspKdTreeLeaf *) a.node; 
     484      VspKdTreeLeaf *leafb = (VspKdTreeLeaf *) b.node; 
     485#if 0 
     486                        return 
     487                                leafa->rays.size()*a.bbox.GetVolume() 
     488                                < 
     489                                leafb->rays.size()*b.bbox.GetVolume(); 
     490#endif 
     491#if 1 
     492                        return 
     493                                leafa->GetPvsSize()*a.bbox.GetVolume() 
     494                                < 
     495                                leafb->GetPvsSize()*b.bbox.GetVolume(); 
     496#endif 
     497#if 0 
     498                        return 
     499                                leafa->GetPvsSize() 
     500                                < 
     501                                leafb->GetPvsSize(); 
     502#endif 
     503#if 0 
     504                        return 
     505                                leafa->GetPvsSize()/(leafa->rays.size()+1) 
     506                                > 
     507                                leafb->GetPvsSize()/(leafb->rays.size()+1); 
     508#endif 
     509#if 0 
     510                        return 
     511                                leafa->GetPvsSize()*leafa->rays.size() 
     512                                < 
     513                                leafb->GetPvsSize()*leafb->rays.size(); 
     514#endif 
     515    } 
    246516  }; 
    247  
    248    
    249  
    250 public: 
    251  
    252   enum {SPLIT_OBJECT_MEDIAN, 
    253         SPLIT_SPATIAL_MEDIAN, 
    254         SPLIT_SAH}; 
    255    
    256   ViewCellKd(); 
    257    
     517   
     518  // simplified data for ray traversal only... 
     519 
     520  struct RayTraversalData { 
    258521     
    259   /** Insert view cell into the tree */ 
    260   virtual void InsertViewCell(ViewCell *viewCell) { 
    261     //      mRoot->mViewcells.push_back(viewCell); 
    262   } 
    263  
    264   virtual bool Construct(); 
    265  
    266   /** Check whether subdivision criteria are met for the given subtree. 
    267       If not subdivide the leafs of the subtree. The criteria are specified in 
    268       the environment as well as the subdivision method. By default surface area 
    269       heuristics is used. 
    270          
    271       @param subtree root of the subtree 
    272  
    273       @return true if subdivision was performed, false if subdivision criteria 
    274       were already met 
    275   */ 
    276   virtual ViewCellKdNode *Subdivide(const TraversalData &tdata); 
    277  
    278   /** Get the root of the tree */ 
    279   ViewCellKdNode *GetRoot() const { 
    280     return mRoot; 
    281   } 
    282  
    283  
    284   AxisAlignedBox3 GetBox() const { return mBox; } 
    285  
    286   int 
    287   CastRay( 
    288           Ray &ray 
    289           ); 
    290  
    291   const ViewCellKdTreeStatistics &GetStatistics() const { 
    292     return mStat; 
    293   } 
    294  
    295   void 
    296   CollectObjects(ViewCellKdNode *n, ObjectContainer &objects); 
    297          
    298   void 
    299   CollectLeaves(vector<ViewCellKdLeaf *> &leaves); 
    300          
    301   AxisAlignedBox3 GetBox(const ViewCellKdNode *node) const { 
    302     ViewCellKdInterior *parent = node->mParent; 
    303     if (parent == NULL) 
    304       return mBox; 
    305      
    306     if (!node->IsLeaf()) 
    307       return ((ViewCellKdInterior *)node)->mBox; 
    308      
    309     AxisAlignedBox3 box(parent->mBox); 
    310     if (parent->mFront == node) 
    311       box.SetMin(parent->mAxis, parent->mPosition); 
    312     else 
    313       box.SetMax(parent->mAxis, parent->mPosition); 
    314     return box; 
    315   } 
    316          
    317   ViewCellKdNode * 
    318   FindRandomNeighbor(ViewCellKdNode *n, 
    319                                                                                  bool onlyUnmailed 
    320                                                                                  ); 
    321    
    322   ViewCellKdNode * 
    323   ViewCellKd::GetRandomLeaf(const Plane3 &halfspace); 
    324  
    325         ViewCellKdNode * 
    326         GetRandomLeaf(const bool onlyUnmailed = false); 
    327  
    328   int 
    329   FindNeighbors(ViewCellKdNode *n, 
    330                 vector<ViewCellKdNode *> &neighbors, 
    331                 bool onlyUnmailed 
    332                 ); 
    333  
    334   int 
    335   CollectLeafPvs(); 
    336  
    337 protected: 
    338  
    339   struct RayData { 
    340     // pointer to the actual ray 
    341     Ray *ray; 
    342      
    343     // endpoints  - do we need them? 
    344 #if USE_FIXEDPOINT_T 
    345     short tmin, tmax; 
    346 #else 
    347     float tmin, tmax; 
    348 #endif 
    349  
    350     RayData():ray(NULL) {} 
    351     RayData(Ray *r):ray(r), tmin(0), 
    352  
    353 #if USE_FIXEDPOINT_T 
    354 #define FIXEDPOINT_ONE 0x7FFE 
    355                           //                      tmax(0xFFFF) 
    356                           tmax(FIXEDPOINT_ONE) 
    357 #else 
    358       tmax(1.0f) 
    359 #endif 
    360     {} 
    361  
    362     RayData(Ray *r, 
    363             const float _min, 
    364             const float _max 
    365             ):ray(r) { 
    366       SetTMin(_min); 
    367       SetTMax(_max); 
    368     } 
    369  
    370     RayData(Ray *r, 
    371             const short _min, 
    372             const float _max 
    373             ):ray(r), tmin(_min) { 
    374       SetTMax(_max); 
    375     } 
    376  
    377     RayData(Ray *r, 
    378             const float _min, 
    379             const short _max 
    380             ):ray(r), tmax(_max) { 
    381       SetTMin(_min); 
    382     } 
    383  
    384     friend bool operator<(const RayData &a, const RayData &b) { 
    385       return a.ray < b.ray; 
    386     } 
    387      
    388      
    389     float ExtrapOrigin(const int axis) const { 
    390       return ray->GetLoc(axis) + GetTMin()*ray->GetDir(axis); 
    391     } 
    392      
    393     float ExtrapTermination(const int axis) const { 
    394       return ray->GetLoc(axis) + GetTMax()*ray->GetDir(axis); 
    395     } 
    396      
    397 #if USE_FIXEDPOINT_T 
    398     float GetTMin () const { return tmin/(float)(FIXEDPOINT_ONE); } 
    399     float GetTMax () const { return tmax/(float)(FIXEDPOINT_ONE); } 
    400  
    401     void SetTMin (const float t) { 
    402       tmin = (short) (t*(float)(FIXEDPOINT_ONE)); 
    403     } 
    404      
    405     void SetTMax (const float t) { 
    406       tmax = (short) (t*(float)(FIXEDPOINT_ONE)); 
    407       tmax++; 
    408       //      if (tmax!=0xFFFF) 
    409       //        tmax++; 
    410     } 
    411 #else 
    412     float GetTMin () const { return tmin; } 
    413     float GetTMax () const { return tmax; } 
    414  
    415     void SetTMin (const float t) { tmin = t; } 
    416     void SetTMax (const float t) { tmax = t; } 
    417 #endif  
    418   }; 
    419  
    420   struct RayTraversalData { 
    421     ViewCellKdNode *mNode; 
    422     Vector3 mExitPoint; 
    423     float mMaxT; 
     522    VspKdTreeNode::RayInfo rayData; 
     523    VspKdTreeNode *node; 
    424524     
    425525    RayTraversalData() {} 
    426     RayTraversalData(ViewCellKdNode *n, 
    427                      const Vector3 &p, 
    428                      const float maxt): 
    429       mNode(n), mExitPoint(p), mMaxT(maxt) {} 
     526    RayTraversalData(VspKdTreeNode *n, 
     527                                                                                 const VspKdTreeNode::RayInfo &data): 
     528      rayData(data), node(n) {} 
    430529  }; 
    431  
    432   // -------------------------------------------------------------- 
    433   // For sorting objects 
    434   // -------------------------------------------------------------- 
    435   struct  SortableEntry 
    436   { 
    437     enum { 
    438       BOX_MIN, 
    439       BOX_MAX 
    440     }; 
    441      
    442     int type; 
    443     float value; 
    444     Intersectable *intersectable; 
    445      
    446     SortableEntry() {} 
    447     SortableEntry(const int t, const float v, Intersectable *i):type(t), 
    448                                                                 value(v), 
    449                                                                 intersectable(i) {} 
    450      
    451     bool operator<(const SortableEntry &b) const { 
    452       return value < b.value; 
    453     } 
    454      
    455   }; 
     530         
     531public: 
     532  ///////////////////////////// 
     533  // The core pointer 
     534  VspKdTreeNode *root; 
     535   
     536  ///////////////////////////// 
     537  // Basic properties 
     538 
     539  // total number of nodes of the tree 
     540  int nodes; 
     541  // axis aligned bounding box of the scene 
     542  AxisAlignedBox3 bbox; 
     543 
     544  // axis aligned bounding box of directions 
     545  AxisAlignedBox3 dirBBox; 
     546   
     547  ///////////////////////////// 
     548  // Construction parameters 
     549 
     550  // epsilon used for the construction 
     551  float epsilon; 
     552 
     553  // ratio between traversal and intersection costs 
     554  float ct_div_ci; 
     555  // max depth of the tree 
     556  int termMaxDepth; 
     557  // minimal ratio of the volume of the cell and the query volume 
     558  float termMinSize; 
     559 
     560        // minimal pvs per node to still get subdivided 
     561  int termMinPvs; 
     562 
     563        // minimal ray number per node to still get subdivided 
     564  int termMinRays; 
     565         
     566  // maximal cost ration to subdivide a node 
     567  float termMaxCostRatio; 
     568         
     569        // maximal contribution per ray to subdivide the node 
     570        float termMaxRayContribution; 
     571 
     572         
     573  // randomized construction 
     574  bool randomize; 
     575 
     576  // type of the splitting to use fo rthe tree construction 
     577  enum {ESplitRegular, ESplitHeuristic }; 
     578  int splitType; 
     579         
     580  // maximal size of the box on which the refdir splitting can be performed 
     581  // (relative to the scene bbox 
     582  float refDirBoxMaxSize; 
     583   
     584  // maximum alovable memory in MB 
     585  float maxTotalMemory; 
     586 
     587  // maximum alovable memory for static kd tree in MB 
     588  float maxStaticMemory; 
     589 
     590  // this is used during the construction depending 
     591  // on the type of the tree and queries... 
     592  float maxMemory; 
     593 
     594 
     595  // minimal acess time for collapse 
     596  int accessTimeThreshold; 
     597 
     598        // minimal depth at which to perform collapse 
     599  int minCollapseDepth; 
     600 
    456601   
    457602  // reusable array of split candidates 
    458603  vector<SortableEntry> *splitCandidates; 
    459  
    460   float 
    461   BestCostRatio( 
    462                 ViewCellKdLeaf *node, 
    463                 const AxisAlignedBox3 &box, 
    464                 const int axis, 
    465                 float &position, 
    466                 int &objectsBack, 
    467                 int &objectsFront 
    468                 ); 
     604  ///////////////////////////// 
     605 
     606  VspKdStatistics stat; 
     607         
     608   
     609  VspKdTree(); 
     610  virtual ~VspKdTree(); 
     611 
     612  virtual void 
     613  Construct( 
     614                                                VssRayContainer &rays, 
     615                                                AxisAlignedBox3 *forcedBoundingBox = NULL 
     616                                                ); 
     617         
     618  // incemental construction 
     619  virtual void UpdateRays(VssRayContainer &remove, 
     620                                                                                                        VssRayContainer &add 
     621                                                                                                        ); 
     622 
     623        virtual void AddRays( 
     624                                                                                         VssRayContainer &add 
     625                                                                                         ) 
     626        { 
     627                VssRayContainer remove; 
     628                UpdateRays(remove, add); 
     629        } 
     630 
     631   
     632         
     633  VspKdTreeNode * 
     634  Locate(const Vector3 &v); 
     635         
     636  VspKdTreeNode * 
     637  SubdivideNode(VspKdTreeLeaf *leaf, 
     638                                                                const AxisAlignedBox3 &box, 
     639                                                                AxisAlignedBox3 &backBox, 
     640                                                                AxisAlignedBox3 &frontBox 
     641                                                                ); 
     642         
     643  VspKdTreeNode * 
     644  Subdivide(const TraversalData &tdata); 
     645         
     646  int 
     647  SelectPlane(VspKdTreeLeaf *leaf, 
     648                                                        const AxisAlignedBox3 &box, 
     649                                                        float &position, 
     650                                                        int &raysBack, 
     651                                                        int &raysFront, 
     652                                                        int &pvsBack, 
     653                                                        int &pvsFront 
     654                                                        ); 
    469655 
    470656  void 
    471657  SortSplitCandidates( 
    472                       ViewCellKdLeaf *node, 
    473                       const int axis 
    474                       ); 
     658                                                                                        VspKdTreeLeaf *node, 
     659                                                                                        const int axis 
     660                                                                                        ); 
     661         
     662   
     663  // return memory usage in MB 
     664  float GetMemUsage() const { 
     665    return  
     666      (sizeof(VspKdTree) + 
     667       stat.Leaves()*sizeof(VspKdTreeLeaf) + 
     668       stat.Interior()*sizeof(VspKdTreeInterior) + 
     669       stat.rayRefs*sizeof(VspKdTreeNode::RayInfo))/(1024.0f*1024.0f); 
     670  } 
     671         
     672  float GetRayMemUsage() const { 
     673    return  
     674      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f); 
     675  } 
     676   
     677        float 
     678        BestCostRatioHeuristic( 
     679                                                                                                 VspKdTreeLeaf *node, 
     680                                                                                                 int &axis, 
     681                                                                                                 float &position, 
     682                                                                                                 int &raysBack, 
     683                                                                                                 int &raysFront, 
     684                                                                                                 int &pvsBack, 
     685                                                                                                 int &pvsFront 
     686                                                                                                 ); 
     687 
     688        float 
     689        BestCostRatioRegular( 
     690                                                                                         VspKdTreeLeaf *node, 
     691                                                                                         int &axis, 
     692                                                                                         float &position, 
     693                                                                                         int &raysBack, 
     694                                                                                         int &raysFront, 
     695                                                                                         int &pvsBack, 
     696                                                                                         int &pvsFront 
     697 
     698                                                                                         ); 
     699         
     700        float 
     701        EvalCostRatio( 
     702                                                                VspKdTreeLeaf *node, 
     703                                                                const int axis, 
     704                                                                const float position, 
     705                                                                int &raysBack, 
     706                                                                int &raysFront, 
     707                                                                int &pvsBack, 
     708                                                                int &pvsFront 
     709                                                                ); 
     710 
     711  AxisAlignedBox3 GetBBox(const VspKdTreeNode *node) { 
     712    if (node->parent == NULL) 
     713      return bbox; 
     714 
     715    if (!node->IsLeaf()) 
     716      return ((VspKdTreeInterior *)node)->bbox; 
     717 
     718    if (node->parent->axis >= 3) 
     719      return node->parent->bbox; 
     720       
     721    AxisAlignedBox3 box(node->parent->bbox); 
     722    if (node->parent->front == node) 
     723      box.SetMin(node->parent->axis, node->parent->position); 
     724    else 
     725      box.SetMax(node->parent->axis, node->parent->position); 
     726    return box; 
     727  } 
     728 
     729  AxisAlignedBox3 GetDirBBox(const VspKdTreeNode *node) { 
     730 
     731    if (node->parent == NULL) 
     732      return dirBBox; 
     733     
     734    if (!node->IsLeaf() ) 
     735      return ((VspKdTreeInterior *)node)->dirBBox; 
     736 
     737    if (node->parent->axis < 3) 
     738      return node->parent->dirBBox; 
     739     
     740    AxisAlignedBox3 dBBox(node->parent->dirBBox); 
     741 
     742    if (node->parent->front == node) 
     743      dBBox.SetMin(node->parent->axis - 3, node->parent->position); 
     744    else 
     745      dBBox.SetMax(node->parent->axis - 3, node->parent->position); 
     746    return dBBox; 
     747  } 
     748   
     749  int 
     750  ReleaseMemory(const int time); 
     751 
     752  int 
     753  CollapseSubtree(VspKdTreeNode *node, const int time); 
    475754 
    476755  void 
     756  CountAccess(VspKdTreeInterior *node, const long time) { 
     757    node->accesses++; 
     758    node->lastAccessTime = time; 
     759  } 
     760 
     761  VspKdTreeNode * 
     762  SubdivideLeaf( 
     763                                                                VspKdTreeLeaf *leaf, 
     764                                                                const float SAThreshold 
     765                                                                ); 
     766 
     767  void 
     768  RemoveRay(VssRay *ray, 
     769                                                vector<VspKdTreeLeaf *> *affectedLeaves, 
     770                                                const bool removeAllScheduledRays 
     771                                                ); 
     772 
     773  void 
     774  AddRay(VssRay *ray); 
     775         
     776  void 
     777  TraverseInternalNode( 
     778                                                                                         RayTraversalData &data, 
     779                                                                                         stack<RayTraversalData> &tstack); 
     780 
     781        void 
    477782  EvaluateLeafStats(const TraversalData &data); 
    478783 
    479   ViewCellKdNode * 
    480   SubdivideNode( 
    481                 ViewCellKdLeaf *leaf, 
    482                 const AxisAlignedBox3 &box, 
    483                 AxisAlignedBox3 &backBBox, 
    484                 AxisAlignedBox3 &frontBBox 
    485                 ); 
    486  
    487   bool 
    488   TerminationCriteriaMet(const ViewCellKdLeaf *leaf); 
    489    
    490   int 
    491   SelectPlane(ViewCellKdLeaf *leaf, 
    492               const AxisAlignedBox3 &box, 
    493               float &position 
    494               ); 
    495  
    496  
    497  
    498   float mSplitBorder; 
    499   int mTermMaxDepth; 
    500   int mTermMinCost; 
    501   float mMaxCostRatio; 
    502   float mCt_div_ci; 
    503   int mSplitMethod; 
    504   bool mSahUseFaces; 
    505   /// root of the tree 
    506   ViewCellKdNode *mRoot; 
    507   /// bounding box of the tree root 
    508   AxisAlignedBox3 mBox; 
    509   ViewCellKdTreeStatistics mStat; 
    510    
     784 
     785        int 
     786        GetRootPvsSize() const { 
     787                return GetPvsSize(root, bbox); 
     788        } 
     789         
     790        int 
     791        GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const; 
     792 
     793        void 
     794        GetRayContributionStatistics( 
     795                                                                                                                         float &minRayContribution, 
     796                                                                                                                         float &maxRayContribution, 
     797                                                                                                                         float &avgRayContribution 
     798                                                                                                                         ); 
     799 
     800        int 
     801        GenerateRays(const float ratioPerLeaf, 
     802                                                         SimpleRayContainer &rays); 
     803 
     804        float 
     805        GetAvgPvsSize(); 
     806 
    511807}; 
    512808 
    513 #endif 
     809 
     810#endif // __LSDS_KDTREE_H__ 
     811 
Note: See TracChangeset for help on using the changeset viewer.