Ignore:
Timestamp:
06/09/06 01:26:46 (18 years ago)
Author:
mattausch
Message:

started viewspace-objectspace subdivision
removed memory leaks

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp

    r1002 r1006  
    44 
    55#include "Plane3.h" 
    6 #include "VspBspTree.h" 
     6#include "VspOspTree.h" 
    77#include "Mesh.h" 
    88#include "common.h" 
     
    2525//-- static members 
    2626 
    27  
    28 int VspBspTree::sFrontId = 0; 
    29 int VspBspTree::sBackId = 0; 
    30 int VspBspTree::sFrontAndBackId = 0; 
    31  
    32 typedef pair<BspNode *, BspNodeGeometry *> bspNodePair; 
     27int VspOspTree::sFrontId = 0; 
     28int VspOspTree::sBackId = 0; 
     29int VspOspTree::sFrontAndBackId = 0; 
     30 
    3331 
    3432 
     
    5149 
    5250/******************************************************************************/ 
    53 /*                       class VspBspTree implementation                      */ 
     51/*                       class VspOspTree implementation                      */ 
    5452/******************************************************************************/ 
    5553 
    5654 
    57 VspBspTree::VspBspTree(Environment *env): 
     55VspOspTree::VspOspTree(): 
    5856mRoot(NULL), 
    59 mUseAreaForPvs(false), 
    60 mCostNormalizer(Limits::Small), 
    61 mViewCellsManager(NULL), 
    6257mOutOfBoundsCell(NULL), 
    6358mStoreRays(false), 
    64 mRenderCostWeight(0.5), 
    6559mUseRandomAxis(false), 
    6660mTimeStamp(1) 
    6761{ 
    6862        bool randomize = false; 
    69         env->GetBoolValue("VspBspTree.Construction.randomize", randomize); 
     63        Environment::GetSingleton()->GetBoolValue("VspOspTree.Construction.randomize", randomize); 
    7064        if (randomize) 
    7165                Randomize(); // initialise random generator for heuristics 
    7266 
    7367        //-- termination criteria for autopartition 
    74         env->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth); 
    75         env->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs); 
    76         env->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays); 
    77         env->GetFloatValue("VspBspTree.Termination.minProbability", mTermMinProbability); 
    78         env->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution); 
    79         env->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength); 
    80         env->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio); 
    81         env->GetIntValue("VspBspTree.Termination.missTolerance", mTermMissTolerance); 
    82         env->GetIntValue("VspBspTree.Termination.maxViewCells", mMaxViewCells); 
     68        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.maxDepth", mTermMaxDepth); 
     69        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.minPvs", mTermMinPvs); 
     70        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.minRays", mTermMinRays); 
     71        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.minProbability", mTermMinProbability); 
     72        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxRayContribution", mTermMaxRayContribution); 
     73        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxCostRatio", mTermMaxCostRatio); 
     74        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.missTolerance", mTermMissTolerance); 
     75        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.maxViewCells", mMaxViewCells); 
    8376 
    8477        //-- max cost ratio for early tree termination 
    85         env->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio); 
    86  
    87         env->GetFloatValue("VspBspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio); 
    88         env->GetIntValue("VspBspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance); 
     78        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxCostRatio", mTermMaxCostRatio); 
     79 
     80        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio); 
     81        Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance); 
    8982 
    9083        // HACK//mTermMinPolygons = 25; 
    9184 
    9285        //-- factors for bsp tree split plane heuristics 
    93         env->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor); 
    94         env->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi); 
    95  
     86        Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.ct_div_ci", mCtDivCi); 
    9687 
    9788        //-- partition criteria 
    98         env->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates); 
    99         env->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates); 
    100         env->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy); 
    101  
    102         env->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon); 
    103         env->GetIntValue("VspBspTree.maxTests", mMaxTests); 
     89        Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.epsilon", mEpsilon); 
    10490 
    10591        // if only the driving axis is used for axis aligned split 
    106         env->GetBoolValue("VspBspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 
    107          
    108         //-- termination criteria for axis aligned split 
    109         env->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution",  
    110                                                                 mTermMaxRayContriForAxisAligned); 
    111         env->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 
    112                                                          mTermMinRaysForAxisAligned); 
    113  
    114         //env->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory); 
    115         env->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory); 
    116  
    117         env->GetFloatValue("VspBspTree.Construction.renderCostWeight", mRenderCostWeight); 
    118         env->GetBoolValue("VspBspTree.usePolygonSplitIfAvailable", mUsePolygonSplitIfAvailable); 
    119  
    120         env->GetBoolValue("VspBspTree.useCostHeuristics", mUseCostHeuristics); 
    121         env->GetBoolValue("VspBspTree.useSplitCostQueue", mUseSplitCostQueue); 
    122         env->GetBoolValue("VspBspTree.simulateOctree", mCirculatingAxis); 
    123         env->GetBoolValue("VspBspTree.useRandomAxis", mUseRandomAxis); 
    124         env->GetIntValue("VspBspTree.nodePriorityQueueType", mNodePriorityQueueType); 
    125  
    126         env->GetBoolValue("ViewCells.PostProcess.emptyViewCellsMerge", mEmptyViewCellsMergeAllowed); 
     92        Environment::GetSingleton()->GetBoolValue("VspOspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 
     93         
     94        //Environment::GetSingleton()->GetFloatValue("VspOspTree.maxTotalMemory", mMaxTotalMemory); 
     95        Environment::GetSingleton()->GetFloatValue("VspOspTree.maxStaticMemory", mMaxMemory); 
     96 
     97        Environment::GetSingleton()->GetBoolValue("VspOspTree.useCostHeuristics", mUseCostHeuristics); 
     98        Environment::GetSingleton()->GetBoolValue("VspOspTree.simulateOctree", mCirculatingAxis); 
     99        Environment::GetSingleton()->GetBoolValue("VspOspTree.useRandomAxis", mUseRandomAxis); 
     100        Environment::GetSingleton()->GetIntValue("VspOspTree.nodePriorityQueueType", mNodePriorityQueueType); 
    127101         
    128102        char subdivisionStatsLog[100]; 
    129         env->GetStringValue("VspBspTree.subdivisionStats", subdivisionStatsLog); 
     103        Environment::GetSingleton()->GetStringValue("VspOspTree.subdivisionStats", subdivisionStatsLog); 
    130104        mSubdivisionStats.open(subdivisionStatsLog); 
    131105 
    132         env->GetFloatValue("VspBspTree.Construction.minBand", mMinBand); 
    133         env->GetFloatValue("VspBspTree.Construction.maxBand", mMaxBand); 
    134         env->GetBoolValue("VspBspTree.Construction.useDrivingAxisForMaxCost", mUseDrivingAxisForMaxCost); 
     106        Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.minBand", mMinBand); 
     107        Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.maxBand", mMaxBand); 
     108         
    135109 
    136110        //-- debug output 
     
    145119        Debug << "miss tolerance: " << mTermMissTolerance << endl; 
    146120        Debug << "max view cells: " << mMaxViewCells << endl; 
    147         Debug << "max polygon candidates: " << mMaxPolyCandidates << endl; 
    148         //Debug << "max plane candidates: " << mMaxRayCandidates << endl; 
    149121        Debug << "randomize: " << randomize << endl; 
    150122 
    151         Debug << "using area for pvs: " << mUseAreaForPvs << endl; 
    152         Debug << "render cost weight: " << mRenderCostWeight << endl; 
    153123        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl; 
    154124        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl; 
    155125        Debug << "only driving axis: " << mOnlyDrivingAxis << endl; 
    156126        Debug << "max memory: " << mMaxMemory << endl; 
    157         Debug << "use poly split if available: " << mUsePolygonSplitIfAvailable << endl; 
    158127        Debug << "use cost heuristics: " << mUseCostHeuristics << endl; 
    159         Debug << "use split cost queue: " << mUseSplitCostQueue << endl; 
    160128        Debug << "subdivision stats log: " << subdivisionStatsLog << endl; 
    161129        Debug << "use random axis: " << mUseRandomAxis << endl; 
    162130        Debug << "priority queue type: " << mNodePriorityQueueType << endl; 
    163         Debug << "empty view cells merge: " << mEmptyViewCellsMergeAllowed << endl; 
    164131        Debug << "circulating axis: " << mCirculatingAxis << endl; 
    165132        Debug << "minband: " << mMinBand << endl; 
    166133        Debug << "maxband: " << mMaxBand << endl; 
    167         Debug << "use driving axis for max cost: " << mUseDrivingAxisForMaxCost << endl; 
    168  
    169         Debug << "Split plane strategy: "; 
    170  
    171         if (mSplitPlaneStrategy & RANDOM_POLYGON) 
    172         { 
    173                 Debug << "random polygon "; 
    174         } 
    175         if (mSplitPlaneStrategy & AXIS_ALIGNED) 
    176         { 
    177                 Debug << "axis aligned "; 
    178         } 
    179         if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    180         { 
    181                 mCostNormalizer += mLeastRaySplitsFactor; 
    182                 Debug << "least ray splits "; 
    183         } 
    184         if (mSplitPlaneStrategy & BALANCED_RAYS) 
    185         { 
    186                 mCostNormalizer += mBalancedRaysFactor; 
    187                 Debug << "balanced rays "; 
    188         } 
    189         if (mSplitPlaneStrategy & PVS) 
    190         { 
    191                 mCostNormalizer += mPvsFactor; 
    192                 Debug << "pvs"; 
    193         } 
    194  
     134         
    195135 
    196136        mSplitCandidates = new vector<SortableEntry>; 
     
    199139} 
    200140 
    201 VspBspTree::VspBspTree(): 
    202 mRoot(NULL), 
    203 mUseAreaForPvs(false), 
    204 mCostNormalizer(Limits::Small), 
    205 mViewCellsManager(NULL), 
    206 mOutOfBoundsCell(NULL), 
    207 mStoreRays(false), 
    208 mRenderCostWeight(0.5), 
    209 mUseRandomAxis(false), 
    210 mTimeStamp(1), 
    211 mEpsilon(1e-6f) 
    212 { 
    213 } 
    214  
    215 BspViewCell *VspBspTree::GetOutOfBoundsCell() 
     141 
     142BspViewCell *VspOspTree::GetOutOfBoundsCell() 
    216143{ 
    217144        return mOutOfBoundsCell; 
     
    219146 
    220147 
    221 BspViewCell *VspBspTree::GetOrCreateOutOfBoundsCell() 
     148BspViewCell *VspOspTree::GetOrCreateOutOfBoundsCell() 
    222149{ 
    223150        if (!mOutOfBoundsCell) 
     
    232159 
    233160 
    234 const BspTreeStatistics &VspBspTree::GetStatistics() const 
     161const BspTreeStatistics &VspOspTree::GetStatistics() const 
    235162{ 
    236163        return mBspStats; 
     
    238165 
    239166 
    240 VspBspTree::~VspBspTree() 
     167VspOspTree::~VspOspTree() 
    241168{ 
    242169        DEL_PTR(mRoot); 
     
    244171} 
    245172 
    246  
    247 int VspBspTree::AddMeshToPolygons(Mesh *mesh, 
    248                                                                   PolygonContainer &polys, 
    249                                                                   MeshInstance *parent) 
    250 { 
    251         FaceContainer::const_iterator fi; 
    252  
    253         // copy the face data to polygons 
    254         for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi) 
    255         { 
    256                 Polygon3 *poly = new Polygon3((*fi), mesh); 
    257  
    258                 if (poly->Valid(mEpsilon)) 
    259                 { 
    260                         poly->mParent = parent; // set parent intersectable 
    261                         polys.push_back(poly); 
    262                 } 
    263                 else 
    264                         DEL_PTR(poly); 
    265         } 
    266         return (int)mesh->mFaces.size(); 
    267 } 
    268  
    269  
    270 int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 
    271                                                                  PolygonContainer &polys, 
    272                                                                  int maxObjects) 
    273 { 
    274         int limit = (maxObjects > 0) ? 
    275                 Min((int)viewCells.size(), maxObjects) : (int)viewCells.size(); 
    276  
    277         int polysSize = 0; 
    278  
    279         for (int i = 0; i < limit; ++ i) 
    280         { 
    281                 if (viewCells[i]->GetMesh()) // copy the mesh data to polygons 
    282                 { 
    283                         mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb 
    284                         polysSize += 
    285                                 AddMeshToPolygons(viewCells[i]->GetMesh(), 
    286                                                                   polys, 
    287                                                                   viewCells[i]); 
    288                 } 
    289         } 
    290  
    291         return polysSize; 
    292 } 
    293  
    294  
    295 int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, 
    296                                                                  PolygonContainer &polys, 
    297                                                                  int maxObjects) 
    298 { 
    299         int limit = (maxObjects > 0) ? 
    300                 Min((int)objects.size(), maxObjects) : (int)objects.size(); 
    301  
    302         for (int i = 0; i < limit; ++i) 
    303         { 
    304                 Intersectable *object = objects[i];//*it; 
    305                 Mesh *mesh = NULL; 
    306  
    307                 switch (object->Type()) // extract the meshes 
    308                 { 
    309                 case Intersectable::MESH_INSTANCE: 
    310                         mesh = dynamic_cast<MeshInstance *>(object)->GetMesh(); 
    311                         break; 
    312                 case Intersectable::VIEW_CELL: 
    313                         mesh = dynamic_cast<ViewCell *>(object)->GetMesh(); 
    314                         break; 
    315                 case Intersectable::TRANSFORMED_MESH_INSTANCE: 
    316                         { 
    317                                 TransformedMeshInstance *mi = dynamic_cast<TransformedMeshInstance *>(object); 
    318  
    319                                 if (!mi->GetMesh()) 
    320                                         break; 
    321  
    322                                 mesh = new Mesh(*mi->GetMesh()); 
    323  
    324                                 Matrix4x4 m; 
    325                                 mi->GetWorldTransform(m); 
    326  
    327                                 mesh->ApplyTransformation(m); 
    328  
    329                 break; 
    330                         } 
    331                 default: 
    332                         Debug << "intersectable type not supported" << endl; 
    333                         break; 
    334                 } 
    335  
    336         if (mesh) // copy the mesh data to polygons 
    337                 { 
    338                         mBox.Include(object->GetBox()); // add to BSP tree aabb 
    339                         AddMeshToPolygons(mesh, polys, NULL); 
    340  
    341                         // cleanup 
    342                         if (object->Type() == Intersectable::TRANSFORMED_MESH_INSTANCE) 
    343                                 DEL_PTR(mesh); 
    344                 } 
    345         } 
    346  
    347         return (int)polys.size(); 
    348 } 
    349  
    350  
    351 void VspBspTree::Construct(const VssRayContainer &sampleRays, 
     173void VspOspTree::Construct(const VssRayContainer &sampleRays, 
    352174                                                   AxisAlignedBox3 *forcedBoundingBox) 
    353175{ 
     
    371193        int numObj = 0; 
    372194 
    373         //-- extract polygons intersected by the rays 
    374         for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
    375         { 
    376                 VssRay *ray = *rit; 
    377  
    378                 if ((mBox.IsInside(ray->mTermination) || !forcedBoundingBox) && 
    379                         ray->mTerminationObject &&  
    380                         !ray->mTerminationObject->Mailed()) 
    381                 { 
    382                         ray->mTerminationObject->Mail(); 
    383                         MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject); 
    384                         AddMeshToPolygons(obj->GetMesh(), polys, obj); 
    385                         ++ numObj; 
    386  
    387                         //-- compute bounding box 
    388                         if (!forcedBoundingBox) 
    389                                 mBox.Include(ray->mTermination); 
    390                 } 
    391  
    392                 if ((mBox.IsInside(ray->mOrigin) || !forcedBoundingBox) && 
    393                         ray->mOriginObject &&  
    394                         !ray->mOriginObject->Mailed()) 
    395                 { 
    396                         ray->mOriginObject->Mail(); 
    397                         MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject); 
    398                         AddMeshToPolygons(obj->GetMesh(), polys, obj); 
    399                         ++ numObj; 
    400  
    401                         //-- compute bounding box 
    402                         if (!forcedBoundingBox) 
    403                                 mBox.Include(ray->mOrigin); 
    404                 } 
    405         } 
    406          
    407         Debug << "maximal pvs (i.e., pvs still considered as valid) : "  
    408                   << mViewCellsManager->GetMaxPvsSize() << endl; 
    409  
    410195        //-- store rays 
    411196        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     
    430215        } 
    431216 
    432         // normalize 
    433         if (mUseAreaForPvs) 
    434                 mTermMinProbability *= mBox.SurfaceArea();  
    435         else  
    436                 mTermMinProbability *= mBox.GetVolume(); 
    437  
    438         // throw out unnecessary polygons 
    439         PreprocessPolygons(polys); 
    440  
    441         mBspStats.polys = (int)polys.size(); 
     217        mTermMinProbability *= mBox.GetVolume(); 
     218 
    442219        mGlobalCostMisses = 0; 
    443220 
    444221        cout << "finished" << endl; 
    445222 
    446         Debug << "\nPolygon extraction: " << (int)polys.size() << " polys extracted from " 
    447                   << (int)sampleRays.size() << " rays in " 
    448                   << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl << endl; 
    449  
    450223        // use split cost priority queue 
    451         if (mUseSplitCostQueue) 
    452         { 
    453                 ConstructWithSplitQueue(polys, rays); 
    454         } 
    455         else 
    456         { 
    457                 Construct(polys, rays); 
    458         } 
    459  
    460         // clean up polygons 
    461         CLEAR_CONTAINER(polys); 
     224        Construct(rays); 
    462225} 
    463226 
    464227 
    465228// TODO: return memory usage in MB 
    466 float VspBspTree::GetMemUsage() const 
     229float VspOspTree::GetMemUsage() const 
    467230{ 
    468231        return (float) 
    469                  (sizeof(VspBspTree) +  
     232                 (sizeof(VspOspTree) +  
    470233                  mBspStats.Leaves() * sizeof(BspLeaf) +  
    471234                  mCreatedViewCells * sizeof(BspViewCell) + 
     
    476239 
    477240 
    478  
    479 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 
    480 { 
    481         VspBspTraversalQueue tQueue; 
     241void VspOspTree::Construct(RayInfoContainer *rays) 
     242{ 
     243        VspOspSplitQueue tQueue; 
    482244 
    483245        mRoot = new BspLeaf(); 
    484246 
    485         // constrruct root node geometry 
    486         BspNodeGeometry *geom = new BspNodeGeometry(); 
    487         ConstructGeometry(mRoot, *geom); 
    488  
    489         const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(); 
    490  
    491         VspBspTraversalData tData(mRoot, 
    492                                                           new PolygonContainer(polys), 
     247        const float prop = mBox.GetVolume(); 
     248 
     249        VspOspTraversalData tData(mRoot, 
    493250                                                          0, 
    494251                                                          rays, 
    495252                              ComputePvsSize(*rays), 
    496253                                                          prop, 
    497                                                           geom); 
    498  
    499         EvalPriority(tData); 
    500  
    501  
    502         // first node is kd node, i.e. an axis aligned box 
    503         if (1) 
    504         tData.mIsKdNode = true; 
    505         else 
    506                 tData.mIsKdNode = false; 
    507  
    508         tQueue.push(tData); 
    509  
    510  
    511         mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume(); 
    512         mTotalPvsSize = tData.mPvs; 
    513          
    514         mSubdivisionStats  
    515                         << "#ViewCells\n1" <<  endl 
    516                         << "#RenderCostDecrease\n0" << endl  
    517                         << "#TotalRenderCost\n" << mTotalCost << endl 
    518                         << "#AvgRenderCost\n" << mTotalPvsSize << endl; 
    519  
    520         Debug << "total cost: " << mTotalCost << endl; 
    521          
    522          
    523         mBspStats.Start(); 
    524         cout << "Constructing vsp bsp tree ... \n"; 
    525  
    526         long startTime = GetTime();      
    527         int nLeaves = 500; 
    528         int nViewCells = 500; 
    529  
    530         // used for intermediate time measurements and progress 
    531         long interTime = GetTime();      
    532  
    533         mOutOfMemory = false; 
    534  
    535         mCreatedViewCells = 0; 
    536          
    537         while (!tQueue.empty()) 
    538         { 
    539                 tData = tQueue.top(); 
    540             tQueue.pop();                
    541  
    542                 if (0 && !mOutOfMemory) 
    543                 { 
    544                         float mem = GetMemUsage(); 
    545  
    546                         if (mem > mMaxMemory) 
    547                         { 
    548                                 mOutOfMemory = true; 
    549                                 Debug << "memory limit reached: " << mem << endl; 
    550                         } 
    551                 } 
    552  
    553                 // subdivide leaf node 
    554                 BspNode *r = Subdivide(tQueue, tData); 
    555  
    556                 if (r == mRoot) 
    557                         Debug << "VSP BSP tree construction time spent at root: " 
    558                                   << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
    559  
    560                 if (mBspStats.Leaves() >= nLeaves) 
    561                 { 
    562                         nLeaves += 500; 
    563  
    564                         cout << "leaves=" << mBspStats.Leaves() << endl; 
    565                         Debug << "needed " 
    566                                   << TimeDiff(interTime, GetTime())*1e-3  
    567                                   << " secs to create 500 view cells" << endl; 
    568                         interTime = GetTime(); 
    569                 } 
    570  
    571                 if (mCreatedViewCells >= nViewCells) 
    572                 { 
    573                         nViewCells += 500; 
    574  
    575                         cout << "generated " << mCreatedViewCells << " viewcells" << endl; 
    576                 } 
    577         } 
    578  
    579         Debug << "Used Memory: " << GetMemUsage() << " MB" << endl << endl; 
    580         cout << "finished\n"; 
    581  
    582         mBspStats.Stop(); 
    583 } 
    584  
    585  
    586  
    587 void VspBspTree::ConstructWithSplitQueue(const PolygonContainer &polys,  
    588                                                                                           RayInfoContainer *rays) 
    589 { 
    590         VspBspSplitQueue tQueue; 
    591  
    592         mRoot = new BspLeaf(); 
    593  
    594         // constrruct root node geometry 
    595         BspNodeGeometry *geom = new BspNodeGeometry(); 
    596         ConstructGeometry(mRoot, *geom); 
    597  
    598         const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(); 
    599  
    600         VspBspTraversalData tData(mRoot, 
    601                                                           new PolygonContainer(polys), 
    602                                                           0, 
    603                                                           rays, 
    604                               ComputePvsSize(*rays), 
    605                                                           prop, 
    606                                                           geom); 
     254                                                          mBox); 
    607255 
    608256 
    609257        // compute first split candidate 
    610         VspBspSplitCandidate splitCandidate; 
     258        VspOspSplitCandidate splitCandidate; 
    611259        EvalSplitCandidate(tData, splitCandidate); 
    612260 
     
    697345 
    698346 
    699 bool VspBspTree::LocalTerminationCriteriaMet(const VspBspTraversalData &data) const 
     347bool VspOspTree::LocalTerminationCriteriaMet(const VspOspTraversalData &data) const 
    700348{ 
    701349        return 
     
    708356 
    709357 
    710 bool VspBspTree::GlobalTerminationCriteriaMet(const VspBspTraversalData &data) const 
     358bool VspOspTree::GlobalTerminationCriteriaMet(const VspOspTraversalData &data) const 
    711359{ 
    712360        return 
     
    718366 
    719367 
    720  
    721 BspNode *VspBspTree::Subdivide(VspBspTraversalQueue &tQueue, 
    722                                                            VspBspTraversalData &tData) 
    723 { 
    724         BspNode *newNode = tData.mNode; 
    725  
    726         if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData)) 
    727         { 
    728                 PolygonContainer coincident; 
    729  
    730                 VspBspTraversalData tFrontData; 
    731                 VspBspTraversalData tBackData; 
    732  
    733                 // create new interior node and two leaf nodes 
    734                 // or return leaf as it is (if maxCostRatio missed) 
    735                 int splitAxis; 
    736                 bool splitFurther = true; 
    737                 int maxCostMisses = tData.mMaxCostMisses; 
    738                  
    739                 Plane3 splitPlane; 
    740                 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
    741                  
    742                 // choose next split plane 
    743                 if (!SelectPlane(splitPlane, leaf, tData, tFrontData, tBackData, splitAxis)) 
    744                 { 
    745                         ++ maxCostMisses; 
    746  
    747                         if (maxCostMisses > mTermMissTolerance) 
    748                         { 
    749                                 // terminate branch because of max cost 
    750                                 ++ mBspStats.maxCostNodes; 
    751                                 splitFurther = false; 
    752                         } 
    753                 } 
    754          
    755                 // if this a valid split => subdivide this node further 
    756                 if (splitFurther) //-- continue subdivision 
    757                 { 
    758                         newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData, coincident); 
    759  
    760                         if (splitAxis < 3) 
    761                                 ++ mBspStats.splits[splitAxis]; 
    762                         else 
    763                                 ++ mBspStats.polySplits; 
    764  
    765                         // if it was a kd node (i.e., a box) and the split axis is axis aligned, it is still a kd node 
    766                         tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && (splitAxis < 3)); 
    767                         tFrontData.mAxis = tBackData.mAxis = splitAxis; 
    768  
    769                         // how often was max cost ratio missed in this branch? 
    770                         tFrontData.mMaxCostMisses = maxCostMisses; 
    771                         tBackData.mMaxCostMisses = maxCostMisses; 
    772  
    773                         EvalPriority(tFrontData); 
    774                         EvalPriority(tBackData); 
    775  
    776                         // evaluate subdivision stats 
    777                         if (1) 
    778                         { 
    779                                 float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 
    780                                 float cBack = (float)tBackData.mPvs * tBackData.mProbability; 
    781                                 float cData = (float)tData.mPvs * tData.mProbability;; 
    782  
    783                 float costDecr = (cFront + cBack - cData) / mBox.GetVolume(); 
    784  
    785                                 mTotalCost += costDecr; 
    786                                 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 
    787  
    788                                 mSubdivisionStats  
    789                                                 << "#ViewCells\n" << mBspStats.Leaves() << endl 
    790                                                 << "#RenderCostDecrease\n" << -costDecr << endl  
    791                                                 << "#TotalRenderCost\n" << mTotalCost << endl 
    792                                                 << "#AvgRenderCost\n" << (float)mTotalPvsSize / (float)mBspStats.Leaves() << endl; 
    793                         } 
    794  
    795                         // push the children on the stack 
    796                         tQueue.push(tFrontData); 
    797                         tQueue.push(tBackData); 
    798  
    799                         // delete old leaf node 
    800                         DEL_PTR(tData.mNode); 
    801                 } 
    802         } 
    803  
    804         //-- terminate traversal and create new view cell 
    805         if (newNode->IsLeaf()) 
    806         { 
    807                 BspLeaf *leaf = dynamic_cast<BspLeaf *>(newNode); 
    808                 BspViewCell *viewCell = new BspViewCell(); 
    809                  
    810                 leaf->SetViewCell(viewCell); 
    811          
    812                 //-- update pvs 
    813                 int conSamp = 0; 
    814                 float sampCon = 0.0f; 
    815                 AddToPvs(leaf, *tData.mRays, sampCon, conSamp); 
    816  
    817                 // update scalar pvs size lookup 
    818                 mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().GetSize()); 
    819          
    820  
    821                 mBspStats.contributingSamples += conSamp; 
    822                 mBspStats.sampleContributions +=(int) sampCon; 
    823  
    824                 //-- store additional info 
    825                 if (mStoreRays) 
    826                 { 
    827                         RayInfoContainer::const_iterator it, it_end = tData.mRays->end(); 
    828                         for (it = tData.mRays->begin(); it != it_end; ++ it) 
    829                         { 
    830                                 (*it).mRay->Ref();                       
    831                                 leaf->mVssRays.push_back((*it).mRay); 
    832                         } 
    833                 } 
    834  
    835                 // should I check here? 
    836                 if (0 && !mViewCellsManager->CheckValidity(viewCell, 0, mViewCellsManager->GetMaxPvsSize())) 
    837                 { 
    838                         viewCell->SetValid(false); 
    839                         leaf->SetTreeValid(false); 
    840                         PropagateUpValidity(leaf); 
    841  
    842                         ++ mBspStats.invalidLeaves; 
    843                 } 
    844                  
    845         viewCell->mLeaf = leaf; 
    846  
    847                 if (mUseAreaForPvs) 
    848                         viewCell->SetArea(tData.mProbability); 
    849                 else 
    850                         viewCell->SetVolume(tData.mProbability); 
    851  
    852                 leaf->mProbability = tData.mProbability; 
    853  
    854                 EvaluateLeafStats(tData);                
    855         } 
    856  
    857         //-- cleanup 
    858         tData.Clear(); 
    859  
    860         return newNode; 
    861 } 
    862  
    863368// subdivide using a split plane queue 
    864 BspNode *VspBspTree::Subdivide(VspBspSplitQueue &tQueue, 
    865                                                            VspBspSplitCandidate &splitCandidate) 
    866 { 
    867         VspBspTraversalData &tData = splitCandidate.mParentData; 
     369BspNode *VspOspTree::Subdivide(VspOspSplitQueue &tQueue, 
     370                                                           VspOspSplitCandidate &splitCandidate) 
     371{ 
     372        VspOspTraversalData &tData = splitCandidate.mParentData; 
    868373 
    869374        BspNode *newNode = tData.mNode; 
     
    871376        if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData)) 
    872377        {        
    873                 PolygonContainer coincident; 
    874  
    875                 VspBspTraversalData tFrontData; 
    876                 VspBspTraversalData tBackData; 
     378                VspOspTraversalData tFrontData; 
     379                VspOspTraversalData tBackData; 
    877380 
    878381                //-- continue subdivision 
    879382                 
    880383                // create new interior node and two leaf node 
    881                 const Plane3 splitPlane = splitCandidate.mSplitPlane; 
     384                //TODO 
     385                const Plane3 splitPlane;// = splitCandidate.mSplitPlane; 
    882386                                 
    883                 newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData, coincident); 
    884          
    885                 const int splitAxis = splitCandidate.mSplitAxis; 
     387                newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData); 
     388         
    886389                const int maxCostMisses = splitCandidate.mMaxCostMisses; 
    887390 
    888                 if (splitAxis < 3) 
    889                         ++ mBspStats.splits[splitAxis]; 
    890                 else 
    891                         ++ mBspStats.polySplits; 
    892  
    893                 tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && (splitAxis < 3)); 
    894                 tFrontData.mAxis = tBackData.mAxis = splitAxis; 
    895391 
    896392                // how often was max cost ratio missed in this branch? 
     
    922418         
    923419                //-- push the new split candidates on the stack 
    924                 VspBspSplitCandidate frontCandidate; 
    925                 VspBspSplitCandidate backCandidate; 
     420                VspOspSplitCandidate frontCandidate; 
     421                VspOspSplitCandidate backCandidate; 
    926422 
    927423                EvalSplitCandidate(tFrontData, frontCandidate); 
     
    969465                viewCell->mLeaf = leaf; 
    970466 
    971                 if (mUseAreaForPvs) 
    972                         viewCell->SetArea(tData.mProbability); 
    973                 else 
    974                         viewCell->SetVolume(tData.mProbability); 
    975  
     467                viewCell->SetVolume(tData.mProbability); 
    976468        leaf->mProbability = tData.mProbability; 
    977469 
     
    986478 
    987479 
    988 void VspBspTree::EvalPriority(VspBspTraversalData &tData) const 
    989 { 
    990     switch (mNodePriorityQueueType)  
    991         { 
    992         case BREATH_FIRST: 
    993                 tData.mPriority = (float)-tData.mDepth; 
    994                 break; 
    995         case DEPTH_FIRST: 
    996                 tData.mPriority = (float)tData.mDepth; 
    997                 break; 
    998         default: 
    999                 tData.mPriority = tData.mPvs * tData.mProbability; 
    1000                 //Debug << "priority: " << tData.mPriority << endl; 
    1001                 break; 
    1002         } 
    1003 } 
    1004  
    1005  
    1006 void VspBspTree::EvalSplitCandidate(VspBspTraversalData &tData, 
    1007                                                                         VspBspSplitCandidate &splitData) 
    1008 { 
    1009         VspBspTraversalData frontData; 
    1010         VspBspTraversalData backData; 
     480void VspOspTree::EvalSplitCandidate(VspOspTraversalData &tData, 
     481                                                                        VspOspSplitCandidate &splitData) 
     482{ 
     483        VspOspTraversalData frontData; 
     484        VspOspTraversalData backData; 
    1011485 
    1012486        BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
    1013487 
    1014488        // compute locally best split plane 
    1015     bool success = SelectPlane(splitData.mSplitPlane, leaf, tData,  
    1016                                                            frontData, backData, splitData.mSplitAxis); 
    1017  
    1018         // TODO: reuse 
    1019         DEL_PTR(frontData.mGeometry); 
    1020         DEL_PTR(backData.mGeometry); 
    1021          
     489        // TODO 
     490    const bool success =0;/// SelectPlane(splitData.mSplitPlane, tData,  
     491//                                                                       frontData, backData); 
     492        //TODO 
    1022493        // compute global decrease in render cost 
    1023         splitData.mRenderCost = EvalRenderCostDecrease(splitData.mSplitPlane, tData); 
     494        splitData.mRenderCost = 0;//EvalRenderCostDecrease(splitData.mSplitPlane, tData); 
    1024495        splitData.mParentData = tData; 
    1025496        splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1; 
     
    1027498 
    1028499 
    1029 BspInterior *VspBspTree::SubdivideNode(const Plane3 &splitPlane, 
    1030                                                                            VspBspTraversalData &tData, 
    1031                                                                            VspBspTraversalData &frontData, 
    1032                                                                            VspBspTraversalData &backData, 
    1033                                                                            PolygonContainer &coincident) 
     500BspInterior *VspOspTree::SubdivideNode(const Plane3 &splitPlane, 
     501                                                                           VspOspTraversalData &tData, 
     502                                                                           VspOspTraversalData &frontData, 
     503                                                                           VspOspTraversalData &backData) 
    1034504{ 
    1035505        BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
     
    1037507        //-- the front and back traversal data is filled with the new values 
    1038508        frontData.mDepth = tData.mDepth + 1; 
    1039         frontData.mPolygons = new PolygonContainer(); 
    1040509        frontData.mRays = new RayInfoContainer(); 
    1041510         
    1042511        backData.mDepth = tData.mDepth + 1; 
    1043         backData.mPolygons = new PolygonContainer(); 
    1044512        backData.mRays = new RayInfoContainer(); 
    1045513         
     
    1059527         
    1060528        // if geometry was not already computed 
    1061         if (!frontData.mGeometry && !backData.mGeometry) 
    1062         { 
    1063                 frontData.mGeometry = new BspNodeGeometry(); 
    1064                 backData.mGeometry = new BspNodeGeometry(); 
    1065  
    1066                 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 
    1067                                                                            *backData.mGeometry, 
    1068                                                                            splitPlane, 
    1069                                                                            mBox, 
    1070                                                                            //0.0f); 
    1071                                                                            mEpsilon); 
    1072                  
    1073                 if (mUseAreaForPvs) 
    1074                 { 
    1075                         frontData.mProbability = frontData.mGeometry->GetArea(); 
    1076                         backData.mProbability = backData.mGeometry->GetArea(); 
    1077                 } 
    1078                 else 
    1079                 { 
    1080                         frontData.mProbability = frontData.mGeometry->GetVolume(); 
    1081                         backData.mProbability = tData.mProbability - frontData.mProbability; 
    1082  
    1083                         // should never come here: wrong volume !!! 
    1084                         if (0) 
    1085                         { 
    1086                                 if (frontData.mProbability < -0.00001) 
    1087                                         Debug << "fatal error f: " << frontData.mProbability << endl; 
    1088                                 if (backData.mProbability < -0.00001) 
    1089                                         Debug << "fatal error b: " << backData.mProbability << endl; 
    1090  
    1091                                 // clamp because of precision issues 
    1092                                 if (frontData.mProbability < 0) frontData.mProbability = 0; 
    1093                                 if (backData.mProbability < 0) backData.mProbability = 0; 
    1094                         } 
    1095                 } 
    1096         } 
    1097  
    1098          
    1099     // subdivide polygons 
    1100         SplitPolygons(splitPlane, 
    1101                                   *tData.mPolygons, 
    1102                       *frontData.mPolygons, 
    1103                                   *backData.mPolygons, 
    1104                                   coincident); 
    1105  
    1106  
    1107  
    1108         /////////////////////////////////////// 
     529        // TODO 
     530 
     531#if TODO 
     532        tData.mBoundingBox.Split(splitPlane.mAxis, splitPlane.mPosition,  
     533                                                         frontData.mBoundingBox, backData.mBoundingBox); 
     534 
     535#endif 
     536 
     537        frontData.mProbability = frontData.mBoundingBox.GetVolume(); 
     538        backData.mProbability = tData.mProbability - frontData.mProbability; 
     539 
     540         
     541    /////////////////////////////////////////// 
    1109542        // subdivide further 
    1110543 
     
    1149582        interior->mTimeStamp = mTimeStamp ++; 
    1150583         
    1151  
    1152         //DEL_PTR(leaf); 
    1153584        return interior; 
    1154585} 
    1155586 
    1156587 
    1157 void VspBspTree::AddToPvs(BspLeaf *leaf, 
     588void VspOspTree::AddToPvs(BspLeaf *leaf, 
    1158589                                                  const RayInfoContainer &rays, 
    1159590                                                  float &sampleContributions, 
     
    1200631 
    1201632 
    1202 void VspBspTree::SortSplitCandidates(const RayInfoContainer &rays,  
     633void VspOspTree::SortSplitCandidates(const RayInfoContainer &rays,  
    1203634                                                                         const int axis,  
    1204635                                                                         float minBand,  
     
    1251682 
    1252683 
    1253 float VspBspTree::BestCostRatioHeuristics(const RayInfoContainer &rays, 
     684float VspOspTree::BestCostRatioHeuristics(const RayInfoContainer &rays, 
    1254685                                                                                  const AxisAlignedBox3 &box, 
    1255686                                                                                  const int pvsSize, 
     
    1413844        if (splitPlaneFound) 
    1414845        { 
    1415                 ratio = mPvsFactor * newRenderCost / (oldRenderCost + Limits::Small); 
     846                ratio = newRenderCost / (oldRenderCost + Limits::Small); 
    1416847        } 
    1417848        //if (axis != 1) 
     
    1423854 
    1424855 
    1425 float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 
    1426                                                                                  const VspBspTraversalData &tData, 
    1427                                                                                  int &axis, 
    1428                                                                                  BspNodeGeometry **frontGeom, 
    1429                                                                                  BspNodeGeometry **backGeom, 
    1430                                                                                  float &pFront, 
    1431                                                                                  float &pBack, 
    1432                                                                                  const bool isKdNode) 
     856float VspOspTree::SelectPlane(const VspOspTraversalData &tData, 
     857                                                          AxisAlignedPlane &plane, 
     858                                                          float &pFront, 
     859                                                          float &pBack) 
    1433860{ 
    1434861        float nPosition[3]; 
     
    1437864        float nProbBack[3]; 
    1438865 
    1439         BspNodeGeometry *nFrontGeom[3]; 
    1440         BspNodeGeometry *nBackGeom[3]; 
    1441  
    1442         // set to NULL, so I can find out which gemetry was stored 
    1443         for (int i = 0; i < 3; ++ i) 
    1444         { 
    1445                 nFrontGeom[i] = NULL; 
    1446                 nBackGeom[i] = NULL; 
    1447         } 
    1448  
    1449866        // create bounding box of node geometry 
    1450         AxisAlignedBox3 box; 
    1451                  
    1452         //TODO: for kd split geometry already is box => only take minmax vertices 
    1453         if (1) 
    1454         { 
    1455                 // get bounding box from geometry 
    1456                 tData.mGeometry->GetBoundingBox(box); 
    1457         } 
    1458         else 
    1459         { 
    1460                 box.Initialize(); 
    1461                 RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 
    1462  
    1463                 for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 
    1464                         box.Include((*ri).ExtrapTermination()); 
    1465         } 
    1466  
     867        AxisAlignedBox3 box = tData.mBoundingBox; 
     868                 
    1467869        int sAxis = 0; 
    1468         int bestAxis; 
    1469  
    1470         // if max cost ratio is exceeded, take split along longest axis instead 
    1471         const float maxCostRatioForArbitraryAxis = 0.9f; 
    1472  
    1473         if (mUseDrivingAxisForMaxCost) 
    1474                 bestAxis = box.Size().DrivingAxis(); 
    1475         else 
    1476                 bestAxis = -1; 
     870        int bestAxis = -1; 
    1477871 
    1478872#if 0 
     
    1493887                sAxis = box.Size().DrivingAxis(); 
    1494888 
    1495                  
    1496         //Debug << "use special axis: " << useSpecialAxis << endl; 
    1497         //Debug << "axis: " << sAxis << " drivingaxis: " << box.Size().DrivingAxis(); 
    1498  
    1499         for (axis = 0; axis < 3 ; ++ axis) 
     889 
     890        for (int axis = 0; axis < 3 ; ++ axis) 
    1500891        { 
    1501892                if (!useSpecialAxis || (axis == sAxis)) 
     
    1512903                                                                                        nPosition[axis]);                        
    1513904                        } 
    1514                          
    1515                         //-- split plane position is spatial median 
    1516  
    1517  
    1518                         // also use median split if cost ratio very low as 
    1519                         // there are not enough visibility cues 
    1520                         //if (!mUseCostHeuristics || (nCostRatio[axis] > maxCostRatioForHeur)) 
    1521                         else  
    1522                         { 
    1523  
     905                        else //-- split plane position is spatial median 
     906                        { 
    1524907                                nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 
    1525                                 Vector3 normal(0,0,0); normal[axis] = 1.0f; 
    1526  
    1527                                 // allows faster split because we have axis aligned kd tree boxes 
    1528                                 if (isKdNode) 
    1529                                 { 
    1530                                         nCostRatio[axis] = EvalAxisAlignedSplitCost(tData, 
    1531                                                                                                                                 box, 
    1532                                                                                                                                 axis, 
    1533                                                                                                                                 nPosition[axis], 
    1534                                                                                                                                 nProbFront[axis],  
    1535                                                                                                                                 nProbBack[axis]); 
    1536                                          
    1537                                         Vector3 pos; 
    1538                                          
    1539                                         // create back geometry from box 
    1540                                         // NOTE: the geometry is saved when possible 
    1541                                         pos = box.Max(); pos[axis] = nPosition[axis]; 
    1542                                         AxisAlignedBox3 bBox(box.Min(), pos); 
    1543                                         PolygonContainer fPolys; 
    1544                                         bBox.ExtractPolys(fPolys); 
    1545  
    1546                                         nBackGeom[axis] = new BspNodeGeometry(fPolys); 
    1547          
    1548                                         //-- create front geometry from box 
    1549                                         pos = box.Min(); pos[axis] = nPosition[axis]; 
    1550                                         AxisAlignedBox3 fBox(pos, box.Max()); 
    1551  
    1552                                         PolygonContainer bPolys; 
    1553                                         fBox.ExtractPolys(bPolys); 
    1554                                         nFrontGeom[axis] = new BspNodeGeometry(bPolys); 
    1555                                 } 
    1556                                 else 
    1557                                 { 
    1558                                         nFrontGeom[axis] = new BspNodeGeometry(); 
    1559                                         nBackGeom[axis] = new BspNodeGeometry(); 
    1560  
    1561                                         nCostRatio[axis] =  
    1562                                                 EvalSplitPlaneCost(Plane3(normal, nPosition[axis]),  
    1563                                                                                    tData, *nFrontGeom[axis], *nBackGeom[axis], 
    1564                                                                                    nProbFront[axis], nProbBack[axis]); 
    1565                                 } 
     908 
     909                                nCostRatio[axis] = EvalSplitCost(tData, 
     910                                                                                                 box, 
     911                                                                                                 axis, 
     912                                                                                                 nPosition[axis], 
     913                                                                                                 nProbFront[axis],  
     914                                                                                                 nProbBack[axis]); 
    1566915                        } 
    1567916                                                 
    1568                          
    1569                         if (mUseDrivingAxisForMaxCost) 
    1570                         { 
    1571                                 // we take longest axis split if cost ratio exceeds threshold 
    1572                                 if (nCostRatio[axis] < min(maxCostRatioForArbitraryAxis, nCostRatio[bestAxis])) 
    1573                                 { 
    1574                                         bestAxis = axis; 
    1575                                 } 
    1576                                 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 
    1577                                         Debug << "taking split along longest axis (" << bestAxis << ") instead of  (" << axis << ")" << endl; 
    1578                                  
    1579                         } 
    1580                         else 
    1581                         { 
    1582                                 if (bestAxis == -1) 
    1583                                 { 
    1584                                         bestAxis = axis; 
    1585                                 } 
    1586                                 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 
    1587                                 { 
    1588                                         bestAxis = axis; 
    1589                                 } 
     917                        if (bestAxis == -1) 
     918                        { 
     919                                bestAxis = axis; 
     920                        } 
     921                        else if (nCostRatio[axis] < nCostRatio[bestAxis]) 
     922                        { 
     923                                bestAxis = axis; 
    1590924                        }  
    1591925                } 
     
    1593927 
    1594928        //-- assign values 
    1595         axis = bestAxis; 
     929        plane.mAxis = bestAxis; 
    1596930        pFront = nProbFront[bestAxis]; 
    1597931        pBack = nProbBack[bestAxis]; 
    1598932 
    1599         // assign best split nodes geometry  
    1600         *frontGeom = nFrontGeom[bestAxis]; 
    1601         *backGeom = nBackGeom[bestAxis]; 
    1602  
    1603         // and delete other geometry 
    1604         DEL_PTR(nFrontGeom[(bestAxis + 1) % 3]); 
    1605         DEL_PTR(nBackGeom[(bestAxis + 2) % 3]); 
    1606  
    1607         //-- split plane 
    1608     Vector3 normal(0,0,0); normal[bestAxis] = 1; 
    1609         plane = Plane3(normal, nPosition[bestAxis]); 
    1610  
    1611         //Debug << "best axis: " << bestAxis << " pos " << nPosition[bestAxis] << endl; 
    1612         //Debug << "!!!!!!!!!!!!!!" << endl; 
     933        //-- split plane position 
     934    plane.mPosition = nPosition[bestAxis]; 
     935 
    1613936        return nCostRatio[bestAxis]; 
    1614937} 
    1615938 
    1616939 
    1617 bool VspBspTree::SelectPlane(Plane3 &bestPlane, 
    1618                                                          BspLeaf *leaf, 
    1619                                                          VspBspTraversalData &data,                                                       
    1620                                                          VspBspTraversalData &frontData, 
    1621                                                          VspBspTraversalData &backData, 
    1622                                                          int &splitAxis) 
    1623 { 
    1624         // HACK matt: subdivide regularily to certain depth 
    1625         if (data.mDepth < 0)     
    1626         { 
    1627                 cout << "d: " << data.mDepth << endl; 
    1628                 // return axis aligned split 
    1629                 AxisAlignedBox3 box; 
    1630                 box.Initialize(); 
    1631          
    1632                 // create bounding box of region 
    1633                 data.mGeometry->GetBoundingBox(box); 
    1634          
    1635                 const int axis = box.Size().DrivingAxis(); 
    1636                 const Vector3 position = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 
    1637  
    1638                 Vector3 norm(0,0,0); norm[axis] = 1.0f; 
    1639                 bestPlane = Plane3(norm, position); 
    1640                 splitAxis = axis; 
    1641                 return true; 
    1642         } 
    1643  
    1644         // simplest strategy: just take next polygon 
    1645         if (mSplitPlaneStrategy & RANDOM_POLYGON) 
    1646         { 
    1647         if (!data.mPolygons->empty()) 
    1648                 { 
    1649                         const int randIdx =  
    1650                                 (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 
    1651                         Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 
    1652  
    1653                         bestPlane = nextPoly->GetSupportingPlane(); 
    1654                         return true; 
    1655                 } 
    1656         } 
    1657  
    1658         //-- use heuristics to find appropriate plane 
    1659  
    1660         // intermediate plane 
    1661         Plane3 plane; 
    1662         float lowestCost = MAX_FLOAT; 
    1663          
    1664         // decides if the first few splits should be only axisAligned 
    1665         const bool onlyAxisAligned  =  
    1666                 (mSplitPlaneStrategy & AXIS_ALIGNED) && 
    1667                 ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 
    1668                 ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 
    1669          
    1670         const int limit = onlyAxisAligned ? 0 :  
    1671                 Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
    1672  
    1673         float candidateCost; 
    1674  
    1675         int maxIdx = (int)data.mPolygons->size(); 
    1676  
    1677         for (int i = 0; i < limit; ++ i) 
    1678         { 
    1679                 // the already taken candidates are stored behind maxIdx 
    1680                 // => assure that no index is taken twice 
    1681                 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 
    1682                 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
    1683  
    1684                 // swap candidate to the end to avoid testing same plane 
    1685                 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 
    1686                 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 
    1687  
    1688                 // evaluate current candidate 
    1689                 BspNodeGeometry fGeom, bGeom; 
    1690                 float fArea, bArea; 
    1691                 plane = poly->GetSupportingPlane(); 
    1692                 candidateCost = EvalSplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 
    1693                  
    1694                 if (candidateCost < lowestCost) 
    1695                 { 
    1696                         bestPlane = plane; 
    1697                         lowestCost = candidateCost; 
    1698                 } 
    1699         } 
    1700  
    1701         //-- evaluate axis aligned splits 
    1702         int axis; 
    1703         BspNodeGeometry *fGeom, *bGeom; 
    1704         float pFront, pBack; 
    1705  
    1706         candidateCost = 99999999.0f; 
    1707  
    1708         // option: axis aligned split only if no polygon available 
    1709         if (!mUsePolygonSplitIfAvailable || data.mPolygons->empty()) 
    1710         { 
    1711                 candidateCost = SelectAxisAlignedPlane(plane,  
    1712                                                                                            data,  
    1713                                                                                            axis, 
    1714                                                                                            &fGeom,  
    1715                                                                                            &bGeom,  
    1716                                                                                            pFront,  
    1717                                                                                            pBack, 
    1718                                                                                            data.mIsKdNode);       
    1719         } 
    1720  
    1721         splitAxis = 3; 
    1722  
    1723         if (candidateCost < lowestCost) 
    1724         {        
    1725                 bestPlane = plane; 
    1726                 lowestCost = candidateCost; 
    1727                 splitAxis = axis; 
    1728          
    1729                 // assign already computed values 
    1730                 // we can do this because we always save the 
    1731                 // computed values from the axis aligned splits          
    1732  
    1733                 if (fGeom && bGeom) 
    1734                 { 
    1735                         frontData.mGeometry = fGeom; 
    1736                         backData.mGeometry = bGeom; 
    1737          
    1738                         frontData.mProbability = pFront; 
    1739                         backData.mProbability = pBack; 
    1740                 } 
    1741         } 
    1742         else 
    1743         { 
    1744                 DEL_PTR(fGeom); 
    1745                 DEL_PTR(bGeom); 
    1746         } 
    1747      
    1748 #ifdef _DEBUG 
    1749         Debug << "plane lowest cost: " << lowestCost << endl; 
    1750 #endif 
    1751  
    1752         // exeeded relative max cost ratio 
    1753         if (lowestCost > mTermMaxCostRatio) 
    1754         { 
    1755                 return false; 
    1756         } 
    1757  
    1758         return true; 
    1759 } 
    1760  
    1761  
    1762 Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const 
    1763 { 
    1764         const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1765  
    1766         const Vector3 minPt = rays[candidateIdx].ExtrapOrigin(); 
    1767         const Vector3 maxPt = rays[candidateIdx].ExtrapTermination(); 
    1768  
    1769         const Vector3 pt = (maxPt + minPt) * 0.5; 
    1770         const Vector3 normal = Normalize(rays[candidateIdx].mRay->GetDir()); 
    1771  
    1772         return Plane3(normal, pt); 
    1773 } 
    1774  
    1775  
    1776 Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const 
    1777 { 
    1778         Vector3 pt[3]; 
    1779  
    1780         int idx[3]; 
    1781         int cmaxT = 0; 
    1782         int cminT = 0; 
    1783         bool chooseMin = false; 
    1784  
    1785         for (int j = 0; j < 3; ++ j) 
    1786         { 
    1787                 idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1)); 
    1788  
    1789                 if (idx[j] >= (int)rays.size()) 
    1790                 { 
    1791                         idx[j] -= (int)rays.size(); 
    1792  
    1793                         chooseMin = (cminT < 2); 
    1794                 } 
    1795                 else 
    1796                         chooseMin = (cmaxT < 2); 
    1797  
    1798                 RayInfo rayInf = rays[idx[j]]; 
    1799                 pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 
    1800         } 
    1801  
    1802         return Plane3(pt[0], pt[1], pt[2]); 
    1803 } 
    1804  
    1805  
    1806 Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const 
    1807 { 
    1808         Vector3 pt[3]; 
    1809  
    1810         int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1811         int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 
    1812  
    1813         // check if rays different 
    1814         if (idx1 == idx2) 
    1815                 idx2 = (idx2 + 1) % (int)rays.size(); 
    1816  
    1817         const RayInfo ray1 = rays[idx1]; 
    1818         const RayInfo ray2 = rays[idx2]; 
    1819  
    1820         // normal vector of the plane parallel to both lines 
    1821         const Vector3 norm = Normalize(CrossProd(ray1.mRay->GetDir(), ray2.mRay->GetDir())); 
    1822  
    1823         // vector from line 1 to line 2 
    1824         const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin(); 
    1825  
    1826         // project vector on normal to get distance 
    1827         const float dist = DotProd(vd, norm); 
    1828  
    1829         // point on plane lies halfway between the two planes 
    1830         const Vector3 planePt = ray1.ExtrapOrigin() + norm * dist * 0.5; 
    1831  
    1832         return Plane3(norm, planePt); 
    1833 } 
    1834  
    1835  
    1836 inline void VspBspTree::GenerateUniqueIdsForPvs() 
     940inline void VspOspTree::GenerateUniqueIdsForPvs() 
    1837941{ 
    1838942        Intersectable::NewMail(); sBackId = Intersectable::sMailId; 
     
    1842946 
    1843947 
    1844 float VspBspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane, 
    1845                                                                                  const VspBspTraversalData &data) const 
     948float VspOspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane, 
     949                                                                                 const VspOspTraversalData &data) const 
    1846950{ 
    1847951        float pvsFront = 0; 
     
    1874978        BspNodeGeometry geomFront; 
    1875979        BspNodeGeometry geomBack; 
    1876  
    1877         // construct child geometry with regard to the candidate split plane 
    1878         data.mGeometry->SplitGeometry(geomFront, 
    1879                                                                   geomBack, 
    1880                                                                   candidatePlane, 
    1881                                                                   mBox, 
    1882                                                                   //0.0f); 
    1883                                                                   mEpsilon); 
    1884  
    1885         if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 
    1886         { 
    1887                 pFront = geomFront.GetVolume(); 
    1888                 pBack = pOverall - pFront; 
    1889  
    1890                 // something is wrong with the volume 
    1891                 if ((pFront < 0.0) || (pBack < 0.0)) 
    1892                 { 
    1893                         Debug << "ERROR in volume:\n" 
    1894                                   << "volume f :" << pFront << " b: " << pBack << " p: " << pOverall  
    1895                                   << ", real volume f: " << pFront << " b: " << geomBack.GetVolume() 
    1896                                   << ", #polygons f: " << geomFront.Size() << " b: " << geomBack.Size() << " p: " << data.mGeometry->Size() << endl; 
    1897                 } 
    1898         } 
    1899         else 
    1900         { 
    1901                 pFront = geomFront.GetArea(); 
    1902                 pBack = geomBack.GetArea(); 
    1903         } 
    1904          
     980         
     981        pFront = geomFront.GetVolume(); 
     982        pBack = pOverall - pFront; 
     983 
     984                 
    1905985 
    1906986        // -- pvs rendering heuristics 
     
    19211001 
    19221002#if 1 
    1923         // take render cost of node into account 
     1003        // take render cost of node into account to avoid being stuck in a local minimum 
    19241004        const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume(); 
    1925         //Debug << "rendercostdecr: " << 0.99f * renderCostDecrease << " old render cost: " << 0.01f * normalizedOldRenderCost << endl; 
    1926         //return 0.5f * renderCostDecrease + 0.5f * normalizedOldRenderCost; 
    19271005        return 0.99f * renderCostDecrease + 0.01f * normalizedOldRenderCost; 
    19281006#else 
     
    19321010 
    19331011 
    1934 float VspBspTree::EvalSplitPlaneCost(const Plane3 &candidatePlane, 
    1935                                                                          const VspBspTraversalData &data, 
    1936                                                                          BspNodeGeometry &geomFront, 
    1937                                                                          BspNodeGeometry &geomBack, 
    1938                                                                          float &pFront, 
    1939                                                                          float &pBack) const 
    1940 { 
    1941         float cost = 0; 
    1942  
    1943         float totalPvs = 0; 
    1944         float pvsFront = 0; 
    1945         float pvsBack = 0; 
    1946          
    1947         // probability that view point lies in back / front node 
    1948         float pOverall = 0; 
    1949         pFront = 0; 
    1950         pBack = 0; 
    1951  
    1952  
    1953         int limit; 
    1954         bool useRand; 
    1955  
    1956         // create unique ids for pvs heuristics 
    1957         GenerateUniqueIdsForPvs(); 
    1958  
    1959         // choose test rays randomly if too much 
    1960         if ((int)data.mRays->size() > mMaxTests) 
    1961         { 
    1962                 useRand = true; 
    1963                 limit = mMaxTests; 
    1964         } 
    1965         else 
    1966         { 
    1967                 useRand = false; 
    1968                 limit = (int)data.mRays->size(); 
    1969         } 
    1970          
    1971         for (int i = 0; i < limit; ++ i) 
    1972         { 
    1973                 const int testIdx = useRand ?  
    1974                         (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
    1975                 RayInfo rayInf = (*data.mRays)[testIdx]; 
    1976  
    1977                 float t; 
    1978                 VssRay *ray = rayInf.mRay; 
    1979                 const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
    1980  
    1981                 // find front and back pvs for origing and termination object 
    1982                 AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
    1983                 AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
    1984         } 
    1985  
    1986         // construct child geometry with regard to the candidate split plane 
    1987         bool splitSuccessFull = data.mGeometry->SplitGeometry(geomFront, 
    1988                                                                                                                   geomBack, 
    1989                                                                                                                   candidatePlane, 
    1990                                                                                                                   mBox, 
    1991                                                                                                                   //0.0f); 
    1992                                                                                                                   mEpsilon); 
    1993  
    1994         pOverall = data.mProbability; 
    1995  
    1996         if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 
    1997         { 
    1998                 pFront = geomFront.GetVolume(); 
    1999                 pBack = pOverall - pFront; 
    2000                  
    2001                 // HACK: precision issues possible for unbalanced split => don't take this split! 
    2002                 if (1 &&  
    2003                         (!splitSuccessFull || (pFront <= 0) || (pBack <= 0) ||  
    2004                         !geomFront.Valid() || !geomBack.Valid())) 
    2005                 { 
    2006                         //Debug << "error f: " << pFront << " b: " << pBack << endl; 
    2007                         // high penalty for this split 
    2008                         return 99999.9f; 
    2009                 } 
    2010         } 
    2011         else 
    2012         { 
    2013                 pFront = geomFront.GetArea(); 
    2014                 pBack = geomBack.GetArea(); 
    2015         } 
    2016          
    2017  
    2018         // -- pvs rendering heuristics 
    2019         const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize(); 
    2020         const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize(); 
    2021  
    2022         // only render cost heuristics or combined with standard deviation 
    2023         const float penaltyOld = EvalPvsPenalty((int)totalPvs, lowerPvsLimit, upperPvsLimit); 
    2024     const float penaltyFront = EvalPvsPenalty((int)pvsFront, lowerPvsLimit, upperPvsLimit); 
    2025         const float penaltyBack = EvalPvsPenalty((int)pvsBack, lowerPvsLimit, upperPvsLimit); 
    2026                          
    2027         const float oldRenderCost = pOverall * penaltyOld; 
    2028         const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack; 
    2029  
    2030         float oldCost, newCost; 
    2031  
    2032         // only render cost 
    2033         if (1) 
    2034         { 
    2035                 oldCost = oldRenderCost; 
    2036                 newCost = newRenderCost; 
    2037         } 
    2038         else // also considering standard deviation 
    2039         { 
    2040                 // standard deviation is difference of back and front pvs 
    2041                 const float expectedCost = 0.5f * (penaltyFront + penaltyBack); 
    2042  
    2043                 const float newDeviation = 0.5f *  
    2044                         fabs(penaltyFront - expectedCost) + fabs(penaltyBack - expectedCost); 
    2045  
    2046                 const float oldDeviation = penaltyOld; 
    2047  
    2048                 newCost = mRenderCostWeight * newRenderCost + (1.0f - mRenderCostWeight) * newDeviation; 
    2049                 oldCost = mRenderCostWeight * oldRenderCost + (1.0f - mRenderCostWeight) * oldDeviation; 
    2050         } 
    2051  
    2052         cost += mPvsFactor * newCost / (oldCost + Limits::Small); 
    2053                  
    2054  
    2055 #ifdef _DEBUG 
    2056         Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 
    2057                   << " frontpvs: " << pvsFront << " pFront: " << pFront 
    2058                   << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 
    2059         Debug << "cost: " << cost << endl; 
    2060 #endif 
    2061  
    2062         return cost; 
    2063 } 
    2064  
    2065  
    2066 int VspBspTree::ComputeBoxIntersections(const AxisAlignedBox3 &box,  
    2067                                                                                 ViewCellContainer &viewCells) const 
    2068 { 
    2069         stack<bspNodePair> nodeStack; 
    2070         BspNodeGeometry *rgeom = new BspNodeGeometry(); 
    2071  
    2072         ConstructGeometry(mRoot, *rgeom); 
    2073  
    2074         nodeStack.push(bspNodePair(mRoot, rgeom)); 
    2075    
    2076         ViewCell::NewMail(); 
    2077  
    2078         while (!nodeStack.empty())  
    2079         { 
    2080                 BspNode *node = nodeStack.top().first; 
    2081                 BspNodeGeometry *geom = nodeStack.top().second; 
    2082                 nodeStack.pop(); 
    2083  
    2084                 const int side = geom->ComputeIntersection(box); 
    2085                  
    2086                 switch (side) 
    2087                 { 
    2088                 case -1: 
    2089                         // node geometry is contained in box 
    2090                         CollectViewCells(node, true, viewCells, true); 
    2091                         break; 
    2092  
    2093                 case 0: 
    2094                         if (node->IsLeaf()) 
    2095                         { 
    2096                                 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
    2097                          
    2098                                 if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid()) 
    2099                                 { 
    2100                                         leaf->GetViewCell()->Mail(); 
    2101                                         viewCells.push_back(leaf->GetViewCell()); 
    2102                                 } 
    2103                         } 
    2104                         else  
    2105                         { 
    2106                                 BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    2107                          
    2108                                 BspNode *first = interior->GetFront(); 
    2109                                 BspNode *second = interior->GetBack(); 
    2110              
    2111                                 BspNodeGeometry *firstGeom = new BspNodeGeometry(); 
    2112                                 BspNodeGeometry *secondGeom = new BspNodeGeometry(); 
    2113  
    2114                                 geom->SplitGeometry(*firstGeom, 
    2115                                                                         *secondGeom, 
    2116                                                                         interior->GetPlane(), 
    2117                                                                         mBox, 
    2118                                                                         //0.0000001f); 
    2119                                                                         mEpsilon); 
    2120  
    2121                                 nodeStack.push(bspNodePair(first, firstGeom)); 
    2122                                 nodeStack.push(bspNodePair(second, secondGeom)); 
    2123                         } 
    2124                          
    2125                         break; 
    2126                 default: 
    2127                         // default: cull 
    2128                         break; 
    2129                 } 
    2130                  
    2131                 DEL_PTR(geom); 
    2132                  
    2133         } 
    2134  
    2135         return (int)viewCells.size(); 
    2136 } 
    2137  
    2138  
    2139 float VspBspTree::EvalAxisAlignedSplitCost(const VspBspTraversalData &data, 
    2140                                                                                    const AxisAlignedBox3 &box, 
    2141                                                                                    const int axis, 
    2142                                                                                    const float &position,                                                                                  
    2143                                                                                    float &pFront, 
    2144                                                                                    float &pBack) const 
     1012 
     1013float VspOspTree::EvalSplitCost(const VspOspTraversalData &data, 
     1014                                                                const AxisAlignedBox3 &box, 
     1015                                                                const int axis, 
     1016                                                                const float &position,                                                                             
     1017                                                                float &pFront, 
     1018                                                                float &pBack) const 
    21451019{ 
    21461020        float pvsTotal = 0; 
     
    21581032        for(rit = data.mRays->begin(); rit != rit_end; ++ rit) 
    21591033        { 
    2160                 //if (!(*rit).mRay->IsActive()) continue; 
    2161  
    21621034                // determine the side of this ray with respect to the plane 
    21631035                float t; 
     
    21751047                 
    21761048        pOverall = data.mProbability; 
    2177  
    2178         if (!mUseAreaForPvs) 
    2179         {   // volume 
    2180                 pBack = pFront = pOverall * 0.5f; 
    2181                  
    2182 #if 0 
    2183                 // box length substitute for probability 
    2184                 const float minBox = box.Min(axis); 
    2185                 const float maxBox = box.Max(axis); 
    2186  
    2187                 pBack = position - minBox; 
    2188                 pFront = maxBox - position; 
    2189                 pOverall = maxBox - minBox; 
    2190 #endif 
    2191         } 
    2192         else //-- area substitute for probability 
    2193         { 
    2194                 const int axis2 = (axis + 1) % 3; 
    2195                 const int axis3 = (axis + 2) % 3; 
    2196  
    2197                 const float faceArea =  
    2198                         (box.Max(axis2) - box.Min(axis2)) * 
    2199                         (box.Max(axis3) - box.Min(axis3)); 
    2200  
    2201                 pBack = pFront = pOverall * 0.5f + faceArea; 
    2202         } 
    2203  
     1049        pBack = pFront = pOverall * 0.5f; 
     1050         
     1051         
    22041052#ifdef _DEBUG 
    22051053        Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl; 
     
    22151063 
    22161064 
    2217 void VspBspTree::AddObjToPvs(Intersectable *obj, 
     1065void VspOspTree::AddObjToPvs(Intersectable *obj, 
    22181066                                                         const int cf, 
    22191067                                                         float &frontPvs, 
     
    22681116 
    22691117 
    2270 void VspBspTree::CollectLeaves(vector<BspLeaf *> &leaves,  
     1118void VspOspTree::CollectLeaves(vector<BspLeaf *> &leaves,  
    22711119                                                           const bool onlyUnmailed, 
    22721120                                                           const int maxPvsSize) const 
     
    23021150 
    23031151 
    2304 AxisAlignedBox3 VspBspTree::GetBoundingBox() const 
     1152AxisAlignedBox3 VspOspTree::GetBoundingBox() const 
    23051153{ 
    23061154        return mBox; 
     
    23081156 
    23091157 
    2310 BspNode *VspBspTree::GetRoot() const 
     1158BspNode *VspOspTree::GetRoot() const 
    23111159{ 
    23121160        return mRoot; 
     
    23141162 
    23151163 
    2316 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 
     1164void VspOspTree::EvaluateLeafStats(const VspOspTraversalData &data) 
    23171165{ 
    23181166        // the node became a leaf -> evaluate stats for leafs 
     
    23701218 
    23711219 
    2372 int VspBspTree::CastRay(Ray &ray) 
     1220int VspOspTree::CastRay(Ray &ray) 
    23731221{ 
    23741222        int hits = 0; 
     
    24391287                        if (!leaf->GetViewCell()->Mailed()) 
    24401288                        { 
    2441                                 //ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf)); 
     1289                                //ray.bspIntersections.push_back(Ray::VspOspIntersection(maxt, leaf)); 
    24421290                                leaf->GetViewCell()->Mail(); 
    24431291                                ++ hits; 
     
    24681316 
    24691317 
    2470 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const 
     1318void VspOspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const 
    24711319{ 
    24721320        ViewCell::NewMail(); 
     
    24761324 
    24771325 
    2478 void VspBspTree::CollapseViewCells() 
     1326void VspOspTree::CollapseViewCells() 
    24791327{ 
    24801328// TODO 
     
    25311379 
    25321380 
    2533 void VspBspTree::CollectRays(VssRayContainer &rays) 
     1381void VspOspTree::CollectRays(VssRayContainer &rays) 
    25341382{ 
    25351383        vector<BspLeaf *> leaves; 
     
    25481396 
    25491397 
    2550 void VspBspTree::ValidateTree() 
     1398void VspOspTree::ValidateTree() 
    25511399{ 
    25521400        stack<BspNode *> nodeStack; 
     
    25911439 
    25921440 
    2593 void VspBspTree::CollectViewCells(BspNode *root, 
     1441void VspOspTree::CollectViewCells(BspNode *root, 
    25941442                                                                  bool onlyValid, 
    25951443                                                                  ViewCellContainer &viewCells, 
     
    26351483 
    26361484 
    2637 void VspBspTree::PreprocessPolygons(PolygonContainer &polys) 
    2638 { 
    2639         // preprocess: throw out polygons coincident to the view space box (not needed) 
    2640         PolygonContainer boxPolys; 
    2641         mBox.ExtractPolys(boxPolys); 
    2642         vector<Plane3> boxPlanes; 
    2643  
    2644         PolygonContainer::iterator pit, pit_end = boxPolys.end(); 
    2645  
    2646         // extract planes of box 
    2647         // TODO: can be done more elegantly than first extracting polygons 
    2648         // and take their planes 
    2649         for (pit = boxPolys.begin(); pit != pit_end; ++ pit) 
    2650         { 
    2651                 boxPlanes.push_back((*pit)->GetSupportingPlane()); 
    2652         } 
    2653  
    2654         pit_end = polys.end(); 
    2655  
    2656         for (pit = polys.begin(); pit != pit_end; ++ pit) 
    2657         { 
    2658                 vector<Plane3>::const_iterator bit, bit_end = boxPlanes.end(); 
    2659                  
    2660                 for (bit = boxPlanes.begin(); (bit != bit_end) && (*pit); ++ bit) 
    2661                 { 
    2662                         const int cf = (*pit)->ClassifyPlane(*bit, mEpsilon); 
    2663  
    2664                         if (cf == Polygon3::COINCIDENT) 
    2665                         { 
    2666                                 DEL_PTR(*pit); 
    2667                                 //Debug << "coincident!!" << endl; 
    2668                         } 
    2669                 } 
    2670         } 
    2671  
    2672         // remove deleted entries 
    2673         for (int i = 0; i < (int)polys.size(); ++ i) 
    2674         { 
    2675                 while (!polys[i] && (i < (int)polys.size())) 
    2676                 { 
    2677                         swap(polys[i], polys.back()); 
    2678                         polys.pop_back(); 
    2679                 } 
    2680         } 
    2681 } 
    2682  
    2683  
    2684 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const 
    2685 { 
    2686         float len = 0; 
    2687  
    2688         RayInfoContainer::const_iterator it, it_end = rays.end(); 
    2689  
    2690         for (it = rays.begin(); it != it_end; ++ it) 
    2691                 len += (*it).SegmentLength(); 
    2692  
    2693         return len; 
    2694 } 
    2695  
    2696  
    2697 int VspBspTree::SplitRays(const Plane3 &plane, 
     1485int VspOspTree::SplitRays(const Plane3 &plane, 
    26981486                                                  RayInfoContainer &rays, 
    26991487                                                  RayInfoContainer &frontRays, 
     
    27251513                        { 
    27261514                                //-- split ray 
    2727                                 //  test if start point behind or in front of plane 
     1515                                //-- test if start point behind or in front of plane 
    27281516                                const int side = plane.Side(bRay.ExtrapOrigin()); 
    27291517 
     
    27501538 
    27511539 
    2752 void VspBspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const 
    2753 { 
    2754         BspNode *lastNode; 
    2755  
    2756         do 
    2757         { 
    2758                 lastNode = n; 
    2759  
    2760                 // want to get planes defining geometry of this node => don't take 
    2761                 // split plane of node itself 
    2762                 n = n->GetParent(); 
    2763  
    2764                 if (n) 
    2765                 { 
    2766                         BspInterior *interior = dynamic_cast<BspInterior *>(n); 
    2767                         Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 
    2768  
    2769             if (interior->GetBack() != lastNode) 
    2770                                 halfSpace.ReverseOrientation(); 
    2771  
    2772                         halfSpaces.push_back(halfSpace); 
    2773                 } 
    2774         } 
    2775         while (n); 
    2776 } 
    2777  
    2778  
    2779 void VspBspTree::ConstructGeometry(BspNode *n, 
    2780                                                                    BspNodeGeometry &geom) const 
    2781 { 
    2782         vector<Plane3> halfSpaces; 
    2783         ExtractHalfSpaces(n, halfSpaces); 
    2784  
    2785         PolygonContainer candidatePolys; 
    2786         vector<Plane3> candidatePlanes; 
    2787  
    2788         vector<Plane3>::const_iterator pit, pit_end = halfSpaces.end(); 
    2789  
    2790         // bounded planes are added to the polygons 
    2791         for (pit = halfSpaces.begin(); pit != pit_end; ++ pit) 
    2792         { 
    2793                 Polygon3 *p = GetBoundingBox().CrossSection(*pit); 
    2794  
    2795                 if (p->Valid(mEpsilon)) 
    2796                 { 
    2797                         candidatePolys.push_back(p); 
    2798                         candidatePlanes.push_back(*pit); 
    2799                 } 
    2800         } 
    2801  
    2802         // add faces of bounding box (also could be faces of the cell) 
    2803         for (int i = 0; i < 6; ++ i) 
    2804         { 
    2805                 VertexContainer vertices; 
    2806  
    2807                 for (int j = 0; j < 4; ++ j) 
    2808                         vertices.push_back(mBox.GetFace(i).mVertices[j]); 
    2809  
    2810                 Polygon3 *poly = new Polygon3(vertices); 
    2811  
    2812                 candidatePolys.push_back(poly); 
    2813                 candidatePlanes.push_back(poly->GetSupportingPlane()); 
    2814         } 
    2815  
    2816         for (int i = 0; i < (int)candidatePolys.size(); ++ i) 
    2817         { 
    2818                 // polygon is split by all other planes 
    2819                 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 
    2820                 { 
    2821                         if (i == j) // polygon and plane are coincident 
    2822                                 continue; 
    2823  
    2824                         VertexContainer splitPts; 
    2825                         Polygon3 *frontPoly, *backPoly; 
    2826  
    2827                         const int cf = 
    2828                                 candidatePolys[i]->ClassifyPlane(halfSpaces[j], 
    2829                                                                                                  mEpsilon); 
    2830  
    2831                         switch (cf) 
    2832                         { 
    2833                                 case Polygon3::SPLIT: 
    2834                                         frontPoly = new Polygon3(); 
    2835                                         backPoly = new Polygon3(); 
    2836  
    2837                                         candidatePolys[i]->Split(halfSpaces[j], 
    2838                                                                                          *frontPoly, 
    2839                                                                                          *backPoly, 
    2840                                                                                          mEpsilon); 
    2841  
    2842                                         DEL_PTR(candidatePolys[i]); 
    2843  
    2844                                         if (backPoly->Valid(mEpsilon)) 
    2845                                                 candidatePolys[i] = backPoly; 
    2846                                         else 
    2847                                                 DEL_PTR(backPoly); 
    2848  
    2849                                         // outside, don't need this 
    2850                                         DEL_PTR(frontPoly); 
    2851                                         break; 
    2852                                 // polygon outside of halfspace 
    2853                                 case Polygon3::FRONT_SIDE: 
    2854                                         DEL_PTR(candidatePolys[i]); 
    2855                                         break; 
    2856                                 // just take polygon as it is 
    2857                                 case Polygon3::BACK_SIDE: 
    2858                                 case Polygon3::COINCIDENT: 
    2859                                 default: 
    2860                                         break; 
    2861                         } 
    2862                 } 
    2863  
    2864                 if (candidatePolys[i]) 
    2865                 { 
    2866                         geom.Add(candidatePolys[i], candidatePlanes[i]); 
    2867                         //      geom.mPolys.push_back(candidates[i]); 
    2868                 } 
    2869         } 
    2870 } 
    2871  
    2872  
    2873 void VspBspTree::ConstructGeometry(ViewCell *vc,  
    2874                                                                    BspNodeGeometry &vcGeom) const 
    2875 { 
    2876         ViewCellContainer leaves; 
    2877          
    2878         mViewCellsTree->CollectLeaves(vc, leaves); 
    2879  
    2880         ViewCellContainer::const_iterator it, it_end = leaves.end(); 
    2881  
    2882         for (it = leaves.begin(); it != it_end; ++ it) 
    2883         { 
    2884                 BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf; 
    2885                  
    2886                 ConstructGeometry(l, vcGeom); 
    2887         } 
    2888 } 
    2889  
    2890  
    2891 int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
     1540int VspOspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
    28921541                                                          const bool onlyUnmailed) const 
    28931542{ 
    2894         stack<bspNodePair> nodeStack; 
    2895          
    2896         BspNodeGeometry nodeGeom; 
    2897         ConstructGeometry(n, nodeGeom); 
    2898 //      const float eps = 0.5f; 
    2899         const float eps = 0.01f; 
    2900         // split planes from the root to this node 
    2901         // needed to verify that we found neighbor leaf 
    2902         // TODO: really needed? 
    2903         vector<Plane3> halfSpaces; 
    2904         ExtractHalfSpaces(n, halfSpaces); 
    2905  
    2906  
    2907         BspNodeGeometry *rgeom = new BspNodeGeometry(); 
    2908         ConstructGeometry(mRoot, *rgeom); 
    2909  
    2910         nodeStack.push(bspNodePair(mRoot, rgeom)); 
    2911  
    2912         while (!nodeStack.empty()) 
    2913         { 
    2914                 BspNode *node = nodeStack.top().first; 
    2915                 BspNodeGeometry *geom = nodeStack.top().second; 
    2916          
    2917                 nodeStack.pop(); 
    2918  
    2919                 if (node->IsLeaf()) 
    2920                 { 
    2921                         // test if this leaf is in valid view space 
    2922                         if (node->TreeValid() && 
    2923                                 (node != n) &&  
    2924                                 (!onlyUnmailed || !node->Mailed())) 
    2925                         { 
    2926                                 bool isAdjacent = true; 
    2927  
    2928                                 if (1) 
    2929                                 { 
    2930                                         // test all planes of current node if still adjacent 
    2931                                         for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i) 
    2932                                         { 
    2933                                                 const int cf = 
    2934                                                         Polygon3::ClassifyPlane(geom->GetPolys(), 
    2935                                                                                                         halfSpaces[i], 
    2936                                                                                                         eps); 
    2937  
    2938                                                 if (cf == Polygon3::FRONT_SIDE) 
    2939                                                 { 
    2940                                                         isAdjacent = false; 
    2941                                                 } 
    2942                                         } 
    2943                                 } 
    2944                                 else 
    2945                                 { 
    2946                                         // TODO: why is this wrong?? 
    2947                                         // test all planes of current node if still adjacent 
    2948                                         for (int i = 0; (i < nodeGeom.Size()) && isAdjacent; ++ i) 
    2949                                         { 
    2950                                                 Polygon3 *poly = nodeGeom.GetPolys()[i]; 
    2951  
    2952                                                 const int cf = 
    2953                                                         Polygon3::ClassifyPlane(geom->GetPolys(), 
    2954                                                                                                         poly->GetSupportingPlane(), 
    2955                                                                                                         eps); 
    2956  
    2957                                                 if (cf == Polygon3::FRONT_SIDE) 
    2958                                                 { 
    2959                                                         isAdjacent = false; 
    2960                                                 } 
    2961                                         } 
    2962                                 } 
    2963                                 // neighbor was found 
    2964                                 if (isAdjacent) 
    2965                                 {        
    2966                                         neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 
    2967                                 } 
    2968                         } 
    2969                 } 
    2970                 else 
    2971                 { 
    2972                         BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    2973  
    2974                         const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(), 
    2975                                                                                                    interior->GetPlane(), 
    2976                                                                                                    eps); 
    2977                          
    2978                         BspNode *front = interior->GetFront(); 
    2979                         BspNode *back = interior->GetBack(); 
    2980              
    2981                         BspNodeGeometry *fGeom = new BspNodeGeometry(); 
    2982                         BspNodeGeometry *bGeom = new BspNodeGeometry(); 
    2983  
    2984                         geom->SplitGeometry(*fGeom, 
    2985                                                                 *bGeom, 
    2986                                                                 interior->GetPlane(), 
    2987                                                                 mBox, 
    2988                                                                 //0.0000001f); 
    2989                                                                 eps); 
    2990                  
    2991                         if (cf == Polygon3::BACK_SIDE) 
    2992                         { 
    2993                                 nodeStack.push(bspNodePair(interior->GetBack(), bGeom)); 
    2994                                 DEL_PTR(fGeom); 
    2995                         } 
    2996                         else 
    2997                         { 
    2998                                 if (cf == Polygon3::FRONT_SIDE) 
    2999                                 { 
    3000                                         nodeStack.push(bspNodePair(interior->GetFront(), fGeom)); 
    3001                                         DEL_PTR(bGeom); 
    3002                                 } 
    3003                                 else 
    3004                                 {       // random decision 
    3005                                         nodeStack.push(bspNodePair(front, fGeom)); 
    3006                                         nodeStack.push(bspNodePair(back, bGeom)); 
    3007                                 } 
    3008                         } 
    3009                 } 
    3010          
    3011                 DEL_PTR(geom); 
    3012         } 
    3013  
    3014         return (int)neighbors.size(); 
    3015 } 
    3016  
    3017  
    3018  
    3019 int VspBspTree::FindApproximateNeighbors(BspNode *n,  
    3020                                                                                  vector<BspLeaf *> &neighbors, 
    3021                                                                                  const bool onlyUnmailed) const 
    3022 { 
    3023         stack<bspNodePair> nodeStack; 
    3024          
    3025         BspNodeGeometry nodeGeom; 
    3026         ConstructGeometry(n, nodeGeom); 
    3027          
    3028         float eps = 0.01f; 
    3029         // split planes from the root to this node 
    3030         // needed to verify that we found neighbor leaf 
    3031         // TODO: really needed? 
    3032         vector<Plane3> halfSpaces; 
    3033         ExtractHalfSpaces(n, halfSpaces); 
    3034  
    3035  
    3036         BspNodeGeometry *rgeom = new BspNodeGeometry(); 
    3037         ConstructGeometry(mRoot, *rgeom); 
    3038  
    3039         nodeStack.push(bspNodePair(mRoot, rgeom)); 
    3040  
    3041         while (!nodeStack.empty()) 
    3042         { 
    3043                 BspNode *node = nodeStack.top().first; 
    3044                 BspNodeGeometry *geom = nodeStack.top().second; 
    3045          
    3046                 nodeStack.pop(); 
    3047  
    3048                 if (node->IsLeaf()) 
    3049                 { 
    3050                         // test if this leaf is in valid view space 
    3051                         if (node->TreeValid() && 
    3052                                 (node != n) &&  
    3053                                 (!onlyUnmailed || !node->Mailed())) 
    3054                         { 
    3055                                 bool isAdjacent = true; 
    3056  
    3057                                 // neighbor was found 
    3058                                 if (isAdjacent) 
    3059                                 {        
    3060                                         neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 
    3061                                 } 
    3062                         } 
    3063                 } 
    3064                 else 
    3065                 { 
    3066                         BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    3067  
    3068                         const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(), 
    3069                                                                                                    interior->GetPlane(), 
    3070                                                                                                    eps); 
    3071                          
    3072                         BspNode *front = interior->GetFront(); 
    3073                         BspNode *back = interior->GetBack(); 
    3074              
    3075                         BspNodeGeometry *fGeom = new BspNodeGeometry(); 
    3076                         BspNodeGeometry *bGeom = new BspNodeGeometry(); 
    3077  
    3078                         geom->SplitGeometry(*fGeom, 
    3079                                                                 *bGeom, 
    3080                                                                 interior->GetPlane(), 
    3081                                                                 mBox, 
    3082                                                                 //0.0000001f); 
    3083                                                                 eps); 
    3084                  
    3085                         if (cf == Polygon3::BACK_SIDE) 
    3086                         { 
    3087                                 nodeStack.push(bspNodePair(interior->GetBack(), bGeom)); 
    3088                                 DEL_PTR(fGeom); 
    3089                                 } 
    3090                         else 
    3091                         { 
    3092                                 if (cf == Polygon3::FRONT_SIDE) 
    3093                                 { 
    3094                                         nodeStack.push(bspNodePair(interior->GetFront(), fGeom)); 
    3095                                         DEL_PTR(bGeom); 
    3096                                 } 
    3097                                 else 
    3098                                 {       // random decision 
    3099                                         nodeStack.push(bspNodePair(front, fGeom)); 
    3100                                         nodeStack.push(bspNodePair(back, bGeom)); 
    3101                                 } 
    3102                         } 
    3103                 } 
    3104          
    3105                 DEL_PTR(geom); 
    3106         } 
    3107  
    3108         return (int)neighbors.size(); 
    3109 } 
    3110  
    3111  
    3112  
    3113 BspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace) 
    3114 { 
     1543        // TODO 
     1544        return 0; 
     1545} 
     1546 
     1547 
     1548BspLeaf *VspOspTree::GetRandomLeaf(const Plane3 &halfspace) 
     1549{ 
     1550#if TODO 
    31151551    stack<BspNode *> nodeStack; 
    31161552        nodeStack.push(mRoot); 
     
    31571593                } 
    31581594        } 
    3159  
     1595#endif 
    31601596        return NULL; 
    31611597} 
    31621598 
    31631599 
    3164 BspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed) 
     1600BspLeaf *VspOspTree::GetRandomLeaf(const bool onlyUnmailed) 
    31651601{ 
    31661602        stack<BspNode *> nodeStack; 
     
    31981634 
    31991635 
    3200 int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const 
     1636int VspOspTree::ComputePvsSize(const RayInfoContainer &rays) const 
    32011637{ 
    32021638        int pvsSize = 0; 
     
    32321668 
    32331669 
    3234 float VspBspTree::GetEpsilon() const 
     1670float VspOspTree::GetEpsilon() const 
    32351671{ 
    32361672        return mEpsilon; 
     
    32381674 
    32391675 
    3240 int VspBspTree::SplitPolygons(const Plane3 &plane, 
    3241                                                           PolygonContainer &polys, 
    3242                                                           PolygonContainer &frontPolys, 
    3243                                                           PolygonContainer &backPolys, 
    3244                                                           PolygonContainer &coincident) const 
    3245 { 
    3246         int splits = 0; 
    3247  
    3248         PolygonContainer::const_iterator it, it_end = polys.end(); 
    3249  
    3250         for (it = polys.begin(); it != polys.end(); ++ it)       
    3251         { 
    3252                 Polygon3 *poly = *it; 
    3253  
    3254                 // classify polygon 
    3255                 const int cf = poly->ClassifyPlane(plane, mEpsilon); 
    3256  
    3257                 switch (cf) 
    3258                 { 
    3259                         case Polygon3::COINCIDENT: 
    3260                                 coincident.push_back(poly); 
    3261                                 break; 
    3262                         case Polygon3::FRONT_SIDE: 
    3263                                 frontPolys.push_back(poly); 
    3264                                 break; 
    3265                         case Polygon3::BACK_SIDE: 
    3266                                 backPolys.push_back(poly); 
    3267                                 break; 
    3268                         case Polygon3::SPLIT: 
    3269                                 backPolys.push_back(poly); 
    3270                                 frontPolys.push_back(poly); 
    3271                                 ++ splits; 
    3272                                 break; 
    3273                         default: 
    3274                 Debug << "SHOULD NEVER COME HERE\n"; 
    3275                                 break; 
    3276                 } 
    3277         } 
    3278  
    3279         return splits; 
    3280 } 
    3281  
    3282  
    3283 int VspBspTree::CastLineSegment(const Vector3 &origin, 
     1676 
     1677int VspOspTree::CastLineSegment(const Vector3 &origin, 
    32841678                                                                const Vector3 &termination, 
    32851679                                                                ViewCellContainer &viewcells) 
     
    33871781 
    33881782 
    3389  
    3390 int VspBspTree::TreeDistance(BspNode *n1, BspNode *n2) const 
    3391 { 
    3392         std::deque<BspNode *> path1; 
    3393         BspNode *p1 = n1; 
    3394  
    3395         // create path from node 1 to root 
    3396         while (p1) 
    3397         { 
    3398                 if (p1 == n2) // second node on path 
    3399                         return (int)path1.size(); 
    3400  
    3401                 path1.push_front(p1); 
    3402                 p1 = p1->GetParent(); 
    3403         } 
    3404  
    3405         int depth = n2->GetDepth(); 
    3406         int d = depth; 
    3407  
    3408         BspNode *p2 = n2; 
    3409  
    3410         // compare with same depth 
    3411         while (1) 
    3412         { 
    3413                 if ((d < (int)path1.size()) && (p2 == path1[d])) 
    3414                         return (depth - d) + ((int)path1.size() - 1 - d); 
    3415  
    3416                 -- d; 
    3417                 p2 = p2->GetParent(); 
    3418         } 
    3419  
    3420         return 0; // never come here 
    3421 } 
    3422  
    3423  
    3424 BspNode *VspBspTree::CollapseTree(BspNode *node, int &collapsed) 
     1783BspNode *VspOspTree::CollapseTree(BspNode *node, int &collapsed) 
    34251784{ 
    34261785// TODO 
     
    34641823 
    34651824 
    3466 int VspBspTree::CollapseTree() 
     1825int VspOspTree::CollapseTree() 
    34671826{ 
    34681827        int collapsed = 0; 
     
    34781837 
    34791838 
    3480 void VspBspTree::RepairViewCellsLeafLists() 
     1839void VspOspTree::RepairViewCellsLeafLists() 
    34811840{ 
    34821841// TODO 
     
    35211880 
    35221881 
    3523 typedef pair<BspNode *, BspNodeGeometry *> bspNodePair; 
    3524  
    3525  
    3526 int VspBspTree::CastBeam(Beam &beam) 
    3527 { 
    3528     stack<bspNodePair> nodeStack; 
    3529         BspNodeGeometry *rgeom = new BspNodeGeometry(); 
    3530         ConstructGeometry(mRoot, *rgeom); 
    3531  
    3532         nodeStack.push(bspNodePair(mRoot, rgeom)); 
    3533    
    3534         ViewCell::NewMail(); 
    3535  
    3536         while (!nodeStack.empty())  
    3537         { 
    3538                 BspNode *node = nodeStack.top().first; 
    3539                 BspNodeGeometry *geom = nodeStack.top().second; 
    3540                 nodeStack.pop(); 
    3541                  
    3542                 AxisAlignedBox3 box; 
    3543                 geom->GetBoundingBox(box); 
    3544  
    3545                 const int side = beam.ComputeIntersection(box); 
    3546                  
    3547                 switch (side)  
    3548                 { 
    3549                 case -1: 
    3550                         CollectViewCells(node, true, beam.mViewCells, true); 
    3551                         break; 
    3552                 case 0: 
    3553                          
    3554                         if (node->IsLeaf()) 
    3555                         { 
    3556                                 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
    3557                          
    3558                                 if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid()) 
    3559                                 { 
    3560                                         leaf->GetViewCell()->Mail(); 
    3561                                         beam.mViewCells.push_back(leaf->GetViewCell()); 
    3562                                 } 
    3563                         } 
    3564                         else  
    3565                         { 
    3566                                 BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    3567                          
    3568                                 BspNode *first = interior->GetFront(); 
    3569                                 BspNode *second = interior->GetBack(); 
    3570              
    3571                                 BspNodeGeometry *firstGeom = new BspNodeGeometry(); 
    3572                                 BspNodeGeometry *secondGeom = new BspNodeGeometry(); 
    3573  
    3574                                 geom->SplitGeometry(*firstGeom, 
    3575                                                                         *secondGeom, 
    3576                                                                         interior->GetPlane(), 
    3577                                                                         mBox, 
    3578                                                                         //0.0000001f); 
    3579                                                                         mEpsilon); 
    3580  
    3581                                 // decide on the order of the nodes 
    3582                                 if (DotProd(beam.mPlanes[0].mNormal,  
    3583                                         interior->GetPlane().mNormal) > 0) 
    3584                                 { 
    3585                                         swap(first, second); 
    3586                                         swap(firstGeom, secondGeom); 
    3587                                 } 
    3588  
    3589                                 nodeStack.push(bspNodePair(first, firstGeom)); 
    3590                                 nodeStack.push(bspNodePair(second, secondGeom)); 
    3591                         } 
    3592                          
    3593                         break; 
    3594                 default: 
    3595                         // default: cull 
    3596                         break; 
    3597                 } 
    3598                  
    3599                 DEL_PTR(geom); 
    3600                  
    3601         } 
    3602  
    3603         return (int)beam.mViewCells.size(); 
    3604 } 
    3605  
    3606  
    3607 void VspBspTree::SetViewCellsManager(ViewCellsManager *vcm) 
    3608 { 
    3609         mViewCellsManager = vcm; 
    3610 } 
    3611  
    3612  
    3613 int VspBspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves, 
    3614                                                                            vector<MergeCandidate> &candidates) 
    3615 { 
    3616         BspLeaf::NewMail(); 
    3617          
    3618         vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 
    3619  
    3620         int numCandidates = 0; 
    3621  
    3622         // find merge candidates and push them into queue 
    3623         for (it = leaves.begin(); it != it_end; ++ it) 
    3624         { 
    3625                 BspLeaf *leaf = *it; 
    3626                  
    3627                 // the same leaves must not be part of two merge candidates 
    3628                 leaf->Mail(); 
    3629                  
    3630                 vector<BspLeaf *> neighbors; 
    3631                  
    3632                 // appoximate neighbor search has slightl relaxed constraints 
    3633                 if (1) 
    3634                         FindNeighbors(leaf, neighbors, true); 
    3635                 else 
    3636                         FindApproximateNeighbors(leaf, neighbors, true); 
    3637  
    3638                 vector<BspLeaf *>::const_iterator nit, nit_end = neighbors.end(); 
    3639  
    3640                 // TODO: test if at least one ray goes from one leaf to the other 
    3641                 for (nit = neighbors.begin(); nit != nit_end; ++ nit) 
    3642                 { 
    3643                         if ((*nit)->GetViewCell() != leaf->GetViewCell()) 
    3644                         { 
    3645                                 MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell()); 
    3646  
    3647                                 // dont't merge view cells if they are empty and not front and back leaf of the same parent 
    3648                                 // in the tree? 
    3649                                 if (mEmptyViewCellsMergeAllowed || 
    3650                                         !leaf->GetViewCell()->GetPvs().Empty() ||  
    3651                                         !(*nit)->GetViewCell()->GetPvs().Empty() || 
    3652                     leaf->IsSibling(*nit)) 
    3653                                 { 
    3654                                         candidates.push_back(mc); 
    3655                                 } 
    3656  
    3657                                 ++ numCandidates; 
    3658                                 if ((numCandidates % 1000) == 0) 
    3659                                 { 
    3660                                         cout << "collected " << numCandidates << " merge candidates" << endl; 
    3661                                 } 
    3662                         } 
    3663                 } 
    3664         } 
    3665  
    3666         Debug << "merge queue: " << (int)candidates.size() << endl; 
    3667         Debug << "leaves in queue: " << numCandidates << endl; 
    3668          
    3669  
    3670         return (int)leaves.size(); 
    3671 } 
    3672  
    3673  
    3674 int VspBspTree::CollectMergeCandidates(const VssRayContainer &rays,  
    3675                                                                            vector<MergeCandidate> &candidates) 
    3676 { 
    3677         ViewCell::NewMail(); 
    3678         long startTime = GetTime(); 
    3679          
    3680         map<BspLeaf *, vector<BspLeaf*> > neighborMap; 
    3681         ViewCellContainer::const_iterator iit; 
    3682  
    3683         int numLeaves = 0; 
    3684          
    3685         BspLeaf::NewMail(); 
    3686  
    3687         for (int i = 0; i < (int)rays.size(); ++ i) 
    3688         {   
    3689                 VssRay *ray = rays[i]; 
    3690          
    3691                 // traverse leaves stored in the rays and compare and  
    3692                 // merge consecutive leaves (i.e., the neighbors in the tree) 
    3693                 if (ray->mViewCells.size() < 2) 
    3694                         continue; 
    3695 //TODO viewcellhierarchy 
    3696                 iit = ray->mViewCells.begin(); 
    3697                 BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*(iit ++)); 
    3698                 BspLeaf *leaf = bspVc->mLeaf; 
    3699                  
    3700                 // traverse intersections  
    3701                 // consecutive leaves are neighbors => add them to queue 
    3702                 for (; iit != ray->mViewCells.end(); ++ iit) 
    3703                 { 
    3704                         // next pair 
    3705                         BspLeaf *prevLeaf = leaf; 
    3706                         bspVc = dynamic_cast<BspViewCell *>(*iit); 
    3707             leaf = bspVc->mLeaf; 
    3708  
    3709                         // view space not valid or same view cell 
    3710                         if (!leaf->TreeValid() || !prevLeaf->TreeValid() || 
    3711                                 (leaf->GetViewCell() == prevLeaf->GetViewCell())) 
    3712                                 continue; 
    3713  
    3714                 vector<BspLeaf *> &neighbors = neighborMap[leaf]; 
    3715                          
    3716                         bool found = false; 
    3717  
    3718                         // both leaves inserted in queue already => 
    3719                         // look if double pair already exists 
    3720                         if (leaf->Mailed() && prevLeaf->Mailed()) 
    3721                         { 
    3722                                 vector<BspLeaf *>::const_iterator it, it_end = neighbors.end(); 
    3723                                  
    3724                 for (it = neighbors.begin(); !found && (it != it_end); ++ it) 
    3725                                         if (*it == prevLeaf) 
    3726                                                 found = true; // already in queue 
    3727                         } 
    3728                  
    3729                         if (!found) 
    3730                         { 
    3731                                 // this pair is not in map yet 
    3732                                 // => insert into the neighbor map and the queue 
    3733                                 neighbors.push_back(prevLeaf); 
    3734                                 neighborMap[prevLeaf].push_back(leaf); 
    3735  
    3736                                 leaf->Mail(); 
    3737                                 prevLeaf->Mail(); 
    3738                  
    3739                                 MergeCandidate mc(leaf->GetViewCell(), prevLeaf->GetViewCell()); 
    3740                                  
    3741                                 candidates.push_back(mc); 
    3742  
    3743                                 if (((int)candidates.size() % 1000) == 0) 
    3744                                 { 
    3745                                         cout << "collected " << (int)candidates.size() << " merge candidates" << endl; 
    3746                                 } 
    3747                         } 
    3748         } 
    3749         } 
    3750  
    3751         Debug << "neighbormap size: " << (int)neighborMap.size() << endl; 
    3752         Debug << "merge queue: " << (int)candidates.size() << endl; 
    3753         Debug << "leaves in queue: " << numLeaves << endl; 
    3754  
    3755  
    3756         //-- collect the leaves which haven't been found by ray casting 
    3757         if (0) 
    3758         { 
    3759                 cout << "finding additional merge candidates using geometry" << endl; 
    3760                 vector<BspLeaf *> leaves; 
    3761                 CollectLeaves(leaves, true); 
    3762                 Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 
    3763                 CollectMergeCandidates(leaves, candidates); 
    3764         } 
    3765  
    3766         return numLeaves; 
    3767 } 
    3768  
    3769  
    3770  
    3771  
    3772 ViewCell *VspBspTree::GetViewCell(const Vector3 &point, const bool active) 
     1882 
     1883ViewCell *VspOspTree::GetViewCell(const Vector3 &point, const bool active) 
    37731884{ 
    37741885        if (mRoot == NULL) 
     
    38091920 
    38101921 
    3811 bool VspBspTree::ViewPointValid(const Vector3 &viewPoint) const 
     1922bool VspOspTree::ViewPointValid(const Vector3 &viewPoint) const 
    38121923{ 
    38131924        BspNode *node = mRoot; 
     
    38391950 
    38401951 
    3841 void VspBspTree::PropagateUpValidity(BspNode *node) 
     1952void VspOspTree::PropagateUpValidity(BspNode *node) 
    38421953{ 
    38431954        const bool isValid = node->TreeValid(); 
     
    38681979 
    38691980#if ZIPPED_VIEWCELLS 
    3870 bool VspBspTree::Export(ogzstream &stream) 
     1981bool VspOspTree::Export(ogzstream &stream) 
    38711982#else 
    3872 bool VspBspTree::Export(ofstream &stream) 
     1983bool VspOspTree::Export(ofstream &stream) 
    38731984#endif 
    38741985{ 
     
    38781989} 
    38791990 
     1991 
    38801992#if ZIPPED_VIEWCELLS 
    3881 void VspBspTree::ExportNode(BspNode *node, ogzstream &stream) 
     1993void VspOspTree::ExportNode(BspNode *node, ogzstream &stream) 
    38821994#else 
    3883 void VspBspTree::ExportNode(BspNode *node, ofstream &stream) 
     1995void VspOspTree::ExportNode(BspNode *node, ofstream &stream) 
    38841996#endif 
    38851997{ 
Note: See TracChangeset for help on using the changeset viewer.