Changeset 448 for trunk


Ignore:
Timestamp:
12/05/05 04:42:54 (19 years ago)
Author:
mattausch
Message:

fixed bug in VspBspTree?
view cells in VssPreprocessor?
bounding rays for vspkdtree

Location:
trunk/VUT
Files:
31 edited

Legend:

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

    r439 r448  
    255255                        </File> 
    256256                        <File 
     257                                RelativePath="..\src\RssPreprocessor.cpp"> 
     258                        </File> 
     259                        <File 
     260                                RelativePath="..\src\RssPreprocessor.h"> 
     261                        </File> 
     262                        <File 
     263                                RelativePath="..\src\RssTree.cpp"> 
     264                        </File> 
     265                        <File 
     266                                RelativePath="..\src\RssTree.h"> 
     267                        </File> 
     268                        <File 
    257269                                RelativePath="..\src\SamplingPreprocessor.cpp"> 
    258270                        </File> 
  • trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env

    r445 r448  
    1919 
    2020Preprocessor { 
    21         type sampling 
    22 #       type vss 
     21#       type sampling 
     22        type vss 
    2323} 
    2424 
     
    9494 
    9595Sampling { 
    96         totalSamples 600000 
     96        totalSamples 300000 
    9797        samplesPerPass  3 
    9898} 
     
    101101        loadFromFile false 
    102102        #type kdTree 
    103         #type vspTree 
     103        type vspKdTree 
    104104        #type bspTree 
    105         type vspBspTree 
     105        #type vspBspTree 
    106106         
    107107        #type sceneDependent 
     
    131131BspTree { 
    132132        Construction { 
    133                 samples 200000 
    134                 sideTolerance 0.005 
     133                samples 50000 
     134                epsilon 0.005 
    135135        } 
    136136 
     
    193193                minRays 200 
    194194                minPolygons -1 
    195                 maxDepth 50 
     195                maxDepth 40 
    196196                minPvs 100 
    197197                minArea 0.01 
     
    256256 
    257257        Construction { 
    258                 samples 500000 
     258                samples 100000 
    259259        } 
    260260         
     
    278278VspBspTree { 
    279279        Construction { 
    280                 samples 200000 
    281                 sideTolerance 0.005 
     280                samples 100000 
     281                epsilon 0.005 
    282282        } 
    283283 
     
    309309                minRays 200 
    310310                minPolygons -1 
    311                 maxDepth 50 
     311                maxDepth 40 
    312312                minPvs 100 
    313313                minArea 0.01 
  • trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp

    r372 r448  
    16621662 
    16631663// TODO: use a table to avoid normal and distance computations 
    1664 Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) 
     1664Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const 
    16651665{ 
    16661666        Polygon3 *planePoly = new Polygon3(); 
     
    17461746        return planePoly; 
    17471747} 
     1748 
     1749bool AxisAlignedBox3::GetRaySegment(const Ray &ray,  
     1750                                                                        float &minT,  
     1751                                                                        float &maxT) const 
     1752{ 
     1753        maxT = 1e6; 
     1754        minT = 0; 
     1755         
     1756        // test with  bounding box 
     1757        if (!GetMinMaxT(ray, &minT, &maxT)) 
     1758                return false; 
     1759 
     1760        if (minT < 0) // start ray from origin 
     1761                minT = 0; 
     1762 
     1763        // bound ray or line segment 
     1764        if (//(ray.GetType() == Ray::LOCAL_RAY) &&  
     1765            !ray.intersections.empty() &&  
     1766                (ray.intersections[0].mT <= maxT)) 
     1767        { 
     1768                maxT = ray.intersections[0].mT; 
     1769        } 
     1770 
     1771        return true; 
     1772} 
  • trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h

    r387 r448  
    312312          @returns the cross section 
    313313  */ 
    314   Polygon3 *CrossSection(const Plane3 &plane); 
     314  Polygon3 *CrossSection(const Plane3 &plane) const; 
     315 
     316  /** Computes minimal and maximal t of ray, including the object intersections. 
     317          @returns true if ray hits the bounding box. 
     318  */ 
     319  bool GetRaySegment(const Ray &ray,  
     320                                float &minT,  
     321                                float &maxT) const; 
    315322 
    316323#define __EXTENT_HACK 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp

    r446 r448  
    12691269          "100000"); 
    12701270 
    1271   RegisterOption("BspTree.Construction.sideTolerance", 
     1271  RegisterOption("BspTree.Construction.epsilon", 
    12721272          optFloat, 
    12731273          "-bsp_construction_side_tolerance=", 
     
    17321732          "false"); 
    17331733 
    1734    RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0"); 
    1735    RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0"); 
    1736    RegisterOption("VspBspTree.Factor.pvs", optFloat, "-vsp_bsp_factor_pvs=", "1.0"); 
     1734  RegisterOption("VspBspTree.Construction.samples", 
     1735          optInt, 
     1736          "-bsp_construction_samples=", 
     1737          "100000"); 
     1738 
     1739  RegisterOption("VspBspTree.Construction.epsilon", 
     1740          optFloat, 
     1741          "-vsp_bsp_construction_side_tolerance=", 
     1742          "0.002"); 
     1743 
     1744  RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0"); 
     1745  RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0"); 
     1746  RegisterOption("VspBspTree.Factor.pvs", optFloat, "-vsp_bsp_factor_pvs=", "1.0"); 
    17371747 
    17381748   ////////////////////////////////////////////////////////////////////////////////// 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h

    r446 r448  
    2020class Polygon3; 
    2121class VssTree; 
     22class VspBspTree; 
    2223class RssTree; 
    2324 
     
    4445  virtual bool ExportScene(SceneGraphNode *node) = 0; 
    4546 
    46  
    4747  virtual bool 
    4848  ExportBox(const AxisAlignedBox3 &box) = 0; 
     
    5656  virtual bool 
    5757  ExportVssTree2(const VssTree &tree, 
    58                                  const Vector3 direction 
    59                                  ) = 0; 
    60  
    61   virtual bool 
    62   ExportRssTree2(const RssTree &tree, 
    6358                                 const Vector3 direction 
    6459                                 ) = 0; 
     
    9893  virtual void  
    9994  ExportBspSplits(const BspTree &tree, const bool exportDepth = false) = 0; 
     95 
    10096  virtual void 
    10197  ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves) = 0; 
    102          
     98   
     99  virtual void  
     100  ExportBspSplits(const VspBspTree &tree, const bool exportDepth = false) = 0; 
     101 
     102  virtual void 
     103  ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0) = 0; 
     104 
    103105  virtual void  
    104106  ExportPolygons(const PolygonContainer &polys) = 0; 
     
    112114  virtual void 
    113115  ExportGeometry(const ObjectContainer &objects) = 0; 
     116 
     117  virtual bool 
     118  ExportRssTree2(const RssTree &tree, 
     119                                 const Vector3 direction) = 0; 
    114120 
    115121  void SetExportRayDensity(const bool d) { mExportRayDensity = d; } 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h

    r437 r448  
    5151  */ 
    5252  Vector3 FindIntersection(const Vector3 &a, 
    53                            const Vector3 &b, 
    54                            float *t = NULL, 
    55                            bool *coplanar = NULL 
    56                            ) const  
     53                                                   const Vector3 &b, 
     54                                                   float *t = NULL, 
     55                                                   bool *coplanar = NULL) const  
    5756  { 
    5857    const Vector3 v = b - a; // line from A to B 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp

    r436 r448  
    4242void Polygon3::Split(const Plane3 &partition,  
    4343                                         Polygon3 &front,  
    44                                          Polygon3 &back) 
     44                                         Polygon3 &back, 
     45                                         const float epsilon) 
    4546{ 
    4647        Vector3 ptA = mVertices.back(); 
    4748         
    48         int sideA = partition.Side(ptA, Vector3::sDistTolerance); 
     49        int sideA = partition.Side(ptA, epsilon); 
    4950         
    5051        VertexContainer::const_iterator it; 
     
    5354 
    5455        bool foundSplit = false; 
    55         // find line - plane intersections 
     56 
     57        //-- find line - plane intersections 
    5658        for (it = mVertices.begin(); it != mVertices.end(); ++ it) 
    5759        { 
    5860                Vector3 ptB = *it; 
    59                 int sideB = partition.Side(ptB, Vector3::sDistTolerance); 
     61                int sideB = partition.Side(ptB, epsilon); 
    6062         
    6163                // vertices on different sides => split 
     
    6870                         
    6971                                // test if split point not too close to previous split point 
    70                                 if (!foundSplit ||  
    71                                         (SqrDistance(splitPt, lastSplit) > Vector3::sDistToleranceSqrt)) 
     72                                if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon))) 
    7273                                { 
    7374                                        // add vertex to both polygons 
     
    8990                                // test if split point not too close to other split point 
    9091                                        // test if split point not too close to previous split point 
    91                                 if (!foundSplit ||  
    92                                         (SqrDistance(splitPt, lastSplit) > Vector3::sDistToleranceSqrt)) 
     92                                if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon))) 
    9393                                { 
    9494                                        // add vertex to both polygons 
     
    125125} 
    126126 
    127 int Polygon3::Side(const Plane3 &plane) const 
    128 { 
    129         int classification = ClassifyPlane(plane); 
     127int Polygon3::Side(const Plane3 &plane,  
     128                                   const float epsilon) const 
     129{ 
     130        int classification = ClassifyPlane(plane, epsilon); 
    130131         
    131132        if (classification == BACK_SIDE) 
     
    137138} 
    138139 
    139 int Polygon3::ClassifyPlane(const Plane3 &plane, const float tolerance) const 
     140int Polygon3::ClassifyPlane(const Plane3 &plane,  
     141                                                        const float epsilon) const 
    140142{ 
    141143        VertexContainer::const_iterator it; 
     
    148150        for (it = mVertices.begin(); it != mVertices.end(); ++ it) 
    149151        { 
    150                 const int side = plane.Side(*it, tolerance); 
     152                const int side = plane.Side(*it, epsilon); 
    151153                 
    152154                if (side > 0) 
     
    179181} 
    180182 
    181 int Polygon3::ClassifyPlane(const Plane3 &plane) const 
    182 { 
    183         return ClassifyPlane(plane, Vector3::sDistTolerance); 
    184 } 
     183/*int Polygon3::ClassifyPlane(const Plane3 &plane) const 
     184{ 
     185        return ClassifyPlane(plane, Limits::Small); 
     186}*/ 
    185187 
    186188 
     
    207209} 
    208210 
    209 bool Polygon3::Valid() const 
     211bool Polygon3::Valid(const float epsilon) const 
    210212{ 
    211213        if (mVertices.size() < 3) 
     
    225227        for (it = mVertices.begin(); it != it_end; ++it) 
    226228        { 
    227                 if (!(SqrDistance(vtx, *it) > sDistToleranceSqrt)) 
    228                 { 
    229                         Debug << "Malformed vertices:\n" << *this << endl; 
     229                if (!(EpsilonEqual(vtx, *it))) 
     230                { 
     231                        //Debug << "Malformed vertices:\n" << *this << endl; 
    230232                        return false; 
    231233                } 
     
    385387} 
    386388 
    387 int Polygon3::ClassifyPlane(const PolygonContainer &polys, const Plane3 &plane) 
     389int Polygon3::ClassifyPlane(const PolygonContainer &polys,  
     390                                                        const Plane3 &plane, 
     391                                                        const float epsilon) 
    388392{ 
    389393        PolygonContainer::const_iterator it; 
     
    395399        for (it = polys.begin(); it != polys.end(); ++ it) 
    396400        { 
    397         const int cf = (*it)->ClassifyPlane(plane); 
     401        const int cf = (*it)->ClassifyPlane(plane, epsilon); 
    398402                 
    399403        if (cf == FRONT_SIDE) 
     
    445449 
    446450        for (pit = cell.begin(); pit != cell.end(); ++ pit) 
     451        { 
     452                if ((*pit)->mVertices.size() < 3) 
     453                        Debug << "ERROR" << endl; 
     454 
    447455                area += (*pit)->GetArea(); 
     456        } 
    448457 
    449458        return area; 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h

    r436 r448  
    5050                @param front returns the front the front polygon 
    5151                @param back returns the back polygon 
     52                @param epsilon epsilon where two points are considered equal 
    5253        */ 
    5354        void Split(const Plane3 &partition,  
    5455                           Polygon3 &front,  
    55                            Polygon3 &back); 
     56                           Polygon3 &back, 
     57                           const float epsilon);// = Limits::Small); 
    5658 
    5759        /** Returns the area of this polygon. 
     
    6264            @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 
    6365        */ 
    64         int ClassifyPlane(const Plane3 &plane) const; 
    65  
     66        //int ClassifyPlane(const Plane3 &plane) const; 
    6667         
    6768        /** Classify polygon with respect to the plane. 
    68             @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 
     69            @param epsilon tolerance value 
     70                @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 
     71 
    6972        */ 
    70         int ClassifyPlane(const Plane3 &plane, const float tolerance) const; 
     73        int ClassifyPlane(const Plane3 &plane, const float epsilon) const; 
    7174 
    7275        /** Side of the polygon with respect to the plane. 
    7376                @returns 1 if on front side, -1 if on back side, 0 else. 
    7477        */ 
    75         int Side(const Plane3 &plane) const; 
     78        int Side(const Plane3 &plane, const float epsilon) const; 
    7679 
    7780        /** Scales the polygon about its center 
     
    8588                @returns true if polygon is valid. 
    8689        */ 
    87         bool Valid() const;  
     90        bool Valid(const float epsilon) const;  
    8891 
    8992        /** Returns the surface normal. 
     
    127130            @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT 
    128131        */ 
    129         static int ClassifyPlane(const PolygonContainer &polys, const Plane3 &plane); 
     132        static int ClassifyPlane(const PolygonContainer &polys,  
     133                                                         const Plane3 &plane, 
     134                                                         const float epsilon); 
    130135 
    131136 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp

    r445 r448  
    178178                mViewCellsManager = new KdViewCellsManager(mKdTree); 
    179179        } 
    180         if (strcmp(viewCellsStr, "bspTree") == 0) 
     180        else if (strcmp(viewCellsStr, "bspTree") == 0) 
    181181        { 
    182182                mBspTree = new BspTree(); 
     183 
     184                Debug << "view cell type: Bsp" << endl; 
    183185 
    184186                environment->GetIntValue("BspTree.Construction.samples", constructionSamples); 
    185187                mViewCellsManager = new BspViewCellsManager(mBspTree, constructionSamples); 
    186188        } 
    187         if (strcmp(viewCellsStr, "vspBspTree") == 0) 
     189        else if (strcmp(viewCellsStr, "vspBspTree") == 0) 
    188190        { 
    189191                mVspBspTree = new VspBspTree(); 
     192 
     193                Debug << "view cell type: VspBsp" << endl; 
    190194 
    191195                environment->GetIntValue("VspBspTree.Construction.samples", constructionSamples); 
     
    204208                mBspTree = new BspTree(); 
    205209 
     210                Debug << "view cell type: Bsp" << endl; 
    206211                environment->GetIntValue("BspTree.Construction.samples", constructionSamples); 
    207212                mViewCellsManager = new BspViewCellsManager(mBspTree, constructionSamples); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp

    r444 r448  
    225225mType(LOCAL_RAY) 
    226226{ 
    227         const float dist = Distance(vssRay.mTermination, vssRay.mOrigin); 
    228  
    229         if (dist) 
    230                 dir = vssRay.GetDir() / dist; 
     227        float len = vssRay.Length(); 
     228 
     229        if (!len) 
     230                len = Limits::Small; 
     231 
     232        dir = vssRay.GetDir() / len; 
    231233 
    232234        if (vssRay.mTerminationObject) 
    233                 intersections.push_back(Intersection(dist, vssRay.mTerminationObject, 0)); 
     235                intersections.push_back(Intersection(len, vssRay.mTerminationObject, 0)); 
    234236 
    235237        Precompute(); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h

    r428 r448  
    1515class VssRay; 
    1616 
     17 
    1718// ------------------------------------------------------------------- 
    1819// CRay class.  A ray is defined by a location and a direction. 
     
    4849                 
    4950    bool operator<( 
    50                                                                          const Intersection &b) const { 
     51                                   const Intersection &b) const { 
     52 
    5153      return  
    5254                                mT 
  • trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp

    r437 r448  
    4545float RayInfo::ExtrapOrigin(const int axis) const  
    4646{ 
    47         return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis); 
     47        return mRay->GetOrigin(axis) + GetMinT() * mRay->GetDir(axis); 
    4848} 
    4949                 
    5050float RayInfo::ExtrapTermination(const int axis) const  
    5151{ 
    52         return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis); 
     52        return mRay->GetOrigin(axis) + GetMaxT() * mRay->GetDir(axis); 
    5353} 
    5454 
    5555Vector3 RayInfo::ExtrapOrigin() const  
    5656{ 
    57         return mRay->GetOrigin() * mRay->GetDir(); 
     57        return mRay->GetOrigin() + GetMinT() * mRay->GetDir(); 
    5858} 
    5959                 
     
    134134        t = splitPlane.FindT(mRay->GetOrigin(), mRay->GetTermination()); 
    135135 
     136//      Debug << "t: " << t << " mint " << GetMinT() << " maxt " << GetMaxT() << " orig: " << mRay->GetOrigin() << 
     137//              " term " << mRay->GetTermination() << endl; 
    136138        if ((t < GetMinT()) || (t > GetMaxT())) 
    137139                return splitPlane.Side(ExtrapOrigin()); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp

    r440 r448  
    33#include "ViewCellBsp.h" 
    44#include "ViewCell.h" 
     5#include "VspBspTree.h" 
     6 
    57 
    68void SimulationStatistics::Print(ostream &app) const 
     
    5355/*     class BspRenderSimulator implementation          */ 
    5456/********************************************************/ 
     57 
     58 
    5559BspRenderSimulator::BspRenderSimulator(BspTree *bspTree): 
    5660mBspTree(bspTree) 
     
    139143 
    140144Real BspRenderSimulator::RenderPvs(ViewCell &viewCell,  
    141                                                                            float objRenderTime) const 
     145                                                                   float objRenderTime) const 
    142146{ 
    143147        return viewCell.GetPvs().GetSize() * objRenderTime; 
     
    234238        return leaf->mKdPvs.GetSize() * objRenderTime; 
    235239} 
     240 
     241/********************************************************/ 
     242/*     class BspRenderSimulator implementation          */ 
     243/********************************************************/ 
     244VspBspRenderSimulator::VspBspRenderSimulator(VspBspTree *vspBspTree): 
     245mVspBspTree(vspBspTree) 
     246{ 
     247} 
     248 
     249VspBspRenderSimulator::VspBspRenderSimulator(float objRenderCost,  
     250                                                                                         float vcOverhead,  
     251                                                                                         float moveSpeed, 
     252                                                                                         VspBspTree *vspBspTree): 
     253RenderSimulator(objRenderCost, vcOverhead, moveSpeed),  
     254mVspBspTree(vspBspTree) 
     255{ 
     256} 
     257 
     258SimulationStatistics VspBspRenderSimulator::SimulateRendering() 
     259{ 
     260        SimulationStatistics simStat; 
     261 
     262        simStat.Reset(); 
     263        simStat.Start(); 
     264 
     265        Real renderTime = 0; 
     266         
     267        // overhead for loading the PVS of the view cells 
     268        float loadPvsOverhead = 0; 
     269        // probability that view point lies in a view cell 
     270        float pInVcTotal = 0; 
     271 
     272        // total probability that a view cell border is crossed 
     273        const float pCrossVcTotal = mVspBspTree->GetBoundingBox().SurfaceArea(); 
     274 
     275        // collect all view cells 
     276        ViewCellContainer viewCells; 
     277        mVspBspTree->CollectViewCells(viewCells); 
     278 
     279        ViewCellContainer::const_iterator it, it_end = viewCells.end(); 
     280 
     281        // surface area substitute for probability 
     282        PolygonContainer geom; 
     283float overallarea = 0; 
     284        for (it = viewCells.begin(); it != it_end; ++ it) 
     285        { 
     286                // compute view cell area 
     287                mVspBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(*it), geom); 
     288 
     289                const float area = Polygon3::GetArea(geom); 
     290                if (area < 0.0001) 
     291                        Debug << "warning, area: " << area << endl; 
     292                CLEAR_CONTAINER(geom); 
     293 
     294                // area substitute for view point probability 
     295                float pInVc = area; 
     296                                 
     297                // compute render time of PVS times probability that view point is in view cell 
     298                float vcCost = pInVc * RenderPvs(*(*it), mObjRenderCost); 
     299                //Debug << "p: " << pInVc << " rendercost: " << RenderPvs(*(*it), mObjRenderCost) << endl; 
     300                renderTime += vcCost; 
     301 
     302                if (vcCost > simStat.maxCost) 
     303                        simStat.maxCost = vcCost; 
     304                else if (vcCost < simStat.minCost) 
     305                        simStat.minCost = vcCost; 
     306 
     307                // probability that a view cell border is crossed 
     308                float pCrossVc = area * mMoveSpeed; 
     309 
     310                // crossing the border of a view cell is also depending on the move speed 
     311                loadPvsOverhead += pCrossVc * mVcOverhead; 
     312overallarea += area; 
     313                pInVcTotal += pInVc; 
     314        } 
     315        Debug << "overall area: " << overallarea << endl; 
     316         
     317        renderTime /= pInVcTotal; 
     318        loadPvsOverhead /= pCrossVcTotal; 
     319 
     320        simStat.avgRtWithoutOverhead = renderTime; 
     321        simStat.avgRenderTime = renderTime + loadPvsOverhead; 
     322         
     323        simStat.maxCost /= pInVcTotal; 
     324        simStat.minCost /= pInVcTotal; 
     325 
     326        simStat.Stop(); 
     327 
     328        return simStat; 
     329} 
     330 
     331Real VspBspRenderSimulator::RenderPvs(ViewCell &viewCell,  
     332                                                                          float objRenderTime) const 
     333{ 
     334        return viewCell.GetPvs().GetSize() * objRenderTime; 
     335} 
  • trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.h

    r441 r448  
    99class ViewCell; 
    1010class KdLeaf; 
     11class VspBspTree; 
    1112 
    1213class SimulationStatistics: public StatisticsBase 
     
    105106        Real RenderPvs(ViewCell &viewCell, const float objRenderTime) const; 
    106107 
     108private: 
    107109        BspTree *mBspTree; 
     110}; 
     111 
     112class VspBspRenderSimulator: public RenderSimulator 
     113{ 
     114public: 
     115        VspBspRenderSimulator(VspBspTree *vspBspTree); 
     116 
     117        VspBspRenderSimulator(float objRenderCost,  
     118                                                  float vcOverhead,  
     119                                                  float moveSpeed,  
     120                                                  VspBspTree *vspBspTree); 
     121 
     122        SimulationStatistics SimulateRendering(); 
     123 
     124protected: 
     125        /** Simulates rendering of the pvs of one view cell, with given rendering time for an object. 
     126                @param viewCell the view cell holding the Pvs 
     127                @param objRenderTime estimated render time for one object of the Pvs 
     128        */ 
     129        Real RenderPvs(ViewCell &viewCell, const float objRenderTime) const; 
     130 
     131private: 
     132        VspBspTree *mVspBspTree; 
    108133}; 
    109134 
  • trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp

    r447 r448  
    99#include "VssRay.h" 
    1010#include "RssTree.h" 
    11  
     11#include "ViewCellBsp.h" 
    1212 
    1313static bool useViewSpaceBox = true;//true; 
     
    474474  } 
    475475   
    476   //-- construct BSP view cells 
    477   if (ViewCell::sHierarchy == ViewCell::BSP)  
    478   { 
    479         const int bspSamples = min((int)mVssRays.size(), mBspConstructionSamples); 
    480          
    481         Debug << "bpssamples: " << bspSamples << endl; 
    482         for (int i = 0; i < bspSamples; ++ i) 
    483           bspRays.push_back(new Ray(*mVssRays[i])); 
    484          
    485         //-- construct BSP tree using the samples 
    486         mBspTree = new BspTree(&mUnbounded);     
    487          
    488         ObjectContainer objects; 
    489         mSceneGraph->CollectObjects(&objects); 
    490         mBspTree->Construct(objects, bspRays); 
    491   } 
    492    
    493476  rssTree = new RssTree; 
    494477  // viewcells = Construct(mVssRays); 
     
    567550        } 
    568551 
    569         // cast rays into BSP tree 
    570         if (ViewCell::sHierarchy == ViewCell::BSP)  
    571           { 
    572                 for (int i = 0; i < (int)vssRays.size(); ++ i) 
    573                   { 
    574                         CastRay(*mBspTree, *vssRays[i]); 
    575                   } 
    576           } 
    577  
    578552        samples+=num; 
    579553        float pvs = rssTree->GetAvgPvsSize(); 
     
    598572  delete rssTree; 
    599573   
    600   if (ViewCell::sHierarchy == ViewCell::BSP)  
    601         { 
    602           Debug << mBspTree->GetStatistics(); 
    603  
    604           ObjectContainer objects; 
    605           ExportSplits(objects, bspRays, 10000); 
    606           ExportBspPvs(objects, bspRays, 10000); 
    607  
    608           BspViewCellsStatistics stat; 
    609           mBspTree->EvaluateViewCellsStats(stat); 
    610           Debug << "original view cell partition:\n" << stat << endl; 
    611  
    612           // clear BSP samples 
    613           CLEAR_CONTAINER(bspRays); 
    614         } 
    615574 
    616575  return true; 
     
    646605          BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 
    647606          // if ray not in unbounded space 
    648           if (leaf->GetViewCell() != &mUnbounded) 
     607/*        if (leaf->GetViewCell() != &mUnbounded) 
    649608                contributingSamples +=  
    650                   leaf->GetViewCell()->GetPvs().AddSample(obj); 
     609                  leaf->GetViewCell()->GetPvs().AddSample(obj);*/ 
    651610        } 
    652611  
     
    657616                BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 
    658617                 
    659                 if (leaf->GetViewCell() != &mUnbounded) 
     618        /*      if (leaf->GetViewCell() != &mUnbounded) 
    660619                  leaf->GetViewCell()-> 
    661                         AddPassingRay(ray, contributingSamples ? 1 : 0); 
     620                        AddPassingRay(ray, contributingSamples ? 1 : 0);*/ 
    662621          } 
    663622   
  • trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp

    r444 r448  
    7575 
    7676        mViewCellsManager->ComputeSampleContributions(rays,  
    77                                                                                                   castRaysToViewCells, 
    7877                                                                                                  sampleContributions,  
    79                                                                                                   contributingSamples); 
     78                                                                                                  contributingSamples, 
     79                                                                                                  castRaysToViewCells); 
    8080} 
    8181 
     
    397397        //-- several visualizations and statistics 
    398398                  
    399         //-- render simulation 
    400         cout << "\nevaluating bsp view cells render time before merge ... "; 
     399        //-- render simulation after merge 
     400        cout << "\nevaluating bsp view cells render time after merge ... "; 
    401401                  
    402402        const SimulationStatistics ss = mViewCellsManager->SimulateRendering(); 
     
    405405        cout << ss << endl; 
    406406        Debug << ss << endl; 
    407                   
     407         
     408 
    408409        mViewCellsManager->Visualize(objects, mSampleRays);      
    409410     
     
    424425                RayContainer::const_iterator it, it_end = newRays.end(); 
    425426 
    426                 if ((int)mVssSampleRays.size() < mViewCellsManager->GetConstructionSamples()) 
     427                if ((int)mVssSampleRays.size() <  
     428                        mViewCellsManager->GetConstructionSamples()) 
    427429                { 
    428430                        for (it = newRays.begin(); it != it_end; ++ it) 
     
    433435                else 
    434436                { 
    435                         // construct view cells using the collected samples 
    436                         cout << "building view cells from " << (int)mVssSampleRays.size() << " samples " << endl; 
    437  
     437                        // construct view cells 
    438438                        mViewCellsManager->Construct(objects, mVssSampleRays); 
    439                          
     439                 
    440440                        // throw away samples  
    441                         CLEAR_CONTAINER(mVssSampleRays); 
    442                 } 
    443         } 
    444         // Need (ordered) rays for post processing => collect new rays 
     441                        //CLEAR_CONTAINER(mVssSampleRays); 
     442                } 
     443        } 
     444        // Need rays (with ordered intersections) for post processing => collect new rays 
    445445        else if (((int)mSampleRays.size() < mViewCellsManager->GetPostProcessSamples()) || 
    446446                         ((int)mSampleRays.size() < mViewCellsManager->GetVisualizationSamples())) 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp

    r372 r448  
    22#include "Vector3.h" 
    33#include "Halton.h" 
    4  
    5 float Vector3::sDistTolerance = 0.002f; 
    6 float Vector3::sDistToleranceSqrt = 0.000004f; 
    74 
    85// Given min a vector to minimize and a candidate vector, replace 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h

    r372 r448  
    3636  Vector3(float X) { x = y = z = X; } 
    3737  Vector3(const Vector3 &v) { x = v.x; y = v.y; z = v.z; } 
    38  
    39   /// the distance where two points are still considered equal 
    40   static float sDistTolerance; 
    41   static float sDistToleranceSqrt; 
    4238 
    4339  // Functions to get at the vector components 
     
    480476EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2) 
    481477{ 
    482   return EpsilonEqualV3(v1,v2,Limits::Small); 
     478  return EpsilonEqualV3(v1, v2, Limits::Small); 
    483479} 
    484480 
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp

    r445 r448  
    9898} 
    9999 
    100 Plane3 *BspInterior::GetPlane() 
    101 { 
    102         return &mPlane; 
     100Plane3 BspInterior::GetPlane() const 
     101{ 
     102        return mPlane; 
    103103} 
    104104 
     
    117117} 
    118118 
    119 int BspInterior::SplitPolygons(PolygonContainer &polys,  
    120                                                            PolygonContainer &frontPolys,  
    121                                                            PolygonContainer &backPolys,  
    122                                                            PolygonContainer &coincident) 
    123 { 
    124         int splits = 0; 
    125  
    126 #ifdef _Debug 
    127         Debug << "splitting polygons of node " << this << " with plane " << mPlane << endl; 
    128 #endif 
    129         while (!polys.empty()) 
    130         { 
    131                 Polygon3 *poly = polys.back(); 
    132                 polys.pop_back(); 
    133  
    134                 //Debug << "New polygon with plane: " << poly->GetSupportingPlane() << "\n"; 
    135  
    136                 // classify polygon 
    137                 const int cf = poly->ClassifyPlane(mPlane); 
    138  
    139                 switch (cf) 
    140                 { 
    141                         case Polygon3::COINCIDENT: 
    142                                 coincident.push_back(poly); 
    143                                 break;                   
    144                         case Polygon3::FRONT_SIDE:       
    145                                 frontPolys.push_back(poly); 
    146                                 break; 
    147                         case Polygon3::BACK_SIDE: 
    148                                 backPolys.push_back(poly); 
    149                                 break; 
    150                         case Polygon3::SPLIT: 
    151                                 { 
    152                                         Polygon3 *front_piece = new Polygon3(poly->mParent); 
    153                                         Polygon3 *back_piece = new Polygon3(poly->mParent); 
    154  
    155                                         //-- split polygon into front and back part 
    156                                         poly->Split(mPlane, *front_piece, *back_piece); 
    157                                          
    158                                         ++ splits; // increase number of splits 
    159  
    160                                         //-- inherit rays from parent polygon for blocked ray criterium 
    161                                         poly->InheritRays(*front_piece, *back_piece); 
    162                                         //Debug << "p: " << poly->mPiercingRays.size() << " f: " << front_piece->mPiercingRays.size() << " b: " << back_piece->mPiercingRays.size() << endl; 
    163                                  
    164                                         // check if polygons still valid  
    165                                         if (front_piece->Valid()) 
    166                                                 frontPolys.push_back(front_piece); 
    167                                         else 
    168                                                 DEL_PTR(front_piece); 
    169                                  
    170                                         if (back_piece->Valid()) 
    171                                                 backPolys.push_back(back_piece); 
    172                                         else                             
    173                                                 DEL_PTR(back_piece); 
    174                                  
    175 #ifdef _DEBUG 
    176                                         Debug << "split " << *poly << endl << *front_piece << endl << *back_piece << endl; 
    177 #endif 
    178                                         DEL_PTR(poly); 
    179                                 } 
    180                                 break; 
    181                         default: 
    182                 Debug << "SHOULD NEVER COME HERE\n"; 
    183                                 break; 
    184                 } 
    185         } 
    186  
    187         return splits; 
    188 } 
    189  
    190119/****************************************************************/ 
    191120/*                  class BspLeaf implementation                */ 
    192121/****************************************************************/ 
     122 
     123 
    193124BspLeaf::BspLeaf(): mViewCell(NULL) 
    194125{ 
    195126} 
     127 
    196128 
    197129BspLeaf::BspLeaf(BspViewCell *viewCell):  
     
    199131{ 
    200132} 
     133 
    201134 
    202135BspLeaf::BspLeaf(BspInterior *parent):  
     
    204137{} 
    205138 
     139 
     140 
    206141BspLeaf::BspLeaf(BspInterior *parent, BspViewCell *viewCell):  
    207142BspNode(parent), mViewCell(viewCell) 
     
    222157{  
    223158        return true;  
    224 } 
    225  
    226 void BspLeaf::AddToPvs(const BoundedRayContainer &rays,  
    227                                            int &sampleContributions, 
    228                                            int &contributingSamples) 
    229 { 
    230         sampleContributions = 0; 
    231         contributingSamples = 0; 
    232  
    233     BoundedRayContainer::const_iterator it, it_end = rays.end(); 
    234  
    235         // add contributions from samples to the PVS 
    236         for (it = rays.begin(); it != it_end; ++ it) 
    237         { 
    238                 int contribution = 0; 
    239                 Ray *ray = (*it)->mRay; 
    240                          
    241                 if (!ray->intersections.empty()) 
    242                         contribution += mViewCell->GetPvs().AddSample(ray->intersections[0].mObject); 
    243                  
    244                 if (ray->sourceObject.mObject) 
    245                         contribution += mViewCell->GetPvs().AddSample(ray->sourceObject.mObject); 
    246  
    247                 if (contribution) 
    248                 { 
    249                         sampleContributions += contribution; 
    250                         ++ contributingSamples; 
    251                 } 
    252  
    253                 //if (ray->mFlags & Ray::STORE_BSP_INTERSECTIONS) 
    254                         ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this)); 
    255         } 
    256159} 
    257160 
     
    308211        environment->GetIntValue("BspTree.maxTests", mMaxTests); 
    309212 
    310         environment->GetFloatValue("BspTree.Construction.sideTolerance", Vector3::sDistTolerance); 
    311         Vector3::sDistToleranceSqrt = Vector3::sDistTolerance * Vector3::sDistTolerance; 
    312  
    313  
     213        environment->GetFloatValue("BspTree.Construction.epsilon", mEpsilon); 
     214         
    314215    Debug << "BSP max depth: " << mTermMaxDepth << endl; 
    315216        Debug << "BSP min PVS: " << mTermMinPvs << endl; 
     
    347248} 
    348249 
     250 
    349251const BspTreeStatistics &BspTree::GetStatistics() const  
    350252{ 
    351253        return mStat; 
    352254} 
     255 
     256 
     257int BspTree::SplitPolygons(const Plane3 &plane, 
     258                                                   PolygonContainer &polys,  
     259                                                   PolygonContainer &frontPolys,  
     260                                                   PolygonContainer &backPolys,  
     261                                                   PolygonContainer &coincident) const 
     262{ 
     263        int splits = 0; 
     264 
     265#ifdef _Debug 
     266        Debug << "splitting polygons of node " << this << " with plane " << mPlane << endl; 
     267#endif 
     268        while (!polys.empty()) 
     269        { 
     270                Polygon3 *poly = polys.back(); 
     271                polys.pop_back(); 
     272 
     273                //Debug << "New polygon with plane: " << poly->GetSupportingPlane() << "\n"; 
     274 
     275                // classify polygon 
     276                const int cf = poly->ClassifyPlane(plane, mEpsilon); 
     277 
     278                switch (cf) 
     279                { 
     280                        case Polygon3::COINCIDENT: 
     281                                coincident.push_back(poly); 
     282                                break;                   
     283                        case Polygon3::FRONT_SIDE:       
     284                                frontPolys.push_back(poly); 
     285                                break; 
     286                        case Polygon3::BACK_SIDE: 
     287                                backPolys.push_back(poly); 
     288                                break; 
     289                        case Polygon3::SPLIT: 
     290                                { 
     291                                        Polygon3 *front_piece = new Polygon3(poly->mParent); 
     292                                        Polygon3 *back_piece = new Polygon3(poly->mParent); 
     293 
     294                                        //-- split polygon into front and back part 
     295                                        poly->Split(plane,  
     296                                                                *front_piece,  
     297                                                                *back_piece, 
     298                                                                mEpsilon); 
     299                                         
     300                                        ++ splits; // increase number of splits 
     301 
     302                                        //-- inherit rays from parent polygon for blocked ray criterium 
     303                                        poly->InheritRays(*front_piece, *back_piece); 
     304                                 
     305                                        // check if polygons still valid  
     306                                        if (front_piece->Valid(mEpsilon)) 
     307                                                frontPolys.push_back(front_piece); 
     308                                        else 
     309                                                DEL_PTR(front_piece); 
     310                                 
     311                                        if (back_piece->Valid(mEpsilon)) 
     312                                                backPolys.push_back(back_piece); 
     313                                        else                             
     314                                                DEL_PTR(back_piece); 
     315                                 
     316#ifdef _DEBUG 
     317                                        Debug << "split " << *poly << endl << *front_piece << endl << *back_piece << endl; 
     318#endif 
     319                                        DEL_PTR(poly); 
     320                                } 
     321                                break; 
     322                        default: 
     323                Debug << "SHOULD NEVER COME HERE\n"; 
     324                                break; 
     325                } 
     326        } 
     327 
     328        return splits; 
     329} 
     330 
    353331 
    354332void BspTreeStatistics::Print(ostream &app) const 
     
    458436                 
    459437                                // split viewcell polygons with respect to split plane 
    460                                 splits += interior->SplitPolygons(*tData.mPolygons, 
    461                                                                                                   *frontPolys,  
    462                                                                                                   *backPolys, 
    463                                                                                                   coincident); 
     438                                splits += SplitPolygons(interior->GetPlane(), 
     439                                                                                *tData.mPolygons,  
     440                                                                                *frontPolys,  
     441                                                                                *backPolys,  
     442                                                                                coincident); 
    464443                                 
    465444                                // extract view cells associated with the split polygons 
     
    505484                        // cleanup 
    506485                        DEL_PTR(tData.mPolygons); 
     486                        DEL_PTR(tData.mRays); 
    507487                } 
    508488                else 
     
    514494} 
    515495 
    516 int BspTree::AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent) 
     496int BspTree::AddMeshToPolygons(Mesh *mesh,  
     497                                                           PolygonContainer &polys,  
     498                                                           MeshInstance *parent) 
    517499{ 
    518500        FaceContainer::const_iterator fi; 
     
    523505                Polygon3 *poly = new Polygon3((*fi), mesh); 
    524506                 
    525                 if (poly->Valid()) 
     507                if (poly->Valid(mEpsilon)) 
    526508                { 
    527509                        poly->mParent = parent; // set parent intersectable 
     
    684666 
    685667                float minT, maxT; 
    686                 if (BoundRay(*ray, minT, maxT)) 
     668                if (mBox.GetRaySegment(*ray, minT, maxT)) 
    687669                        rays->push_back(new BoundedRay(ray, minT, maxT)); 
    688670        } 
     
    719701 
    720702                float minT, maxT; 
    721                 if (BoundRay(*ray, minT, maxT)) 
     703                if (mBox.GetRaySegment(*ray, minT, maxT)) 
    722704                        rays->push_back(new BoundedRay(ray, minT, maxT)); 
    723705        } 
     
    801783                { 
    802784                        int conSamp = 0, sampCon = 0; 
    803                         leaf->AddToPvs(*tData.mRays, conSamp, sampCon); 
     785                        AddToPvs(leaf, *tData.mRays, conSamp, sampCon); 
    804786                         
    805787                        mStat.contributingSamples += conSamp; 
     
    818800                DEL_PTR(tData.mPolygons); 
    819801                DEL_PTR(tData.mRays); 
    820                          
     802                DEL_PTR(tData.mGeometry); 
     803 
    821804                return leaf; 
    822805        } 
     
    860843        // cleanup 
    861844        DEL_PTR(tData.mNode); 
     845 
    862846        DEL_PTR(tData.mPolygons); 
    863847        DEL_PTR(tData.mRays); 
     
    916900         
    917901 
    918         Debug << "number of rays: " << tData.mRays->size() << endl; 
    919         Debug << "number of polys: " << tData.mPolygons->size() << endl; 
     902        Debug << "number of rays: " << (int)tData.mRays->size() << endl; 
     903        Debug << "number of polys: " << (int)tData.mPolygons->size() << endl; 
    920904 
    921905        startTime = GetTime(); 
     
    928912        startTime = GetTime(); 
    929913        // subdivide polygons with plane 
    930         mStat.splits += interior->SplitPolygons(*tData.mPolygons,  
    931                                                     *frontData.mPolygons,  
    932                                                                                         *backData.mPolygons,  
    933                                                                                         coincident); 
     914        mStat.splits += SplitPolygons(interior->GetPlane(), 
     915                                                                  *tData.mPolygons,  
     916                                          *frontData.mPolygons,  
     917                                                                  *backData.mPolygons,  
     918                                                                  coincident); 
    934919 
    935920        Debug << "time used for polygon splitting: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
     
    944929                tData.mGeometry->SplitGeometry(*frontData.mGeometry,  
    945930                                                                           *backData.mGeometry,  
    946                                                                            *this,  
    947                                                                            interior->mPlane); 
     931                                                                           interior->mPlane, 
     932                                                                           mBox, 
     933                                                                           mEpsilon); 
    948934         
    949935                 
     
    974960        interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior)); 
    975961         
    976         frontData.mNode = interior->mFront; 
    977         backData.mNode = interior->mBack; 
     962        frontData.mNode = interior->GetFront(); 
     963        backData.mNode = interior->GetBack(); 
    978964         
    979965        //DEL_PTR(leaf); 
     
    12691255 
    12701256                        BoundedRay *bRay = (*rays)[idx[j]]; 
    1271                         pt[j] = chooseMin ? bRay->mRay->Extrap(bRay->mMinT) : bRay->mRay->Extrap(bRay->mMaxT); 
     1257                        pt[j] = chooseMin ? bRay->mRay->Extrap(bRay->mMinT) :  
     1258                                                                bRay->mRay->Extrap(bRay->mMaxT); 
    12721259                }        
    12731260                         
     
    13471334                Polygon3 *poly = polys[testIdx]; 
    13481335 
    1349         const int classification = poly->ClassifyPlane(candidatePlane); 
     1336        const int classification =  
     1337                        poly->ClassifyPlane(candidatePlane, mEpsilon); 
    13501338 
    13511339                if (mSplitPlaneStrategy & BALANCED_POLYS) 
     
    14371425} 
    14381426 
    1439 bool BspTree::BoundRay(const Ray &ray, float &minT, float &maxT) const 
    1440 { 
    1441         maxT = 1e6; 
    1442         minT = 0; 
    1443          
    1444         // test with tree bounding box 
    1445         if (!mBox.GetMinMaxT(ray, &minT, &maxT)) 
    1446                 return false; 
    1447  
    1448         if (minT < 0) // start ray from origin 
    1449                 minT = 0; 
    1450  
    1451         // bound ray or line segment 
    1452         if (//(ray.GetType() == Ray::LOCAL_RAY) &&  
    1453             !ray.intersections.empty() &&  
    1454                 (ray.intersections[0].mT <= maxT)) 
    1455         { 
    1456                 maxT = ray.intersections[0].mT; 
    1457         } 
    1458  
    1459         return true; 
    1460 } 
    14611427 
    14621428inline void BspTree::GenerateUniqueIdsForPvs() 
     
    14991465                        BspNodeGeometry backCell; 
    15001466 
    1501                         cell.SplitGeometry(frontCell, backCell, *this, candidatePlane); 
     1467                        cell.SplitGeometry(frontCell,  
     1468                                                           backCell,  
     1469                                                           candidatePlane, 
     1470                                                           mBox, 
     1471                                                           mEpsilon); 
    15021472                 
    15031473                        pFront = frontCell.GetArea(); 
     
    18031773        float maxt, mint; 
    18041774 
    1805         if (!BoundRay(ray, mint, maxt)) 
     1775        if (!mBox.GetRaySegment(ray, mint, maxt)) 
    18061776                return 0; 
    18071777 
     
    18181788                if (!node->IsLeaf())  
    18191789                { 
    1820                         BspInterior *in = (BspInterior *) node; 
     1790                        BspInterior *in = dynamic_cast<BspInterior *>(node); 
    18211791                         
    1822                         Plane3 *splitPlane = in->GetPlane(); 
    1823  
    1824                         int entSide = splitPlane->Side(entp); 
    1825                         int extSide = splitPlane->Side(extp); 
    1826  
    1827                         Vector3 intersection; 
     1792                        Plane3 splitPlane = in->GetPlane(); 
     1793                        const int entSide = splitPlane.Side(entp); 
     1794                        const int extSide = splitPlane.Side(extp); 
    18281795 
    18291796                        if (entSide < 0) 
     
    18581825                        // find intersection of ray segment with plane 
    18591826                        float t; 
    1860                         extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &t); 
     1827                        extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t); 
    18611828                        maxt *= t; 
    18621829                         
     
    19341901                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    19351902 
    1936                         nodeStack.push(interior->mFront); 
    1937                         nodeStack.push(interior->mBack); 
     1903                        nodeStack.push(interior->GetFront()); 
     1904                        nodeStack.push(interior->GetBack()); 
    19381905                } 
    19391906        } 
     
    19891956                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    19901957 
    1991                         nodeStack.push(interior->mFront); 
    1992                         nodeStack.push(interior->mBack); 
     1958                        nodeStack.push(interior->GetFront()); 
     1959                        nodeStack.push(interior->GetBack()); 
    19931960                } 
    19941961        } 
     
    21012068                { 
    21022069                        BspInterior *interior = dynamic_cast<BspInterior *>(n); 
    2103                         Plane3 halfSpace = *dynamic_cast<BspInterior *>(interior)->GetPlane(); 
    2104  
    2105             if (interior->mFront != lastNode) 
     2070                        Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 
     2071 
     2072            if (interior->GetFront() != lastNode) 
    21062073                                halfSpace.ReverseOrientation(); 
    21072074 
     
    21352102        ExtractHalfSpaces(n, halfSpaces); 
    21362103 
    2137         PolygonContainer candidatePolys; 
     2104        PolygonContainer candidates; 
    21382105 
    21392106        // bounded planes are added to the polygons (reverse polygons 
     
    21432110                Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]); 
    21442111                 
    2145                 if (p->Valid()) 
    2146                 { 
    2147                         candidatePolys.push_back(p->CreateReversePolygon()); 
     2112                if (p->Valid(mEpsilon)) 
     2113                { 
     2114                        candidates.push_back(p->CreateReversePolygon()); 
    21482115                        DEL_PTR(p); 
    21492116                } 
     
    21582125                        vertices.push_back(mBox.GetFace(i).mVertices[j]); 
    21592126 
    2160                 candidatePolys.push_back(new Polygon3(vertices)); 
    2161         } 
    2162  
    2163         for (int i = 0; i < (int)candidatePolys.size(); ++ i) 
     2127                candidates.push_back(new Polygon3(vertices)); 
     2128        } 
     2129 
     2130        for (int i = 0; i < (int)candidates.size(); ++ i) 
    21642131        { 
    21652132                // polygon is split by all other planes 
    2166                 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 
     2133                for (int j = 0; (j < (int)halfSpaces.size()) && candidates[i]; ++ j) 
    21672134                { 
    21682135                        if (i == j) // polygon and plane are coincident 
     
    21722139                        Polygon3 *frontPoly, *backPoly; 
    21732140 
    2174                         const int cf = candidatePolys[i]->ClassifyPlane(halfSpaces[j]); 
     2141                        const int cf = candidates[i]-> 
     2142                                ClassifyPlane(halfSpaces[j], mEpsilon); 
    21752143                         
    21762144                        switch (cf) 
     
    21802148                                        backPoly = new Polygon3(); 
    21812149 
    2182                                         candidatePolys[i]->Split(halfSpaces[j],  
    2183                                                                                          *frontPoly,  
    2184                                                                                          *backPoly); 
    2185  
    2186                                         DEL_PTR(candidatePolys[i]); 
    2187  
    2188                                         if (frontPoly->Valid()) 
    2189                                                 candidatePolys[i] = frontPoly; 
     2150                                        candidates[i]->Split(halfSpaces[j],  
     2151                                                                                 *frontPoly,  
     2152                                                                                 *backPoly, 
     2153                                                                                 mEpsilon); 
     2154 
     2155                                        DEL_PTR(candidates[i]); 
     2156 
     2157                                        if (frontPoly->Valid(mEpsilon)) 
     2158                                                candidates[i] = frontPoly; 
    21902159                                        else 
    21912160                                                DEL_PTR(frontPoly); 
     
    21942163                                        break; 
    21952164                                case Polygon3::BACK_SIDE: 
    2196                                         DEL_PTR(candidatePolys[i]); 
     2165                                        DEL_PTR(candidates[i]); 
    21972166                                        break; 
    21982167                                // just take polygon as it is 
     
    22042173                } 
    22052174                 
    2206                 if (candidatePolys[i]) 
    2207                         cell.push_back(candidatePolys[i]); 
     2175                if (candidates[i]) 
     2176                        cell.push_back(candidates[i]); 
    22082177        } 
    22092178} 
     
    22422211                                { 
    22432212                                        const int cf =  
    2244                                                 Polygon3::ClassifyPlane(neighborCandidate, halfSpaces[i]); 
     2213                                                Polygon3::ClassifyPlane(neighborCandidate,  
     2214                                                                                                halfSpaces[i], 
     2215                                                                                                mEpsilon); 
    22452216 
    22462217                                        if (cf == Polygon3::BACK_SIDE) 
     
    22582229                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    22592230         
    2260                         const int cf = Polygon3::ClassifyPlane(cell, interior->mPlane); 
     2231                        const int cf = Polygon3::ClassifyPlane(cell,  
     2232                                                                                                   interior->mPlane, 
     2233                                                                                                   mEpsilon); 
    22612234 
    22622235                        if (cf == Polygon3::FRONT_SIDE) 
    2263                                 nodeStack.push(interior->mFront); 
     2236                                nodeStack.push(interior->GetFront()); 
    22642237                        else 
    22652238                                if (cf == Polygon3::BACK_SIDE) 
    2266                                         nodeStack.push(interior->mBack); 
     2239                                        nodeStack.push(interior->GetBack()); 
    22672240                                else  
    22682241                                { 
    22692242                                        // random decision 
    2270                                         nodeStack.push(interior->mBack); 
    2271                                         nodeStack.push(interior->mFront); 
     2243                                        nodeStack.push(interior->GetBack()); 
     2244                                        nodeStack.push(interior->GetFront()); 
    22722245                                } 
    22732246                } 
     
    23052278                        ConstructGeometry(interior, cell); 
    23062279 
    2307                         const int cf = Polygon3::ClassifyPlane(cell, halfspace); 
     2280                        const int cf = Polygon3::ClassifyPlane(cell,  
     2281                                                                                                   halfspace,  
     2282                                                                                                   mEpsilon); 
    23082283 
    23092284                        if (cf == Polygon3::BACK_SIDE) 
    2310                                 next = interior->mFront; 
     2285                                next = interior->GetFront(); 
    23112286                        else 
    23122287                                if (cf == Polygon3::FRONT_SIDE) 
    2313                                         next = interior->mFront; 
     2288                                        next = interior->GetFront(); 
    23142289                        else  
    23152290                        { 
    23162291                                // random decision 
    23172292                                if (mask & 1) 
    2318                                         next = interior->mBack; 
     2293                                        next = interior->GetBack(); 
    23192294                                else 
    2320                                         next = interior->mFront; 
     2295                                        next = interior->GetFront(); 
    23212296                                mask = mask >> 1; 
    23222297                        } 
     
    23532328                        // random decision 
    23542329                        if (mask & 1) 
    2355                                 nodeStack.push(interior->mBack); 
     2330                                nodeStack.push(interior->GetBack()); 
    23562331                        else 
    2357                                 nodeStack.push(interior->mFront); 
     2332                                nodeStack.push(interior->GetFront()); 
    23582333 
    23592334                        mask = mask >> 1; 
     
    23622337         
    23632338        return NULL; 
     2339} 
     2340 
     2341void BspTree::AddToPvs(BspLeaf *leaf, 
     2342                                           const BoundedRayContainer &rays,  
     2343                                           int &sampleContributions, 
     2344                                           int &contributingSamples) 
     2345{ 
     2346        sampleContributions = 0; 
     2347        contributingSamples = 0; 
     2348 
     2349    BoundedRayContainer::const_iterator it, it_end = rays.end(); 
     2350 
     2351        ViewCell *vc = leaf->GetViewCell(); 
     2352 
     2353        // add contributions from samples to the PVS 
     2354        for (it = rays.begin(); it != it_end; ++ it) 
     2355        { 
     2356                int contribution = 0; 
     2357                Ray *ray = (*it)->mRay; 
     2358                         
     2359                if (!ray->intersections.empty()) 
     2360                        contribution += vc->GetPvs().AddSample(ray->intersections[0].mObject); 
     2361                 
     2362                if (ray->sourceObject.mObject) 
     2363                        contribution += vc->GetPvs().AddSample(ray->sourceObject.mObject); 
     2364 
     2365                if (contribution) 
     2366                { 
     2367                        sampleContributions += contribution; 
     2368                        ++ contributingSamples; 
     2369                } 
     2370 
     2371                //if (ray->mFlags & Ray::STORE_BSP_INTERSECTIONS) 
     2372                //      ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this)); 
     2373        } 
    23642374} 
    23652375 
     
    23972407} 
    23982408 
    2399 /************************************************************* 
    2400  *            BspNodeGeometry Implementation                 * 
    2401  *************************************************************/ 
     2409float BspTree::GetEpsilon() const 
     2410{ 
     2411        return mEpsilon; 
     2412} 
     2413 
     2414void BspViewCellsStatistics::Print(ostream &app) const 
     2415{ 
     2416        app << "===== BspViewCells statistics ===============\n"; 
     2417 
     2418        app << setprecision(4); 
     2419 
     2420        //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n"; 
     2421 
     2422        app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl; 
     2423 
     2424        app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl; 
     2425 
     2426        app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl; 
     2427 
     2428        app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl; 
     2429 
     2430        app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl; 
     2431 
     2432        app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl; 
     2433 
     2434        app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgBspLeaves() << endl; 
     2435 
     2436        app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxBspLeaves << endl; 
     2437         
     2438        app << "===== END OF BspViewCells statistics ==========\n"; 
     2439} 
     2440 
     2441/*************************************************************/ 
     2442/*            BspNodeGeometry Implementation                 */ 
     2443/*************************************************************/ 
    24022444 
    24032445BspNodeGeometry::~BspNodeGeometry() 
     
    24132455void BspNodeGeometry::SplitGeometry(BspNodeGeometry &front, 
    24142456                                                                        BspNodeGeometry &back, 
    2415                                                                         const BspTree &tree,                                              
    2416                                                                         const Plane3 &splitPlane) const 
     2457                                                                        const Plane3 &splitPlane, 
     2458                                                                        const AxisAlignedBox3 &box, 
     2459                                                                        const float epsilon) const 
    24172460{        
    24182461        // get cross section of new polygon 
    2419         Polygon3 *planePoly = tree.GetBoundingBox().CrossSection(splitPlane); 
    2420  
    2421         planePoly = SplitPolygon(planePoly, tree); 
    2422  
    2423         //-- plane poly splits all other cell polygons 
     2462        Polygon3 *planePoly = box.CrossSection(splitPlane); 
     2463 
     2464        // split polygon with all other polygons 
     2465        planePoly = SplitPolygon(planePoly, epsilon); 
     2466 
     2467        //-- new polygon splits all other polygons 
    24242468        for (int i = 0; i < (int)mPolys.size(); ++ i) 
    24252469        { 
    2426                 const int cf = mPolys[i]->ClassifyPlane(splitPlane, 0.00001f); 
     2470                /// don't use epsilon here to get exact split planes 
     2471                const int cf =  
     2472                        mPolys[i]->ClassifyPlane(splitPlane, Limits::Small); 
    24272473                         
    2428                 // split new polygon with all previous planes 
    24292474                switch (cf) 
    24302475                { 
     
    24362481                                        Polygon3 *backPoly = new Polygon3(); 
    24372482                                 
    2438                                         poly->Split(splitPlane, *frontPoly, *backPoly); 
     2483                                        poly->Split(splitPlane,  
     2484                                                                *frontPoly,  
     2485                                                                *backPoly, 
     2486                                                                epsilon); 
    24392487 
    24402488                                        DEL_PTR(poly); 
    24412489 
    2442                                         if (frontPoly->Valid()) 
     2490                                        if (frontPoly->Valid(epsilon)) 
    24432491                                                front.mPolys.push_back(frontPoly); 
    24442492                                        else 
    24452493                                                DEL_PTR(frontPoly); 
    24462494 
    2447                                         if (backPoly->Valid()) 
     2495                                        if (backPoly->Valid(epsilon)) 
    24482496                                                back.mPolys.push_back(backPoly); 
    24492497                                        else 
     
    24672515        } 
    24682516 
    2469         //-- finally add the new polygon to the child cells 
     2517        //-- finally add the new polygon to the child node geometries 
    24702518        if (planePoly) 
    24712519        { 
     
    24812529 
    24822530Polygon3 *BspNodeGeometry::SplitPolygon(Polygon3 *planePoly, 
    2483                                                                                 const BspTree &tree) const 
    2484 { 
     2531                                                                                const float epsilon) const 
     2532{ 
     2533        if (!planePoly->Valid(epsilon)) 
     2534                DEL_PTR(planePoly); 
     2535 
    24852536        // polygon is split by all other planes 
    24862537        for (int i = 0; (i < (int)mPolys.size()) && planePoly; ++ i) 
     
    24882539                Plane3 plane = mPolys[i]->GetSupportingPlane(); 
    24892540 
     2541                /// don't use epsilon here to get exact split planes 
    24902542                const int cf =  
    2491                         planePoly->ClassifyPlane(plane, 0.00001f); 
     2543                        planePoly->ClassifyPlane(plane, Limits::Small); 
    24922544                         
    24932545                // split new polygon with all previous planes 
     
    24992551                                        Polygon3 *backPoly = new Polygon3(); 
    25002552 
    2501                                         planePoly->Split(plane, *frontPoly, *backPoly); 
     2553                                        planePoly->Split(plane,  
     2554                                                                         *frontPoly,  
     2555                                                                         *backPoly, 
     2556                                                                         epsilon); 
    25022557                                         
    25032558                                        // don't need anymore 
     
    25062561 
    25072562                                        // back polygon is belonging to geometry 
    2508                                         if (backPoly->Valid()) 
     2563                                        if (backPoly->Valid(epsilon)) 
    25092564                                                planePoly = backPoly; 
    25102565                                        else 
     
    25252580        return planePoly; 
    25262581} 
    2527  
    2528 void BspViewCellsStatistics::Print(ostream &app) const 
    2529 { 
    2530         app << "===== BspViewCells statistics ===============\n"; 
    2531  
    2532         app << setprecision(4); 
    2533  
    2534         //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n"; 
    2535  
    2536         app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl; 
    2537  
    2538         app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl; 
    2539  
    2540         app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl; 
    2541  
    2542         app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl; 
    2543  
    2544         app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl; 
    2545  
    2546         app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl; 
    2547  
    2548         app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgBspLeaves() << endl; 
    2549  
    2550         app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxBspLeaves << endl; 
    2551          
    2552         app << "===== END OF BspViewCells statistics ==========\n"; 
    2553 } 
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h

    r444 r448  
    77#include <stack> 
    88#include "Statistics.h" 
     9#include "VssRay.h" 
     10 
    911 
    1012class ViewCell; 
     
    2729        float GetArea() const; 
    2830         
    29         /** Computes new cell based on the old cell definition and a new split plane 
    30                 @param side indicates which side of the halfspace  
    31         */ 
    32         void SplitGeometry(BspNodeGeometry &front,  
     31        /** Computes new front and back geometry based on the old cell  
     32                geometry and a new split plane 
     33        */ 
     34        void SplitGeometry(BspNodeGeometry &front, 
    3335                                           BspNodeGeometry &back, 
    34                                            const BspTree &tree, 
    35                                            const Plane3 &splitPlane) const; 
    36  
    37         Polygon3 *SplitPolygon(Polygon3 *poly, const BspTree &tree) const; 
     36                                           const Plane3 &splitPlane, 
     37                       const AxisAlignedBox3 &box, 
     38                                           const float epsilon) const; 
     39 
     40        Polygon3 *SplitPolygon(Polygon3 *poly, const float epsilon) const; 
    3841 
    3942        PolygonContainer mPolys; 
     
    270273        BspNode *GetFront(); 
    271274 
    272         Plane3 *GetPlane(); 
    273  
     275        /** Returns split plane. 
     276        */ 
     277        Plane3 GetPlane() const; 
     278 
     279        /** Replace front or back child with new child. 
     280        */ 
    274281        void ReplaceChildLink(BspNode *oldChild, BspNode *newChild); 
     282        /** Replace front and back child. 
     283        */ 
    275284        void SetupChildLinks(BspNode *b, BspNode *f); 
    276  
    277         /** Splits polygons with respect to the split plane. 
    278                 @param polys the polygons to be split. the polygons are consumed and 
    279                            distributed to the containers frontPolys, backPolys, coincident. 
    280                 @param frontPolys returns the polygons in the front of the split plane 
    281                 @param backPolys returns the polygons in the back of the split plane 
    282                 @param coincident returns the polygons coincident to the split plane 
    283  
    284                 @returns the number of splits    
    285         */ 
    286         int SplitPolygons(PolygonContainer &polys,  
    287                                           PolygonContainer &frontPolys,  
    288                                           PolygonContainer &backPolys,  
    289                                           PolygonContainer &coincident); 
    290285 
    291286        friend ostream &operator<<(ostream &s, const BspInterior &A) 
     
    298293        /// Splitting plane corresponding to this node 
    299294        Plane3 mPlane; 
     295 
    300296        /// back node 
    301297        BspNode *mBack; 
     
    328324        void SetViewCell(BspViewCell *viewCell); 
    329325 
    330         /** Adds ray sample contributions to the PVS. 
    331                 @param sampleContributions the number contributions of the samples 
    332                 @param contributingSampels the number of contributing rays 
    333                  
    334         */ 
    335         void AddToPvs(const BoundedRayContainer &rays,  
    336                                   int &sampleContributions, 
    337                                   int &contributingSamples); 
     326        VssRayContainer mVssRays; 
    338327 
    339328protected: 
     
    516505        BspViewCell *GetRootCell() const; 
    517506 
    518         /** Parses the environment and stores the global BSP tree parameters 
    519         */ 
    520         static void ParseEnvironment(); 
    521  
     507        /** Returns epsilon of this tree. 
     508        */ 
     509        float GetEpsilon() const; 
    522510 
    523511protected: 
     
    722710        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const; 
    723711 
    724         /** Bounds ray and returns minT and maxT. 
    725                 @returns true if ray hits BSP tree bounding box 
    726         */ 
    727         bool BoundRay(const Ray &ray, float &minT, float &maxT) const; 
    728  
    729712        /** Subdivides the rays into front and back rays according to the split plane. 
    730713                 
     
    768751        */ 
    769752        float AccumulatedRayLength(BoundedRayContainer &rays) const; 
     753 
     754        /** Splits polygons with respect to the split plane. 
     755                @param polys the polygons to be split. the polygons are consumed and 
     756                           distributed to the containers frontPolys, backPolys, coincident. 
     757                @param frontPolys returns the polygons in the front of the split plane 
     758                @param backPolys returns the polygons in the back of the split plane 
     759                @param coincident returns the polygons coincident to the split plane 
     760 
     761                @returns the number of splits    
     762        */ 
     763        int SplitPolygons(const Plane3 &plane, 
     764                                          PolygonContainer &polys,  
     765                                          PolygonContainer &frontPolys,  
     766                                          PolygonContainer &backPolys,  
     767                                          PolygonContainer &coincident) const; 
     768 
     769        /** Adds ray sample contributions to the PVS. 
     770                @param sampleContributions the number contributions of the samples 
     771                @param contributingSampels the number of contributing rays 
     772                 
     773        */ 
     774        void AddToPvs(BspLeaf *leaf, 
     775                                  const BoundedRayContainer &rays,  
     776                                  int &sampleContributions, 
     777                                  int &contributingSamples); 
    770778 
    771779        /// Pointer to the root of the tree. 
     
    852860        bool mPvsUseArea; 
    853861 
     862        /// epsilon where two points are still considered equal 
     863        float mEpsilon; 
     864 
    854865private: 
    855866         
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp

    r444 r448  
    6868 
    6969void ViewCellsManager::ComputeSampleContributions(const RayContainer &rays,  
    70                                                                                                   const bool castRays, 
    7170                                                                                                  int &sampleContributions, 
    72                                                                                                   int &contributingSamples) 
     71                                                                                                  int &contributingSamples, 
     72                                                                                                  const bool castRays) 
    7373{ 
    7474        // view cells not yet constructed 
     
    168168SimulationStatistics ViewCellsManager::SimulateRendering() const 
    169169{ 
    170         if (!ViewCellsConstructed()) 
     170        if (!ViewCellsConstructed() || !mRenderSimulator) 
    171171                return SimulationStatistics(); 
    172172 
     
    240240                return 0; 
    241241 
    242         Debug << "Constructing bsp view cells" << endl; 
    243  
    244242        int sampleContributions = 0; 
    245243         
     
    247245 
    248246        int limit = min (mConstructionSamples, (int)rays.size()); 
     247 
     248        // construct view cells using the collected samples 
     249        Debug << "construcing bsp view cells from "  
     250                  << limit << " samples " << endl; 
    249251 
    250252    for (int i = 0; i < limit; ++ i) 
     
    332334        int pvsSize = 0; 
    333335 
    334         BspViewCellsStatistics stat; 
    335         mBspTree->EvaluateViewCellsStats(stat); 
    336         Debug << "original view cell partition:\n" << stat << endl; 
    337                  
    338         if (1) // export view cells 
     336        BspViewCellsStatistics vcStats; 
     337        mBspTree->EvaluateViewCellsStats(vcStats); 
     338        Debug << "original view cell partition:\n" << vcStats << endl; 
     339                 
     340        if (1) // export view cells before merge 
    339341        { 
    340342                cout << "exporting initial view cells (=leaves) ... "; 
     
    344346                { 
    345347                        exporter->SetWireframe(); 
    346                         exporter->ExportBspLeaves(*mBspTree, stat.maxPvs); 
     348                        exporter->ExportBspLeaves(*mBspTree, vcStats.maxPvs); 
    347349                        //exporter->ExportBspViewCellPartition(*mBspTree, 0); 
    348350                                 
     
    360362                } 
    361363                cout << "finished" << endl; 
    362         } 
     364 
     365                //-- render simulation 
     366                cout << "\nevaluating bsp view cells render time before merge ... "; 
     367                  
     368                const SimulationStatistics ss = SimulateRendering(); 
     369                          
     370                cout << " finished" << endl; 
     371                cout << ss << endl; 
     372                Debug << ss << endl; 
     373        } 
     374 
    363375 
    364376        cout << "starting post processing using " << mPostProcessSamples << " samples ... "; 
    365                  
     377 
    366378        long startTime = GetTime(); 
    367  
    368379 
    369380        //-- merge or subdivide view cells 
     
    408419        cout << "merged " << merged << " view cells in " 
    409420                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl; 
     421 
     422        // statistics after post process 
     423        vcStats.Reset(); 
     424        mBspTree->EvaluateViewCellsStats(vcStats); 
     425        Debug << "post processed view cell partition:\n" << vcStats << endl; 
    410426 
    411427        return merged; 
     
    956972mVspKdTree(vspKdTree) 
    957973{ 
    958    mRenderSimulator = NULL; // TODO: new VspKdRenderSimulator(vspKdTree); 
     974   mRenderSimulator = NULL;//new VspKdRenderSimulator(vspKdTree); 
    959975   InitRenderSimulator(); 
    960976} 
     
    983999                return 0; 
    9841000 
    985         //if (castRay) // TODO 
     1001        //if (castRay) 
     1002                //mVspKdTree->CastRay(ray); 
    9861003 
    9871004        int sampleContributions = 0; 
    9881005 
    989 /* 
    990     for (int i = 0; i < (int)rays.size(); ++ i) 
    991         { 
    992                 Ray *ray = rays[i]; 
    993  
    994                 mBspTree->CastRay(*ray); 
    995                          
    996                 Intersectable *term =  
    997                         !ray->intersections.empty() ? ray->intersections[0].mObject : NULL 
    998                         ; 
    999                 sampleContributions +=  
    1000                         AddSampleContributions(*ray, ray->sourceObject.mObject, term); 
    1001                          
    1002         } 
    1003 */ 
    10041006        return sampleContributions; 
    10051007} 
     
    11211123mVspBspTree(vspBspTree) 
    11221124{ 
    1123    mRenderSimulator = NULL;// TODO new VspBspRenderSimulator(bspTree); 
    1124    //InitRenderSimulator(); 
     1125        mRenderSimulator = new VspBspRenderSimulator(vspBspTree); 
     1126        InitRenderSimulator(); 
    11251127} 
    11261128 
     
    11821184                for (int j = 0; j < (int)ray.bspIntersections.size(); ++ j) 
    11831185                {        
    1184                         VspBspLeaf *leaf = NULL;  //TODO ray.bspIntersections[j].mLeaf; 
     1186                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 
    11851187                 
    11861188                        // if ray not in unbounded space 
     
    12061208                for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j)  
    12071209                { 
    1208                         VspBspLeaf *leaf = NULL;// TODO = ray.bspIntersections[j].mLeaf; 
     1210                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf; 
    12091211 
    12101212                        if (leaf->GetViewCell() != mVspBspTree->GetRootCell()) 
     
    12191221                                                                                const RayContainer &rays) 
    12201222{ 
    1221         return 0;// TODO 
    12221223        if (!ViewCellsConstructed()) 
    12231224        { 
     
    12311232        int pvsSize = 0; 
    12321233 
    1233         VspBspViewCellsStatistics vcStats; 
     1234        BspViewCellsStatistics vcStats; 
    12341235        mVspBspTree->EvaluateViewCellsStats(vcStats); 
    12351236        Debug << "original view cell partition:\n" << vcStats << endl; 
     
    12431244                { 
    12441245                        exporter->SetWireframe(); 
    1245                         //exporter->ExportBspLeaves(*mVspBspTree, stat.maxPvs); 
     1246                        exporter->ExportBspViewCellPartition(*mVspBspTree, vcStats.maxPvs); 
    12461247                                 
    12471248                        if (0) 
     
    12841285                iit = ray->bspIntersections.begin(); 
    12851286 
    1286                 VspBspLeaf *previousLeaf = NULL;//TODO(*iit).mLeaf; 
     1287                BspLeaf *previousLeaf = (*iit).mLeaf; 
    12871288                ++ iit; 
    12881289                 
    12891290                for (; iit != ray->bspIntersections.end(); ++ iit) 
    12901291                { 
    1291                         VspBspLeaf *leaf = NULL;//TODO(*iit).mLeaf; 
     1292                        BspLeaf *leaf = (*iit).mLeaf; 
    12921293 
    12931294                        if (ShouldMerge(leaf, previousLeaf)) 
     
    13071308                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl; 
    13081309 
     1310        // statistics after post process 
     1311        vcStats.Reset(); 
     1312        mVspBspTree->EvaluateViewCellsStats(vcStats); 
     1313        Debug << "post processed view cell partition:\n" << vcStats << endl; 
     1314 
    13091315        return merged; 
    13101316} 
     
    13191325                                                                           const RayContainer &sampleRays) 
    13201326{ 
    1321         return; // TODO 
    13221327        if (!ViewCellsConstructed()) 
    13231328                return; 
    13241329 
    13251330        //-- recount pvs 
    1326         VspBspViewCellsStatistics vcStats; 
     1331        BspViewCellsStatistics vcStats; 
    13271332        mVspBspTree->EvaluateViewCellsStats(vcStats); 
    13281333 
     
    13301335        { 
    13311336                cout << "exporting view cells after merge ... "; 
    1332                 /*Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d"); 
     1337                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d"); 
    13331338 
    13341339                if (exporter) 
     
    13371342                        delete exporter; 
    13381343                } 
    1339                 */ 
     1344                 
    13401345                cout << "finished" << endl; 
    13411346        }        
     
    13431348        //-- visualization of the BSP splits 
    13441349        bool exportSplits = false; 
    1345                 environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits); 
     1350        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits); 
    13461351         
    13471352        if (exportSplits) 
     
    13521357        } 
    13531358 
    1354 //TODO  ExportVspBspPvs(objects, sampleRays); 
     1359        ExportBspPvs(objects, sampleRays); 
    13551360} 
    13561361 
     
    13671372                exporter->SetForcedMaterial(m); 
    13681373                exporter->SetWireframe(); 
    1369                 // TODO 
    1370                 //exporter->ExportBspSplits(*mVspBspTree, true); 
     1374                 
     1375                exporter->ExportBspSplits(*mVspBspTree, true); 
    13711376 
    13721377                // take forced material, else big scenes cannot be viewed 
     
    14121417        const int raysOut = min((int)sampleRays.size(), mVisualizationSamples); 
    14131418        cout << "visualization using " << mVisualizationSamples << " samples" << endl; 
    1414         vector<Ray *> vcRays[leafOut]; 
    1415  
    1416         if (0) 
     1419         
     1420        if (1) 
    14171421        { 
    14181422                //-- some random view cells and rays for output 
    1419                 vector<VspBspLeaf *> vspBspLeaves; 
     1423                vector<BspLeaf *> vspBspLeaves; 
    14201424 
    14211425                for (int i = 0; i < leafOut; ++ i) 
     
    14241428                for (int i = 0; i < (int)vspBspLeaves.size(); ++ i) 
    14251429                { 
     1430                        RayContainer vcRays; 
    14261431                        cout << "creating output for view cell " << i << " ... "; 
    14271432                        // check whether we can add the current ray to the output rays 
    1428                         for (int k = 0; k < raysOut; ++ k)  
     1433                        /*for (int k = 0; k < raysOut; ++ k)  
    14291434                        { 
    14301435                                Ray *ray = sampleRays[k]; 
     
    14361441                                        if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell())  
    14371442                                        { 
    1438                                                 vcRays[i].push_back(ray); 
     1443                                                vcRays.push_back(ray); 
    14391444                                        } 
    14401445                                } 
    14411446                        } 
     1447                        */ 
    14421448 
    14431449                        Intersectable::NewMail(); 
     
    14741480 
    14751481                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()  
    1476                                         << ", piercing rays=" << (int)vcRays[i].size() << endl; 
     1482                                        << ", piercing rays=" << (int)vcRays.size() << endl; 
    14771483 
    14781484                        // export rays piercing this view cell 
    1479                         exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0)); 
    1480  
    1481                         m.mDiffuseColor = RgbColor(1, 0, 0); 
     1485                        exporter->ExportRays(vcRays, 1000, RgbColor(1, 0, 0)); 
     1486                        exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1)); 
     1487                         
     1488                        m.mDiffuseColor = RgbColor(0, 1, 1); 
    14821489                        exporter->SetForcedMaterial(m); 
    14831490 
    1484                         // exporter->SetWireframe(); 
    1485                         exporter->SetFilled(); 
     1491                        exporter->SetWireframe(); 
     1492                        //exporter->SetFilled(); 
    14861493 
    14871494                        // output PVS of view cell 
     
    15271534                { 
    15281535                        cout << "creating output for view cell " << i << " ... "; 
    1529                          
     1536                        RayContainer vcRays; 
    15301537            Intersectable::NewMail(); 
    15311538                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]); 
     
    15391546                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j) 
    15401547                                { 
    1541                                         VspBspLeaf *leaf = NULL; // TODO = ray->bspIntersections[j].mLeaf; 
     1548                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf; 
    15421549 
    15431550                                        if (vc == leaf->GetViewCell())  
    15441551                                        { 
    1545                                                 vcRays[i].push_back(ray); 
     1552                                                vcRays.push_back(ray); 
    15461553                                        } 
    15471554                                } 
     
    15721579                         
    15731580                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()  
    1574                                         << ", piercing rays=" << (int)vcRays[i].size() << endl; 
     1581                                        << ", piercing rays=" << (int)vcRays.size() << endl; 
    15751582 
    15761583                         
    15771584                        // export rays piercing this view cell 
    1578                         exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0)); 
     1585                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0)); 
    15791586         
    15801587                        m.mDiffuseColor = RgbColor(1, 0, 0); 
     
    16071614 
    16081615 
    1609 bool VspBspViewCellsManager::MergeVspBspLeafViewCells(VspBspLeaf *front,  
    1610                                                                                                           VspBspLeaf *back) const 
     1616bool VspBspViewCellsManager::MergeVspBspLeafViewCells(BspLeaf *front,  
     1617                                                                                                          BspLeaf *back) const 
    16111618{ 
    16121619        BspViewCell *viewCell =  
     
    16231630        BspViewCell *bVc = back->GetViewCell(); 
    16241631 
    1625         // TODO 
    1626         /*vector<VspBspLeaf *> fLeaves = fVc->mBspLeaves; 
    1627         vector<VspBspLeaf *> bLeaves = bVc->mBspLeaves; 
    1628  
    1629         vector<VspBspLeaf *>::const_iterator it; 
     1632        vector<BspLeaf *> fLeaves = fVc->mBspLeaves; 
     1633        vector<BspLeaf *> bLeaves = bVc->mBspLeaves; 
     1634 
     1635        vector<BspLeaf *>::const_iterator it; 
    16301636         
    16311637        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it) 
     
    16421648        DEL_PTR(fVc); 
    16431649        DEL_PTR(bVc); 
    1644 */ 
     1650 
    16451651        return true; 
    16461652} 
    16471653 
    1648 bool VspBspViewCellsManager::ShouldMerge(VspBspLeaf *front, VspBspLeaf *back) const 
     1654bool VspBspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const 
    16491655{ 
    16501656        ViewCell *fvc = front->GetViewCell(); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h

    r444 r448  
    2020class VspKdTree; 
    2121class AxisAlignedBox3; 
    22 class VspBspLeaf; 
     22class BspLeaf; 
    2323 
    2424/** 
     
    5757        */ 
    5858        void  ComputeSampleContributions(const RayContainer &rays,  
    59                                                                          const bool castRays, 
    6059                                                                         int &sampleContributions, 
    61                                                                          int &contributingSamples); 
     60                                                                         int &contributingSamples, 
     61                                                                         const bool castRays = true); 
    6262 
    6363 
     
    350350        /** Merges view cells front and back leaf view cell. 
    351351        */ 
    352         bool MergeVspBspLeafViewCells(VspBspLeaf *front, VspBspLeaf *back) const; 
     352        bool MergeVspBspLeafViewCells(BspLeaf *front, BspLeaf *back) const; 
    353353 
    354354        /** Returns true if front and back leaf should be merged. 
    355355        */ 
    356         bool ShouldMerge(VspBspLeaf *front, VspBspLeaf *back) const; 
     356        bool ShouldMerge(BspLeaf *front, BspLeaf *back) const; 
    357357 
    358358        /// the view space partition BSP tree. 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp

    r445 r448  
    1313#include "Exporter.h" 
    1414#include "Plane3.h" 
     15#include "ViewCellBsp.h" 
    1516 
    1617//-- static members 
     
    2425const float VspBspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0}; 
    2526 
    26 int VspBspNode::sMailId = 1; 
    2727 
    2828int VspBspTree::sFrontId = 0;  
     
    3030int VspBspTree::sFrontAndBackId = 0; 
    3131 
     32 
    3233/****************************************************************/ 
    33 /*                  class VspBspNode implementation                */ 
     34/*                  class VspBspTree implementation             */ 
    3435/****************************************************************/ 
    3536 
    36 VspBspNode::VspBspNode():  
    37 mParent(NULL) 
    38 {} 
    39  
    40 VspBspNode::VspBspNode(VspBspInterior *parent):  
    41 mParent(parent) 
    42 {} 
    43  
    44  
    45 bool VspBspNode::IsRoot() const  
    46 { 
    47         return mParent == NULL; 
    48 } 
    49  
    50 VspBspInterior *VspBspNode::GetParent()  
    51 {  
    52         return mParent;  
    53 } 
    54  
    55 void VspBspNode::SetParent(VspBspInterior *parent) 
    56 { 
    57         mParent = parent; 
    58 } 
    59  
    60 /****************************************************************/ 
    61 /*              class VspBspInterior implementation                */ 
    62 /****************************************************************/ 
    63  
    64  
    65 VspBspInterior::VspBspInterior(const Plane3 &plane):  
    66 mPlane(plane), mFront(NULL), mBack(NULL) 
    67 {} 
    68  
    69 VspBspInterior::~VspBspInterior()  
    70 {  
    71         DEL_PTR(mFront);  
    72         DEL_PTR(mBack); 
    73 } 
    74  
    75 bool VspBspInterior::IsLeaf() const 
    76 {  
    77         return false;  
    78 } 
    79  
    80 VspBspNode *VspBspInterior::GetBack()  
    81 { 
    82         return mBack; 
    83 } 
    84  
    85 VspBspNode *VspBspInterior::GetFront()  
    86 { 
    87         return mFront; 
    88 } 
    89  
    90 Plane3 *VspBspInterior::GetPlane() 
    91 { 
    92         return &mPlane; 
    93 } 
    94  
    95 void VspBspInterior::ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild)  
    96 { 
    97         if (mBack == oldChild) 
    98                 mBack = newChild; 
     37VspBspTree::VspBspTree():  
     38mRoot(NULL), 
     39mPvsUseArea(true) 
     40{ 
     41        mRootCell = new BspViewCell(); 
     42 
     43        Randomize(); // initialise random generator for heuristics 
     44 
     45        //-- termination criteria for autopartition 
     46        environment->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth); 
     47        environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs); 
     48        environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays); 
     49        environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea);      
     50        environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution); 
     51        environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength); 
     52 
     53        //-- factors for bsp tree split plane heuristics 
     54        environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor); 
     55        environment->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor); 
     56        environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi); 
     57 
     58        //-- termination criteria for axis aligned split 
     59        environment->GetFloatValue("VspBspTree.Termination.AxisAligned.ct_div_ci", mAaCtDivCi); 
     60        environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxCostRatio", mMaxCostRatio); 
     61         
     62        environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays",  
     63                                                         mTermMinRaysForAxisAligned); 
     64         
     65        //-- partition criteria 
     66        environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates); 
     67        environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates); 
     68        environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy); 
     69        environment->GetFloatValue("VspBspTree.AxisAligned.splitBorder", mSplitBorder); 
     70 
     71        environment->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon); 
     72        environment->GetIntValue("VspBspTree.maxTests", mMaxTests); 
     73 
     74    Debug << "BSP max depth: " << mTermMaxDepth << endl; 
     75        Debug << "BSP min PVS: " << mTermMinPvs << endl; 
     76        Debug << "BSP min area: " << mTermMinArea << endl; 
     77        Debug << "BSP min rays: " << mTermMinRays << endl; 
     78        Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl; 
     79        Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl; 
     80 
     81        Debug << "Split plane strategy: "; 
     82        if (mSplitPlaneStrategy & RANDOM_POLYGON) 
     83                Debug << "random polygon "; 
     84        if (mSplitPlaneStrategy & AXIS_ALIGNED) 
     85                Debug << "axis aligned "; 
     86        if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     87                Debug << "least ray splits "; 
     88        if (mSplitPlaneStrategy & BALANCED_RAYS) 
     89                Debug << "balanced rays "; 
     90        if (mSplitPlaneStrategy & PVS) 
     91                Debug << "pvs"; 
     92 
     93        Debug << endl; 
     94} 
     95 
     96 
     97const BspTreeStatistics &VspBspTree::GetStatistics() const  
     98{ 
     99        return mStat; 
     100} 
     101 
     102 
     103VspBspTree::~VspBspTree() 
     104{ 
     105        DEL_PTR(mRoot); 
     106        DEL_PTR(mRootCell); 
     107} 
     108 
     109int VspBspTree::AddMeshToPolygons(Mesh *mesh,  
     110                                                                  PolygonContainer &polys,  
     111                                                                  MeshInstance *parent) 
     112{ 
     113        FaceContainer::const_iterator fi; 
     114         
     115        // copy the face data to polygons 
     116        for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi) 
     117        { 
     118                Polygon3 *poly = new Polygon3((*fi), mesh); 
     119                 
     120                if (poly->Valid(mEpsilon)) 
     121                { 
     122                        poly->mParent = parent; // set parent intersectable 
     123                        polys.push_back(poly); 
     124                } 
     125                else 
     126                        DEL_PTR(poly); 
     127        } 
     128        return (int)mesh->mFaces.size(); 
     129} 
     130 
     131int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells,  
     132                                                          PolygonContainer &polys,  
     133                                                          int maxObjects) 
     134{ 
     135        int limit = (maxObjects > 0) ?  
     136                Min((int)viewCells.size(), maxObjects) : (int)viewCells.size(); 
     137   
     138        int polysSize = 0; 
     139 
     140        for (int i = 0; i < limit; ++ i) 
     141        { 
     142                if (viewCells[i]->GetMesh()) // copy the mesh data to polygons 
     143                { 
     144                        mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb 
     145                        polysSize +=  
     146                                AddMeshToPolygons(viewCells[i]->GetMesh(),  
     147                                                                  polys,  
     148                                                                  viewCells[i]); 
     149                } 
     150        } 
     151 
     152        return polysSize; 
     153} 
     154 
     155int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects,  
     156                                                                 PolygonContainer &polys,  
     157                                                                 int maxObjects) 
     158{ 
     159        int limit = (maxObjects > 0) ?  
     160                Min((int)objects.size(), maxObjects) : (int)objects.size(); 
     161   
     162        for (int i = 0; i < limit; ++i) 
     163        { 
     164                Intersectable *object = objects[i];//*it; 
     165                Mesh *mesh = NULL; 
     166 
     167                switch (object->Type()) // extract the meshes 
     168                { 
     169                case Intersectable::MESH_INSTANCE: 
     170                        mesh = dynamic_cast<MeshInstance *>(object)->GetMesh(); 
     171                        break; 
     172                case Intersectable::VIEW_CELL: 
     173                        mesh = dynamic_cast<ViewCell *>(object)->GetMesh(); 
     174                        break; 
     175                        // TODO: handle transformed mesh instances 
     176                default: 
     177                        Debug << "intersectable type not supported" << endl; 
     178                        break; 
     179                } 
     180                 
     181        if (mesh) // copy the mesh data to polygons 
     182                { 
     183                        mBox.Include(object->GetBox()); // add to BSP tree aabb 
     184                        AddMeshToPolygons(mesh, polys, mRootCell); 
     185                } 
     186        } 
     187 
     188        return (int)polys.size(); 
     189} 
     190 
     191void VspBspTree::Construct(const VssRayContainer &sampleRays) 
     192{ 
     193    mStat.nodes = 1; 
     194        mBox.Initialize();      // initialise BSP tree bounding box 
     195         
     196        PolygonContainer polys; 
     197        RayInfoContainer *rays = new RayInfoContainer(); 
     198 
     199        VssRayContainer::const_iterator rit, rit_end = sampleRays.end(); 
     200 
     201        long startTime = GetTime(); 
     202 
     203        Debug << "**** Extracting polygons from rays ****\n"; 
     204 
     205        Intersectable::NewMail(); 
     206 
     207        //-- extract polygons intersected by the rays 
     208        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     209        { 
     210                VssRay *ray = *rit; 
     211         
     212                if (ray->mTerminationObject && !ray->mTerminationObject->Mailed()) 
     213                { 
     214                        ray->mTerminationObject->Mail(); 
     215                        MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject); 
     216                        AddMeshToPolygons(obj->GetMesh(), polys, obj); 
     217                } 
     218 
     219                if (ray->mOriginObject && !ray->mOriginObject->Mailed()) 
     220                { 
     221                        ray->mOriginObject->Mail(); 
     222                        MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject); 
     223                        AddMeshToPolygons(obj->GetMesh(), polys, obj); 
     224                } 
     225        } 
     226 
     227        // compute bounding box 
     228        Polygon3::IncludeInBox(polys, mBox); 
     229 
     230        //-- store rays 
     231        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     232        { 
     233                VssRay *ray = *rit; 
     234                 
     235                float minT, maxT; 
     236 
     237                // TODO: not very efficient to implictly cast between rays types ... 
     238                if (mBox.GetRaySegment(*ray, minT, maxT)) 
     239                { 
     240                        float len = ray->Length(); 
     241                         
     242                        if (!len)  
     243                                len = Limits::Small; 
     244                         
     245                        rays->push_back(RayInfo(ray, minT / len, maxT / len)); 
     246                } 
     247        } 
     248 
     249        mStat.polys = (int)polys.size(); 
     250 
     251        Debug << "**** Finished polygon extraction ****" << endl; 
     252        Debug << (int)polys.size() << " polys extracted from " << (int)sampleRays.size() << " rays" << endl; 
     253        Debug << "extraction time: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
     254 
     255        Construct(polys, rays); 
     256 
     257        // clean up polygons 
     258        CLEAR_CONTAINER(polys); 
     259} 
     260 
     261void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 
     262{ 
     263        std::stack<VspBspTraversalData> tStack; 
     264 
     265        mRoot = new BspLeaf(); 
     266 
     267        // constrruct root node geometry 
     268        BspNodeGeometry *geom = new BspNodeGeometry(); 
     269        ConstructGeometry(mRoot, *geom); 
     270 
     271        VspBspTraversalData tData(mRoot,  
     272                                                          new PolygonContainer(polys),  
     273                                                          0, 
     274                                                          rays,  
     275                              ComputePvsSize(*rays),  
     276                                                          geom->GetArea(),  
     277                                                          geom); 
     278 
     279        tStack.push(tData); 
     280 
     281        mStat.Start(); 
     282        cout << "Contructing vsp bsp tree ... "; 
     283 
     284        long startTime = GetTime(); 
     285         
     286        while (!tStack.empty())  
     287        { 
     288                tData = tStack.top(); 
     289 
     290            tStack.pop(); 
     291 
     292                // subdivide leaf node 
     293                BspNode *r = Subdivide(tStack, tData); 
     294 
     295                if (r == mRoot) 
     296                        Debug << "BSP tree construction time spent at root: "  
     297                                  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
     298        } 
     299 
     300        cout << "finished\n"; 
     301 
     302        mStat.Stop(); 
     303} 
     304 
     305bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const 
     306{ 
     307        return  
     308                (((int)data.mRays->size() <= mTermMinRays) || 
     309                 (data.mPvs <= mTermMinPvs) || 
     310                 (data.mArea <= mTermMinArea) || 
     311                // (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 
     312                 (data.mDepth >= mTermMaxDepth)); 
     313} 
     314 
     315BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack,  
     316                                                           VspBspTraversalData &tData) 
     317{ 
     318        //-- terminate traversal   
     319        if (TerminationCriteriaMet(tData))               
     320        { 
     321                BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
     322         
     323                BspViewCell *viewCell = new BspViewCell(); 
     324                 
     325                leaf->SetViewCell(viewCell); 
     326                viewCell->mBspLeaves.push_back(leaf); 
     327 
     328                //-- add pvs 
     329                if (viewCell != mRootCell) 
     330                { 
     331                        int conSamp = 0, sampCon = 0; 
     332                        AddToPvs(leaf, *tData.mRays, conSamp, sampCon); 
     333                         
     334                        mStat.contributingSamples += conSamp; 
     335                        mStat.sampleContributions += sampCon; 
     336                } 
     337 
     338                EvaluateLeafStats(tData); 
     339         
     340                //-- clean up 
     341                 
     342                DEL_PTR(tData.mPolygons); 
     343                DEL_PTR(tData.mRays); 
     344                DEL_PTR(tData.mGeometry); 
     345 
     346                return leaf; 
     347        } 
     348 
     349        //-- continue subdivision 
     350        PolygonContainer coincident; 
     351         
     352        VspBspTraversalData tFrontData(new PolygonContainer(),  
     353                                                                   tData.mDepth + 1, 
     354                                                                   new RayInfoContainer(),  
     355                                                                   new BspNodeGeometry()); 
     356 
     357        VspBspTraversalData tBackData(new PolygonContainer(),  
     358                                                                  tData.mDepth + 1, 
     359                                                                  new RayInfoContainer(),  
     360                                                                  new BspNodeGeometry()); 
     361 
     362        // create new interior node and two leaf nodes 
     363        BspInterior *interior =  
     364                SubdivideNode(tData, tFrontData, tBackData, coincident); 
     365 
     366#ifdef _DEBUG    
     367        if (frontPolys->empty() && backPolys->empty() && (coincident.size() > 2)) 
     368        {       for (PolygonContainer::iterator it = coincident.begin(); it != coincident.end(); ++it) 
     369                        Debug << (*it) << " " << (*it)->GetArea() << " " << (*it)->mParent << endl ; 
     370                Debug << endl;} 
     371#endif 
     372 
     373        // push the children on the stack 
     374        tStack.push(tFrontData); 
     375        tStack.push(tBackData); 
     376 
     377        // cleanup 
     378        DEL_PTR(tData.mNode);    
     379 
     380        DEL_PTR(tData.mPolygons); 
     381        DEL_PTR(tData.mRays); 
     382        DEL_PTR(tData.mGeometry); 
     383 
     384        return interior; 
     385} 
     386 
     387BspInterior *VspBspTree::SubdivideNode(VspBspTraversalData &tData, 
     388                                                                           VspBspTraversalData &frontData, 
     389                                                                           VspBspTraversalData &backData, 
     390                                                                           PolygonContainer &coincident) 
     391{ 
     392        mStat.nodes += 2; 
     393         
     394        BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
     395         
     396        // select subdivision plane 
     397        BspInterior *interior = new BspInterior(SelectPlane(leaf, tData));  
     398 
     399#ifdef _DEBUG 
     400        Debug << interior << endl; 
     401#endif 
     402         
     403        // subdivide rays into front and back rays 
     404        SplitRays(interior->GetPlane(),  
     405                          *tData.mRays,  
     406                          *frontData.mRays,  
     407                          *backData.mRays); 
     408         
     409        // subdivide polygons with plane 
     410        mStat.splits += SplitPolygons(interior->GetPlane(), 
     411                                                                  *tData.mPolygons,  
     412                                          *frontData.mPolygons,  
     413                                                                  *backData.mPolygons, 
     414                                                                  coincident); 
     415 
     416    // compute pvs 
     417        frontData.mPvs = ComputePvsSize(*frontData.mRays); 
     418        backData.mPvs = ComputePvsSize(*backData.mRays); 
     419 
     420        // split geometry and compute area 
     421        if (1) 
     422        { 
     423                tData.mGeometry->SplitGeometry(*frontData.mGeometry,  
     424                                                                           *backData.mGeometry,  
     425                                                                           interior->GetPlane(), 
     426                                                                           mBox, 
     427                                                                           mEpsilon); 
     428         
     429                 
     430                frontData.mArea = frontData.mGeometry->GetArea(); 
     431                backData.mArea = backData.mGeometry->GetArea(); 
     432        } 
     433 
     434        // compute accumulated ray length 
     435        //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays); 
     436        //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays); 
     437 
     438        //-- create front and back leaf 
     439 
     440        BspInterior *parent = leaf->GetParent(); 
     441 
     442        // replace a link from node's parent 
     443        if (!leaf->IsRoot()) 
     444        { 
     445                parent->ReplaceChildLink(leaf, interior); 
     446                interior->SetParent(parent); 
     447        } 
     448        else // new root 
     449        { 
     450                mRoot = interior; 
     451        } 
     452 
     453        // and setup child links 
     454        interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior)); 
     455         
     456        frontData.mNode = interior->GetFront(); 
     457        backData.mNode = interior->GetBack(); 
     458         
     459        //DEL_PTR(leaf); 
     460        return interior; 
     461} 
     462 
     463void VspBspTree::AddToPvs(BspLeaf *leaf, 
     464                                                  const RayInfoContainer &rays,  
     465                                                  int &sampleContributions, 
     466                                                  int &contributingSamples) 
     467{ 
     468        sampleContributions = 0; 
     469        contributingSamples = 0; 
     470 
     471    RayInfoContainer::const_iterator it, it_end = rays.end(); 
     472 
     473        ViewCell *vc = leaf->GetViewCell(); 
     474 
     475        // add contributions from samples to the PVS 
     476        for (it = rays.begin(); it != it_end; ++ it) 
     477        { 
     478                int contribution = 0; 
     479                VssRay *ray = (*it).mRay; 
     480                         
     481                if (ray->mTerminationObject) 
     482                        contribution += vc->GetPvs().AddSample(ray->mTerminationObject); 
     483                 
     484                if (ray->mOriginObject) 
     485                        contribution += vc->GetPvs().AddSample(ray->mOriginObject); 
     486 
     487                if (contribution) 
     488                { 
     489                        sampleContributions += contribution; 
     490                        ++ contributingSamples; 
     491                } 
     492                //leaf->mVssRays.push_back(ray); 
     493        } 
     494} 
     495 
     496void VspBspTree::SortSplitCandidates(const PolygonContainer &polys,  
     497                                                                         const int axis,  
     498                                                                         vector<SortableEntry> &splitCandidates) const 
     499{ 
     500  splitCandidates.clear(); 
     501   
     502  int requestedSize = 2 * (int)polys.size(); 
     503  // creates a sorted split candidates array   
     504  splitCandidates.reserve(requestedSize); 
     505   
     506  PolygonContainer::const_iterator it, it_end = polys.end(); 
     507 
     508  AxisAlignedBox3 box; 
     509 
     510  // insert all queries  
     511  for(it = polys.begin(); it != it_end; ++ it) 
     512  { 
     513          box.Initialize(); 
     514          box.Include(*(*it)); 
     515           
     516          splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it)); 
     517      splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it)); 
     518  } 
     519   
     520  stable_sort(splitCandidates.begin(), splitCandidates.end()); 
     521} 
     522 
     523 
     524float VspBspTree::BestCostRatio(const PolygonContainer &polys, 
     525                                                                const AxisAlignedBox3 &box, 
     526                                                                const int axis, 
     527                                                                float &position, 
     528                                                                int &objectsBack, 
     529                                int &objectsFront) const 
     530{ 
     531        vector<SortableEntry> splitCandidates; 
     532 
     533        SortSplitCandidates(polys, axis, splitCandidates); 
     534         
     535        // go through the lists, count the number of objects left and right 
     536        // and evaluate the following cost funcion: 
     537        // C = ct_div_ci  + (ol + or)/queries 
     538         
     539        int objectsLeft = 0, objectsRight = (int)polys.size(); 
     540         
     541        float minBox = box.Min(axis); 
     542        float maxBox = box.Max(axis); 
     543        float boxArea = box.SurfaceArea(); 
     544   
     545        float minBand = minBox + mSplitBorder * (maxBox - minBox); 
     546        float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox); 
     547         
     548        float minSum = 1e20f; 
     549        vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end(); 
     550 
     551        for(ci = splitCandidates.begin(); ci != ci_end; ++ ci)  
     552        { 
     553                switch ((*ci).type)  
     554                { 
     555                        case SortableEntry::POLY_MIN: 
     556                                ++ objectsLeft; 
     557                                break; 
     558                        case SortableEntry::POLY_MAX: 
     559                            -- objectsRight; 
     560                                break; 
     561                        default: 
     562                                break; 
     563                } 
     564                 
     565                if ((*ci).value > minBand && (*ci).value < maxBand)  
     566                { 
     567                        AxisAlignedBox3 lbox = box; 
     568                        AxisAlignedBox3 rbox = box; 
     569                        lbox.SetMax(axis, (*ci).value); 
     570                        rbox.SetMin(axis, (*ci).value); 
     571 
     572                        float sum = objectsLeft * lbox.SurfaceArea() +  
     573                                                objectsRight * rbox.SurfaceArea(); 
     574       
     575                        if (sum < minSum)  
     576                        { 
     577                                minSum = sum; 
     578                                position = (*ci).value; 
     579 
     580                                objectsBack = objectsLeft; 
     581                                objectsFront = objectsRight; 
     582                        } 
     583                } 
     584        } 
     585   
     586        float oldCost = (float)polys.size(); 
     587        float newCost = mAaCtDivCi + minSum / boxArea; 
     588        float ratio = newCost / oldCost; 
     589 
     590 
     591#if 0 
     592  Debug << "====================" << endl; 
     593  Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox) 
     594      << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl; 
     595#endif 
     596  return ratio; 
     597} 
     598 
     599bool VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 
     600                                        const PolygonContainer &polys) const 
     601{ 
     602        AxisAlignedBox3 box; 
     603        box.Initialize(); 
     604         
     605        // create bounding box of region 
     606        Polygon3::IncludeInBox(polys, box); 
     607         
     608        int objectsBack = 0, objectsFront = 0; 
     609        int axis = 0; 
     610        float costRatio = MAX_FLOAT; 
     611        Vector3 position; 
     612 
     613        //-- area subdivision 
     614        for (int i = 0; i < 3; ++ i)  
     615        { 
     616                float p = 0; 
     617                float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront); 
     618                 
     619                if (r < costRatio) 
     620                { 
     621                        costRatio = r; 
     622                        axis = i; 
     623                        position = p; 
     624                } 
     625        } 
     626         
     627        if (costRatio >= mMaxCostRatio) 
     628                return false; 
     629 
     630        Vector3 norm(0,0,0); norm[axis] = 1.0f; 
     631        plane = Plane3(norm, position); 
     632 
     633        return true; 
     634} 
     635 
     636Plane3 VspBspTree::SelectPlane(BspLeaf *leaf, VspBspTraversalData &data) 
     637{ 
     638        if ((mSplitPlaneStrategy & AXIS_ALIGNED) && 
     639                ((int)data.mRays->size() > mTermMinRaysForAxisAligned)) 
     640        { 
     641                Plane3 plane; 
     642                if (SelectAxisAlignedPlane(plane, *data.mPolygons)) // TODO: should be rays 
     643                        return plane; 
     644        } 
     645 
     646        // simplest strategy: just take next polygon 
     647        if (mSplitPlaneStrategy & RANDOM_POLYGON) 
     648        { 
     649        if (!data.mPolygons->empty()) 
     650                { 
     651                        const int randIdx = Random((int)data.mPolygons->size()); 
     652                        Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 
     653                        return nextPoly->GetSupportingPlane(); 
     654                } 
     655                else 
     656                { 
     657                        //-- choose plane on midpoint of a ray 
     658                        const int candidateIdx = Random((int)data.mRays->size()); 
     659                                                                         
     660                        const Vector3 minPt = (*data.mRays)[candidateIdx].ExtrapOrigin(); 
     661                        const Vector3 maxPt = (*data.mRays)[candidateIdx].ExtrapTermination(); 
     662 
     663                        const Vector3 pt = (maxPt + minPt) * 0.5; 
     664 
     665                        const Vector3 normal = (*data.mRays)[candidateIdx].mRay->GetDir(); 
     666                         
     667                        return Plane3(normal, pt); 
     668                } 
     669 
     670                return Plane3(); 
     671        } 
     672 
     673        // use heuristics to find appropriate plane 
     674        return SelectPlaneHeuristics(leaf, data);  
     675} 
     676 
     677Plane3 VspBspTree::SelectPlaneHeuristics(BspLeaf *leaf, VspBspTraversalData &data) 
     678{ 
     679        float lowestCost = MAX_FLOAT; 
     680        Plane3 bestPlane; 
     681        Plane3 plane; 
     682 
     683        int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
     684         
     685        int candidateIdx = limit; 
     686         
     687        for (int i = 0; i < limit; ++ i) 
     688        { 
     689                candidateIdx = GetNextCandidateIdx(candidateIdx, *data.mPolygons); 
     690                 
     691                Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
     692 
     693                // evaluate current candidate 
     694                const float candidateCost =  
     695                        SplitPlaneCost(poly->GetSupportingPlane(), data); 
     696 
     697                if (candidateCost < lowestCost) 
     698                { 
     699                        bestPlane = poly->GetSupportingPlane(); 
     700                        lowestCost = candidateCost; 
     701                } 
     702        } 
     703         
     704        //Debug << "lowest: " << lowestCost << endl; 
     705 
     706        //-- choose candidate planes extracted from rays 
     707        // we currently use different two methods chosen with 
     708        // equal probability 
     709         
     710        // take 3 ray endpoints, where two are minimum and one a maximum 
     711        // point or the other way round 
     712        for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 
     713        { 
     714                candidateIdx = Random((int)data.mRays->size()); 
     715         
     716                RayInfo rayInf = (*data.mRays)[candidateIdx]; 
     717 
     718                const Vector3 minPt = rayInf.ExtrapOrigin(); 
     719                const Vector3 maxPt = rayInf.ExtrapTermination(); 
     720 
     721                const Vector3 pt = (maxPt + minPt) * 0.5; 
     722                const Vector3 normal = Normalize(rayInf.mRay->GetDir()); 
     723 
     724                plane = Plane3(normal, pt); 
     725 
     726                const float candidateCost = SplitPlaneCost(plane, data); 
     727 
     728                if (candidateCost < lowestCost) 
     729                { 
     730                        bestPlane = plane;       
     731                        lowestCost = candidateCost; 
     732                } 
     733        } 
     734 
     735        // take plane normal as plane normal and the midpoint of the ray. 
     736        // PROBLEM: does not resemble any point where visibility is likely to change 
     737        //Debug << "lowest2: " << lowestCost << endl; 
     738        for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 
     739        { 
     740                Vector3 pt[3]; 
     741                int idx[3]; 
     742                int cmaxT = 0; 
     743                int cminT = 0; 
     744                bool chooseMin = false; 
     745 
     746                for (int j = 0; j < 3; j ++) 
     747                { 
     748                        idx[j] = Random((int)data.mRays->size() * 2); 
     749                                 
     750                        if (idx[j] >= (int)data.mRays->size()) 
     751                        { 
     752                                idx[j] -= (int)data.mRays->size(); 
     753                                 
     754                                chooseMin = (cminT < 2); 
     755                        } 
     756                        else 
     757                                chooseMin = (cmaxT < 2); 
     758 
     759                        RayInfo rayInf = (*data.mRays)[idx[j]]; 
     760                        pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 
     761                }        
     762                         
     763                plane = Plane3(pt[0], pt[1], pt[2]); 
     764 
     765                const float candidateCost = SplitPlaneCost(plane, data); 
     766 
     767                if (candidateCost < lowestCost) 
     768                { 
     769                        //Debug << "choose ray plane 2: " << candidateCost << endl; 
     770                        bestPlane = plane; 
     771                         
     772                        lowestCost = candidateCost; 
     773                } 
     774        }        
     775 
     776#ifdef _DEBUG 
     777        Debug << "plane lowest cost: " << lowestCost << endl; 
     778#endif 
     779        return bestPlane; 
     780} 
     781 
     782int VspBspTree::GetNextCandidateIdx(int currentIdx, PolygonContainer &polys) 
     783{ 
     784        const int candidateIdx = Random(currentIdx --); 
     785 
     786        // swap candidates to avoid testing same plane 2 times 
     787        std::swap(polys[currentIdx], polys[candidateIdx]); 
     788         
     789        return currentIdx; 
     790        //return Random((int)polys.size()); 
     791} 
     792 
     793 
     794inline void VspBspTree::GenerateUniqueIdsForPvs() 
     795{ 
     796        Intersectable::NewMail(); sBackId = ViewCell::sMailId; 
     797        Intersectable::NewMail(); sFrontId = ViewCell::sMailId; 
     798        Intersectable::NewMail(); sFrontAndBackId = ViewCell::sMailId; 
     799} 
     800 
     801float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane,  
     802                                                                 const VspBspTraversalData &data) 
     803{ 
     804        float val = 0; 
     805 
     806        float sumBalancedRays = 0; 
     807        float sumRaySplits = 0; 
     808         
     809        int frontPvs = 0; 
     810        int backPvs = 0; 
     811 
     812        // probability that view point lies in child 
     813        float pOverall = 0; 
     814        float pFront = 0; 
     815        float pBack = 0; 
     816 
     817        const bool pvsUseLen = false; 
     818 
     819        if (mSplitPlaneStrategy & PVS) 
     820        { 
     821                // create unique ids for pvs heuristics 
     822                GenerateUniqueIdsForPvs(); 
     823         
     824                if (mPvsUseArea) // use front and back cell areas to approximate volume 
     825                {        
     826                        // construct child geometry with regard to the candidate split plane 
     827                        BspNodeGeometry frontCell; 
     828                        BspNodeGeometry backCell; 
     829                 
     830                        data.mGeometry->SplitGeometry(frontCell,  
     831                                                                                  backCell,  
     832                                                                                  candidatePlane, 
     833                                                                                  mBox, 
     834                                                                                  mEpsilon); 
     835                 
     836                        pFront = frontCell.GetArea(); 
     837                        pBack = backCell.GetArea(); 
     838 
     839                        pOverall = data.mArea; 
     840                } 
     841        } 
     842                 
     843        int limit; 
     844        bool useRand; 
     845 
     846        // choose test polyongs randomly if over threshold 
     847        if ((int)data.mRays->size() > mMaxTests) 
     848        { 
     849                useRand = true; 
     850                limit = mMaxTests; 
     851        } 
    99852        else 
    100                 mFront = newChild; 
    101 } 
    102  
    103 void VspBspInterior::SetupChildLinks(VspBspNode *b, VspBspNode *f)  
    104 { 
    105     mBack = b; 
    106     mFront = f; 
    107 } 
    108  
    109 int VspBspInterior::SplitPolygons(PolygonContainer &polys,  
    110                                                                   PolygonContainer &frontPolys,  
    111                                                                   PolygonContainer &backPolys,  
    112                                                                   PolygonContainer &coincident) 
     853        { 
     854                useRand = false; 
     855                limit = (int)data.mRays->size(); 
     856        } 
     857 
     858        for (int i = 0; i < limit; ++ i) 
     859        { 
     860                const int testIdx = useRand ? Random(limit) : i; 
     861                RayInfo rayInf = (*data.mRays)[testIdx]; 
     862 
     863                VssRay *ray = rayInf.mRay; 
     864                const int cf = rayInf.ComputeRayIntersection(candidatePlane, ray->mT); 
     865 
     866                if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     867                { 
     868                        sumBalancedRays += cf; 
     869                } 
     870                 
     871                if (mSplitPlaneStrategy & BALANCED_RAYS) 
     872                { 
     873                        if (cf == 0) 
     874                                ++ sumRaySplits; 
     875                } 
     876 
     877                if (mSplitPlaneStrategy & PVS) 
     878                { 
     879                        // in case the ray intersects an object 
     880                        // assure that we only count the object  
     881                        // once for the front and once for the back side of the plane 
     882                         
     883                        // add the termination object 
     884                        AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs); 
     885                         
     886                        // add the source object 
     887                        AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs); 
     888                         
     889                        // use number or length of rays to approximate volume 
     890                        if (!mPvsUseArea) 
     891                        { 
     892                                float len = 1; 
     893 
     894                                if (pvsUseLen) // use length of rays 
     895                                        len = rayInf.SqrSegmentLength(); 
     896                         
     897                                pOverall += len; 
     898 
     899                                if (cf == 1) 
     900                                        pFront += len; 
     901                                if (cf == -1) 
     902                                        pBack += len; 
     903                                if (cf == 0) 
     904                                { 
     905                                        // use length of rays to approximate volume 
     906                                        if (pvsUseLen)  
     907                                        { 
     908                                                float newLen = len *  
     909                                                        (rayInf.GetMaxT() - rayInf.mRay->mT) /  
     910                                                        (rayInf.GetMaxT() - rayInf.GetMinT()); 
     911                 
     912                                                if (candidatePlane.Side(rayInf.ExtrapOrigin()) <= 0) 
     913                                                { 
     914                                                        pBack += newLen; 
     915                                                        pFront += len - newLen; 
     916                                                } 
     917                                                else 
     918                                                { 
     919                                                        pFront += newLen; 
     920                                                        pBack += len - newLen; 
     921                                                } 
     922                                        } 
     923                                        else 
     924                                        { 
     925                                                ++ pFront; 
     926                                                ++ pBack; 
     927                                        } 
     928                                } 
     929                        } 
     930                } 
     931        } 
     932 
     933        const float raysSize = (float)data.mRays->size() + Limits::Small; 
     934 
     935        if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     936                val += mLeastRaySplitsFactor * sumRaySplits / raysSize; 
     937 
     938        if (mSplitPlaneStrategy & BALANCED_RAYS) 
     939                val += mBalancedRaysFactor * fabs(sumBalancedRays) /  raysSize; 
     940 
     941        const float denom = pOverall * (float)data.mPvs * 2.0f + Limits::Small; 
     942 
     943        if (mSplitPlaneStrategy & PVS) 
     944        { 
     945                val += mPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom; 
     946 
     947                // give penalty to unbalanced split 
     948                if (1) 
     949                if (((pFront * 0.2 + Limits::Small) > pBack) ||  
     950                        (pFront < (pBack * 0.2 + Limits::Small))) 
     951                        val += 0.5; 
     952        } 
     953 
     954#ifdef _DEBUG 
     955        Debug << "totalpvs: " << pvs << " ptotal: " << pOverall 
     956                  << " frontpvs: " << frontPvs << " pFront: " << pFront  
     957                  << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl; 
     958#endif 
     959        return val; 
     960} 
     961 
     962void VspBspTree::AddObjToPvs(Intersectable *obj, 
     963                                                         const int cf, 
     964                                                         int &frontPvs, 
     965                                                         int &backPvs) const 
     966{ 
     967        if (!obj) 
     968                return; 
     969        // TODO: does this really belong to no pvs? 
     970        //if (cf == Ray::COINCIDENT) return; 
     971 
     972        // object belongs to both PVS 
     973        if (cf >= 0) 
     974        { 
     975                if ((obj->mMailbox != sFrontId) &&  
     976                        (obj->mMailbox != sFrontAndBackId)) 
     977                { 
     978                        ++ frontPvs; 
     979 
     980                        if (obj->mMailbox == sBackId) 
     981                                obj->mMailbox = sFrontAndBackId;         
     982                        else 
     983                                obj->mMailbox = sFrontId;                                                                
     984                } 
     985        } 
     986         
     987        if (cf <= 0) 
     988        { 
     989                if ((obj->mMailbox != sBackId) && 
     990                        (obj->mMailbox != sFrontAndBackId)) 
     991                { 
     992                        ++ backPvs; 
     993 
     994                        if (obj->mMailbox == sFrontId) 
     995                                obj->mMailbox = sFrontAndBackId;  
     996                        else 
     997                                obj->mMailbox = sBackId;                                 
     998                } 
     999        } 
     1000} 
     1001 
     1002void VspBspTree::CollectLeaves(vector<BspLeaf *> &leaves) const 
     1003{ 
     1004        stack<BspNode *> nodeStack; 
     1005        nodeStack.push(mRoot); 
     1006  
     1007        while (!nodeStack.empty())  
     1008        { 
     1009                BspNode *node = nodeStack.top(); 
     1010     
     1011                nodeStack.pop(); 
     1012     
     1013                if (node->IsLeaf())  
     1014                { 
     1015                        BspLeaf *leaf = (BspLeaf *)node;                 
     1016                        leaves.push_back(leaf); 
     1017                }  
     1018                else  
     1019                { 
     1020                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1021 
     1022                        nodeStack.push(interior->GetBack()); 
     1023                        nodeStack.push(interior->GetFront()); 
     1024                } 
     1025        } 
     1026} 
     1027 
     1028AxisAlignedBox3 VspBspTree::GetBoundingBox() const 
     1029{ 
     1030        return mBox; 
     1031} 
     1032 
     1033BspNode *VspBspTree::GetRoot() const 
     1034{ 
     1035        return mRoot; 
     1036} 
     1037 
     1038void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 
     1039{ 
     1040        // the node became a leaf -> evaluate stats for leafs 
     1041        BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode); 
     1042 
     1043        // store maximal and minimal depth 
     1044        if (data.mDepth > mStat.maxDepth) 
     1045                mStat.maxDepth = data.mDepth; 
     1046 
     1047        if (data.mDepth < mStat.minDepth) 
     1048                mStat.minDepth = data.mDepth; 
     1049 
     1050        // accumulate depth to compute average depth 
     1051        mStat.accumDepth += data.mDepth; 
     1052         
     1053 
     1054        if (data.mDepth >= mTermMaxDepth) 
     1055                ++ mStat.maxDepthNodes; 
     1056 
     1057        if (data.mPvs < mTermMinPvs) 
     1058                ++ mStat.minPvsNodes; 
     1059 
     1060        if ((int)data.mRays->size() < mTermMinRays) 
     1061                ++ mStat.minRaysNodes; 
     1062 
     1063        if (data.GetAvgRayContribution() > mTermMaxRayContribution) 
     1064                ++ mStat.maxRayContribNodes; 
     1065         
     1066        if (data.mGeometry->GetArea() <= mTermMinArea)  
     1067                ++ mStat.minAreaNodes; 
     1068 
     1069#ifdef _DEBUG 
     1070        Debug << "BSP stats: " 
     1071                  << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), " 
     1072                  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), " 
     1073                  << "Area: " << data.mArea << " (min: " << mTermMinArea << "), " 
     1074                  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "  
     1075                  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, " 
     1076                  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl; 
     1077#endif 
     1078} 
     1079 
     1080int VspBspTree::CastRay(Ray &ray) 
     1081{ 
     1082        int hits = 0; 
     1083   
     1084        stack<BspRayTraversalData> tStack; 
     1085   
     1086        float maxt, mint; 
     1087 
     1088        if (!mBox.GetRaySegment(ray, mint, maxt)) 
     1089                return 0; 
     1090 
     1091        Intersectable::NewMail(); 
     1092 
     1093        Vector3 entp = ray.Extrap(mint); 
     1094        Vector3 extp = ray.Extrap(maxt); 
     1095   
     1096        BspNode *node = mRoot; 
     1097        BspNode *farChild = NULL; 
     1098         
     1099        while (1) 
     1100        { 
     1101                if (!node->IsLeaf())  
     1102                { 
     1103                        BspInterior *in = dynamic_cast<BspInterior *>(node); 
     1104 
     1105                        Plane3 splitPlane = in->GetPlane(); 
     1106                        const int entSide = splitPlane.Side(entp); 
     1107                        const int extSide = splitPlane.Side(extp); 
     1108 
     1109                        if (entSide < 0) 
     1110                        { 
     1111                                node = in->GetBack(); 
     1112 
     1113                                if(extSide <= 0) // plane does not split ray => no far child 
     1114                                        continue; 
     1115                                         
     1116                                farChild = in->GetFront(); // plane splits ray 
     1117 
     1118                        } else if (entSide > 0) 
     1119                        { 
     1120                                node = in->GetFront(); 
     1121 
     1122                                if (extSide >= 0) // plane does not split ray => no far child 
     1123                                        continue; 
     1124 
     1125                                farChild = in->GetBack(); // plane splits ray                    
     1126                        } 
     1127                        else // ray and plane are coincident 
     1128                        { 
     1129                                // WHAT TO DO IN THIS CASE ? 
     1130                                //break; 
     1131                                node = in->GetFront(); 
     1132                                continue; 
     1133                        } 
     1134 
     1135                        // push data for far child 
     1136                        tStack.push(BspRayTraversalData(farChild, extp, maxt)); 
     1137 
     1138                        // find intersection of ray segment with plane 
     1139                        float t; 
     1140                        extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t); 
     1141                        maxt *= t; 
     1142                         
     1143                } else // reached leaf => intersection with view cell 
     1144                { 
     1145                        BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
     1146       
     1147                        if (!leaf->GetViewCell()->Mailed()) 
     1148                        { 
     1149                                //ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf)); 
     1150                                leaf->GetViewCell()->Mail(); 
     1151                                ++ hits; 
     1152                        } 
     1153                         
     1154                        //-- fetch the next far child from the stack 
     1155                        if (tStack.empty()) 
     1156                                break; 
     1157       
     1158                        entp = extp; 
     1159                        mint = maxt; // NOTE: need this? 
     1160 
     1161                        if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f) 
     1162                                break; 
     1163 
     1164                        BspRayTraversalData &s = tStack.top(); 
     1165 
     1166                        node = s.mNode; 
     1167                        extp = s.mExitPoint; 
     1168                        maxt = s.mMaxT; 
     1169 
     1170                        tStack.pop(); 
     1171                } 
     1172        } 
     1173 
     1174        return hits; 
     1175} 
     1176 
     1177bool VspBspTree::Export(const string filename) 
     1178{ 
     1179        Exporter *exporter = Exporter::GetExporter(filename); 
     1180 
     1181        if (exporter)  
     1182        { 
     1183                //exporter->ExportVspBspTree(*this); 
     1184                return true; 
     1185        }        
     1186 
     1187        return false; 
     1188} 
     1189 
     1190void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const 
     1191{ 
     1192        stack<BspNode *> nodeStack; 
     1193        nodeStack.push(mRoot); 
     1194 
     1195        ViewCell::NewMail(); 
     1196 
     1197        while (!nodeStack.empty())  
     1198        { 
     1199                BspNode *node = nodeStack.top(); 
     1200                nodeStack.pop(); 
     1201 
     1202                if (node->IsLeaf())  
     1203                { 
     1204                        ViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 
     1205 
     1206                        if (!viewCell->Mailed())  
     1207                        { 
     1208                                viewCell->Mail(); 
     1209                                viewCells.push_back(viewCell); 
     1210                        } 
     1211                } 
     1212                else  
     1213                { 
     1214                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1215 
     1216                        nodeStack.push(interior->GetFront()); 
     1217                        nodeStack.push(interior->GetBack()); 
     1218                } 
     1219        } 
     1220} 
     1221 
     1222void VspBspTree::EvaluateViewCellsStats(BspViewCellsStatistics &stat) const 
     1223{ 
     1224        stat.Reset(); 
     1225 
     1226        stack<BspNode *> nodeStack; 
     1227        nodeStack.push(mRoot); 
     1228 
     1229        ViewCell::NewMail(); 
     1230 
     1231        // exclude root cell 
     1232        mRootCell->Mail(); 
     1233 
     1234        while (!nodeStack.empty())  
     1235        { 
     1236                BspNode *node = nodeStack.top(); 
     1237                nodeStack.pop(); 
     1238 
     1239                if (node->IsLeaf())  
     1240                { 
     1241                        ++ stat.bspLeaves; 
     1242 
     1243                        BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 
     1244 
     1245                        if (!viewCell->Mailed())  
     1246                        { 
     1247                                viewCell->Mail(); 
     1248                                 
     1249                                ++ stat.viewCells; 
     1250                                const int pvsSize = viewCell->GetPvs().GetSize(); 
     1251 
     1252                stat.pvs += pvsSize; 
     1253 
     1254                                if (pvsSize < 1) 
     1255                                        ++ stat.emptyPvs; 
     1256 
     1257                                if (pvsSize > stat.maxPvs) 
     1258                                        stat.maxPvs = pvsSize; 
     1259 
     1260                                if (pvsSize < stat.minPvs) 
     1261                                        stat.minPvs = pvsSize; 
     1262 
     1263                                if ((int)viewCell->mBspLeaves.size() > stat.maxBspLeaves) 
     1264                                        stat.maxBspLeaves = (int)viewCell->mBspLeaves.size();            
     1265                        } 
     1266                } 
     1267                else  
     1268                { 
     1269                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1270 
     1271                        nodeStack.push(interior->GetFront()); 
     1272                        nodeStack.push(interior->GetBack()); 
     1273                } 
     1274        } 
     1275} 
     1276 
     1277BspTreeStatistics &VspBspTree::GetStat() 
     1278{ 
     1279        return mStat; 
     1280} 
     1281 
     1282float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const 
     1283{ 
     1284        float len = 0; 
     1285 
     1286        RayInfoContainer::const_iterator it, it_end = rays.end(); 
     1287 
     1288        for (it = rays.begin(); it != it_end; ++ it) 
     1289                len += (*it).SegmentLength(); 
     1290 
     1291        return len; 
     1292} 
     1293 
     1294int VspBspTree::SplitRays(const Plane3 &plane, 
     1295                                                  RayInfoContainer &rays,  
     1296                                                  RayInfoContainer &frontRays,  
     1297                                                  RayInfoContainer &backRays) 
     1298{ 
     1299        int splits = 0; 
     1300 
     1301        while (!rays.empty()) 
     1302        { 
     1303                RayInfo bRay = rays.back(); 
     1304                VssRay *ray = bRay.mRay; 
     1305 
     1306                rays.pop_back(); 
     1307         
     1308                // get classification and receive new t 
     1309                const int cf = bRay.ComputeRayIntersection(plane, ray->mT); 
     1310 
     1311                switch (cf) 
     1312                { 
     1313                case -1: 
     1314                        backRays.push_back(bRay); 
     1315                        break; 
     1316                case 1: 
     1317                        frontRays.push_back(bRay); 
     1318                        break; 
     1319                case 0:  
     1320                        //-- split ray 
     1321 
     1322                        // if start point behind plane 
     1323                        if (plane.Side(bRay.ExtrapOrigin()) <= 0) 
     1324                        {        
     1325                                backRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 
     1326                                frontRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 
     1327                        } 
     1328                        else 
     1329                        { 
     1330                                frontRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 
     1331                                backRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 
     1332                        } 
     1333                        break; 
     1334                default: 
     1335                        Debug << "Should not come here 4" << endl; 
     1336                        break; 
     1337                } 
     1338        } 
     1339 
     1340        return splits; 
     1341} 
     1342 
     1343void VspBspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const 
     1344{ 
     1345        BspNode *lastNode; 
     1346 
     1347        do 
     1348        { 
     1349                lastNode = n; 
     1350 
     1351                // want to get planes defining geometry of this node => don't take 
     1352                // split plane of node itself 
     1353                n = n->GetParent(); 
     1354                 
     1355                if (n) 
     1356                { 
     1357                        BspInterior *interior = dynamic_cast<BspInterior *>(n); 
     1358                        Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 
     1359 
     1360            if (interior->GetFront() != lastNode) 
     1361                                halfSpace.ReverseOrientation(); 
     1362 
     1363                        halfSpaces.push_back(halfSpace); 
     1364                } 
     1365        } 
     1366        while (n); 
     1367} 
     1368 
     1369void VspBspTree::ConstructGeometry(BspNode *n,  
     1370                                                                   BspNodeGeometry &cell) const 
     1371{ 
     1372        PolygonContainer polys; 
     1373        ConstructGeometry(n, polys); 
     1374        cell.mPolys = polys; 
     1375} 
     1376 
     1377void VspBspTree::ConstructGeometry(BspNode *n,  
     1378                                                                   PolygonContainer &cell) const 
     1379{ 
     1380        vector<Plane3> halfSpaces; 
     1381        ExtractHalfSpaces(n, halfSpaces); 
     1382 
     1383        PolygonContainer candidatePolys; 
     1384 
     1385        // bounded planes are added to the polygons (reverse polygons 
     1386        // as they have to be outfacing 
     1387        for (int i = 0; i < (int)halfSpaces.size(); ++ i) 
     1388        { 
     1389                Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]); 
     1390                 
     1391                if (p->Valid(mEpsilon)) 
     1392                { 
     1393                        candidatePolys.push_back(p->CreateReversePolygon()); 
     1394                        DEL_PTR(p); 
     1395                } 
     1396        } 
     1397 
     1398        // add faces of bounding box (also could be faces of the cell) 
     1399        for (int i = 0; i < 6; ++ i) 
     1400        { 
     1401                VertexContainer vertices; 
     1402         
     1403                for (int j = 0; j < 4; ++ j) 
     1404                        vertices.push_back(mBox.GetFace(i).mVertices[j]); 
     1405 
     1406                candidatePolys.push_back(new Polygon3(vertices)); 
     1407        } 
     1408 
     1409        for (int i = 0; i < (int)candidatePolys.size(); ++ i) 
     1410        { 
     1411                // polygon is split by all other planes 
     1412                for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 
     1413                { 
     1414                        if (i == j) // polygon and plane are coincident 
     1415                                continue; 
     1416 
     1417                        VertexContainer splitPts; 
     1418                        Polygon3 *frontPoly, *backPoly; 
     1419 
     1420                        const int cf =  
     1421                                candidatePolys[i]->ClassifyPlane(halfSpaces[j], 
     1422                                                                                                 mEpsilon); 
     1423                         
     1424                        switch (cf) 
     1425                        { 
     1426                                case Polygon3::SPLIT: 
     1427                                        frontPoly = new Polygon3(); 
     1428                                        backPoly = new Polygon3(); 
     1429 
     1430                                        candidatePolys[i]->Split(halfSpaces[j],  
     1431                                                                                         *frontPoly,  
     1432                                                                                         *backPoly, 
     1433                                                                                         mEpsilon); 
     1434 
     1435                                        DEL_PTR(candidatePolys[i]); 
     1436 
     1437                                        if (frontPoly->Valid(mEpsilon)) 
     1438                                                candidatePolys[i] = frontPoly; 
     1439                                        else 
     1440                                                DEL_PTR(frontPoly); 
     1441 
     1442                                        DEL_PTR(backPoly); 
     1443                                        break; 
     1444                                case Polygon3::BACK_SIDE: 
     1445                                        DEL_PTR(candidatePolys[i]); 
     1446                                        break; 
     1447                                // just take polygon as it is 
     1448                                case Polygon3::FRONT_SIDE: 
     1449                                case Polygon3::COINCIDENT: 
     1450                                default: 
     1451                                        break; 
     1452                        } 
     1453                } 
     1454                 
     1455                if (candidatePolys[i]) 
     1456                        cell.push_back(candidatePolys[i]); 
     1457        } 
     1458} 
     1459 
     1460void VspBspTree::ConstructGeometry(BspViewCell *vc, PolygonContainer &vcGeom) const 
     1461{ 
     1462        vector<BspLeaf *> leaves = vc->mBspLeaves; 
     1463 
     1464        vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 
     1465 
     1466        for (it = leaves.begin(); it != it_end; ++ it) 
     1467                ConstructGeometry(*it, vcGeom); 
     1468} 
     1469 
     1470int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,  
     1471                                                   const bool onlyUnmailed) const 
     1472{ 
     1473        PolygonContainer cell; 
     1474 
     1475        ConstructGeometry(n, cell); 
     1476 
     1477        stack<BspNode *> nodeStack; 
     1478        nodeStack.push(mRoot); 
     1479                 
     1480        // planes needed to verify that we found neighbor leaf. 
     1481        vector<Plane3> halfSpaces; 
     1482        ExtractHalfSpaces(n, halfSpaces); 
     1483 
     1484        while (!nodeStack.empty())  
     1485        { 
     1486                BspNode *node = nodeStack.top(); 
     1487                nodeStack.pop(); 
     1488 
     1489                if (node->IsLeaf()) 
     1490                { 
     1491            if (node != n && (!onlyUnmailed || !node->Mailed())) 
     1492                        { 
     1493                                // test all planes of current node if candidate really 
     1494                                // is neighbour 
     1495                                PolygonContainer neighborCandidate; 
     1496                                ConstructGeometry(node, neighborCandidate); 
     1497                                 
     1498                                bool isAdjacent = true; 
     1499                                for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i) 
     1500                                { 
     1501                                        const int cf =  
     1502                                                Polygon3::ClassifyPlane(neighborCandidate,  
     1503                                                                                                halfSpaces[i], 
     1504                                                                                                mEpsilon); 
     1505 
     1506                                        if (cf == Polygon3::BACK_SIDE) 
     1507                                                isAdjacent = false; 
     1508                                } 
     1509 
     1510                                if (isAdjacent) 
     1511                                        neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 
     1512 
     1513                                CLEAR_CONTAINER(neighborCandidate); 
     1514                        } 
     1515                } 
     1516                else  
     1517                { 
     1518                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1519         
     1520                        const int cf = Polygon3::ClassifyPlane(cell,  
     1521                                                                                                   interior->GetPlane(),  
     1522                                                                                                   mEpsilon); 
     1523 
     1524                        if (cf == Polygon3::FRONT_SIDE) 
     1525                                nodeStack.push(interior->GetFront()); 
     1526                        else 
     1527                                if (cf == Polygon3::BACK_SIDE) 
     1528                                        nodeStack.push(interior->GetBack()); 
     1529                                else  
     1530                                { 
     1531                                        // random decision 
     1532                                        nodeStack.push(interior->GetBack()); 
     1533                                        nodeStack.push(interior->GetFront()); 
     1534                                } 
     1535                } 
     1536        } 
     1537         
     1538        CLEAR_CONTAINER(cell); 
     1539        return (int)neighbors.size(); 
     1540} 
     1541 
     1542BspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace) 
     1543{ 
     1544    stack<BspNode *> nodeStack; 
     1545        nodeStack.push(mRoot); 
     1546         
     1547        int mask = rand(); 
     1548   
     1549        while (!nodeStack.empty())  
     1550        { 
     1551                BspNode *node = nodeStack.top(); 
     1552                nodeStack.pop(); 
     1553           
     1554                if (node->IsLeaf())  
     1555                { 
     1556                        return dynamic_cast<BspLeaf *>(node); 
     1557                }  
     1558                else  
     1559                { 
     1560                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1561                         
     1562                        BspNode *next; 
     1563         
     1564                        PolygonContainer cell; 
     1565 
     1566                        // todo: not very efficient: constructs full cell everytime 
     1567                        ConstructGeometry(interior, cell); 
     1568 
     1569                        const int cf = Polygon3::ClassifyPlane(cell, halfspace, mEpsilon); 
     1570 
     1571                        if (cf == Polygon3::BACK_SIDE) 
     1572                                next = interior->GetFront(); 
     1573                        else 
     1574                                if (cf == Polygon3::FRONT_SIDE) 
     1575                                        next = interior->GetFront(); 
     1576                        else  
     1577                        { 
     1578                                // random decision 
     1579                                if (mask & 1) 
     1580                                        next = interior->GetBack(); 
     1581                                else 
     1582                                        next = interior->GetFront(); 
     1583                                mask = mask >> 1; 
     1584                        } 
     1585 
     1586                        nodeStack.push(next); 
     1587                } 
     1588        } 
     1589         
     1590        return NULL; 
     1591} 
     1592 
     1593BspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed) 
     1594{ 
     1595        stack<BspNode *> nodeStack; 
     1596         
     1597        nodeStack.push(mRoot); 
     1598 
     1599        int mask = rand(); 
     1600         
     1601        while (!nodeStack.empty())  
     1602        { 
     1603                BspNode *node = nodeStack.top(); 
     1604                nodeStack.pop(); 
     1605                 
     1606                if (node->IsLeaf())  
     1607                { 
     1608                        if ( (!onlyUnmailed || !node->Mailed()) ) 
     1609                                return dynamic_cast<BspLeaf *>(node); 
     1610                } 
     1611                else  
     1612                { 
     1613                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1614 
     1615                        // random decision 
     1616                        if (mask & 1) 
     1617                                nodeStack.push(interior->GetBack()); 
     1618                        else 
     1619                                nodeStack.push(interior->GetFront()); 
     1620 
     1621                        mask = mask >> 1; 
     1622                } 
     1623        } 
     1624         
     1625        return NULL; 
     1626} 
     1627 
     1628int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const 
     1629{ 
     1630        int pvsSize = 0; 
     1631 
     1632        RayInfoContainer::const_iterator rit, rit_end = rays.end(); 
     1633 
     1634        Intersectable::NewMail(); 
     1635 
     1636        for (rit = rays.begin(); rit != rays.end(); ++ rit) 
     1637        { 
     1638                VssRay *ray = (*rit).mRay; 
     1639                 
     1640                if (ray->mOriginObject) 
     1641                { 
     1642                        if (!ray->mOriginObject->Mailed()) 
     1643                        { 
     1644                                ray->mOriginObject->Mail(); 
     1645                                ++ pvsSize; 
     1646                        } 
     1647                } 
     1648                if (ray->mTerminationObject) 
     1649                { 
     1650                        if (!ray->mTerminationObject->Mailed()) 
     1651                        { 
     1652                                ray->mTerminationObject->Mail(); 
     1653                                ++ pvsSize; 
     1654                        } 
     1655                } 
     1656        } 
     1657 
     1658        return pvsSize; 
     1659} 
     1660 
     1661float VspBspTree::GetEpsilon() const 
     1662{ 
     1663        return mEpsilon; 
     1664} 
     1665 
     1666BspViewCell *VspBspTree::GetRootCell() const 
     1667{ 
     1668        return mRootCell; 
     1669} 
     1670 
     1671int VspBspTree::SplitPolygons(const Plane3 &plane, 
     1672                                                          PolygonContainer &polys,  
     1673                                                          PolygonContainer &frontPolys,  
     1674                                                          PolygonContainer &backPolys,  
     1675                                                          PolygonContainer &coincident) const 
    1131676{ 
    1141677        int splits = 0; 
     
    1201683 
    1211684                // classify polygon 
    122                 const int cf = poly->ClassifyPlane(mPlane); 
     1685                const int cf = poly->ClassifyPlane(plane, mEpsilon); 
    1231686 
    1241687                switch (cf) 
     
    1461709        return splits; 
    1471710} 
    148  
    149 /****************************************************************/ 
    150 /*                  class VspBspLeaf implementation                */ 
    151 /****************************************************************/ 
    152 VspBspLeaf::VspBspLeaf(): mViewCell(NULL) 
    153 { 
    154 } 
    155  
    156 VspBspLeaf::VspBspLeaf(BspViewCell *viewCell):  
    157 mViewCell(viewCell) 
    158 { 
    159 } 
    160  
    161 VspBspLeaf::VspBspLeaf(VspBspInterior *parent):  
    162 VspBspNode(parent), mViewCell(NULL) 
    163 {} 
    164  
    165 VspBspLeaf::VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell):  
    166 VspBspNode(parent), mViewCell(viewCell) 
    167 { 
    168 } 
    169  
    170 BspViewCell *VspBspLeaf::GetViewCell() const 
    171 { 
    172         return mViewCell; 
    173 } 
    174  
    175 void VspBspLeaf::SetViewCell(BspViewCell *viewCell) 
    176 { 
    177         mViewCell = viewCell; 
    178 } 
    179  
    180 bool VspBspLeaf::IsLeaf() const  
    181 {  
    182         return true;  
    183 } 
    184  
    185 void VspBspLeaf::AddToPvs(const RayInfoContainer &rays,  
    186                                                   int &sampleContributions, 
    187                                                   int &contributingSamples, 
    188                                                   bool storeLeavesWithRays) 
    189 { 
    190         sampleContributions = 0; 
    191         contributingSamples = 0; 
    192  
    193     RayInfoContainer::const_iterator it, it_end = rays.end(); 
    194  
    195         // add contributions from samples to the PVS 
    196         for (it = rays.begin(); it != it_end; ++ it) 
    197         { 
    198                 int contribution = 0; 
    199                 VssRay *ray = (*it).mRay; 
    200                          
    201                 if (ray->mTerminationObject) 
    202                         contribution += mViewCell->GetPvs().AddSample(ray->mTerminationObject); 
    203                  
    204                 if (ray->mOriginObject) 
    205                         contribution += mViewCell->GetPvs().AddSample(ray->mOriginObject); 
    206  
    207                 if (contribution > 0) 
    208                 { 
    209                         sampleContributions += contribution; 
    210                         ++ contributingSamples; 
    211                 } 
    212         } 
    213 } 
    214  
    215  
    216 /****************************************************************/ 
    217 /*                  class VspBspTree implementation             */ 
    218 /****************************************************************/ 
    219  
    220 VspBspTree::VspBspTree():  
    221 mRoot(NULL), 
    222 mPvsUseArea(true) 
    223 { 
    224         mRootCell = new BspViewCell(); 
    225  
    226         Randomize(); // initialise random generator for heuristics 
    227  
    228         //-- termination criteria for autopartition 
    229         environment->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth); 
    230         environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs); 
    231         environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays); 
    232         environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea);      
    233         environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution); 
    234         environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength); 
    235  
    236         //-- factors for bsp tree split plane heuristics 
    237         environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor); 
    238         environment->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor); 
    239         environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi); 
    240  
    241         //-- termination criteria for axis aligned split 
    242         environment->GetFloatValue("VspBspTree.Termination.AxisAligned.ct_div_ci", mAaCtDivCi); 
    243         environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxCostRatio", mMaxCostRatio); 
    244          
    245         environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays",  
    246                                                          mTermMinRaysForAxisAligned); 
    247          
    248         //-- partition criteria 
    249         environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates); 
    250         environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates); 
    251         environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy); 
    252         environment->GetFloatValue("VspBspTree.AxisAligned.splitBorder", mSplitBorder); 
    253  
    254         environment->GetFloatValue("VspBspTree.Construction.sideTolerance", Vector3::sDistTolerance); 
    255         Vector3::sDistToleranceSqrt = Vector3::sDistTolerance * Vector3::sDistTolerance; 
    256  
    257     Debug << "BSP max depth: " << mTermMaxDepth << endl; 
    258         Debug << "BSP min PVS: " << mTermMinPvs << endl; 
    259         Debug << "BSP min area: " << mTermMinArea << endl; 
    260         Debug << "BSP min rays: " << mTermMinRays << endl; 
    261         Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl; 
    262         Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl; 
    263  
    264         Debug << "Split plane strategy: "; 
    265         if (mSplitPlaneStrategy & RANDOM_POLYGON) 
    266                 Debug << "random polygon "; 
    267         if (mSplitPlaneStrategy & AXIS_ALIGNED) 
    268                 Debug << "axis aligned "; 
    269         if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    270                 Debug << "least ray splits "; 
    271         if (mSplitPlaneStrategy & BALANCED_RAYS) 
    272                 Debug << "balanced rays "; 
    273         if (mSplitPlaneStrategy & PVS) 
    274                 Debug << "pvs"; 
    275  
    276         Debug << endl; 
    277 } 
    278  
    279  
    280 const VspBspTreeStatistics &VspBspTree::GetStatistics() const  
    281 { 
    282         return mStat; 
    283 } 
    284  
    285 void VspBspTreeStatistics::Print(ostream &app) const 
    286 { 
    287         app << "===== VspBspTree statistics ===============\n"; 
    288  
    289         app << setprecision(4); 
    290  
    291         app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n"; 
    292  
    293         app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 
    294  
    295         app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n"; 
    296  
    297         app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 
    298  
    299         app << "#N_SPLITS ( Number of splits )\n" << splits << "\n"; 
    300  
    301         app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n"  
    302                 <<      maxDepthNodes * 100 / (double)Leaves() << endl; 
    303  
    304         app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n"  
    305                 <<      maxDepthNodes * 100 / (double)Leaves() << endl; 
    306  
    307         app << "#N_PMINPVSLEAVES  ( Percentage of leaves with mininimal PVS )\n"  
    308                 << minPvsNodes * 100 / (double)Leaves() << endl; 
    309  
    310         app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minimal number of rays)\n"  
    311                 <<      minRaysNodes * 100 / (double)Leaves() << endl; 
    312  
    313         app << "#N_PMINAREALEAVES  ( Percentage of leaves with mininum area )\n" 
    314                 << minAreaNodes * 100 / (double)Leaves() << endl; 
    315  
    316         app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n"  
    317                 <<      maxRayContribNodes * 100 / (double)Leaves() << endl; 
    318  
    319         app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl; 
    320  
    321         app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl; 
    322  
    323         app << "#AVGDEPTH ( average depth )\n" << AvgDepth() << endl; 
    324  
    325         app << "#N_INPUT_POLYGONS (number of input polygons )\n" <<     polys << endl; 
    326  
    327         //app << "#N_PVS: " << pvs << endl; 
    328  
    329         app << "#N_ROUTPUT_INPUT_POLYGONS ( ratio polygons after subdivision / input polygons )\n" << 
    330                  (polys + splits) / (double)polys << endl; 
    331          
    332         app << "===== END OF VspBspTree statistics ==========\n"; 
    333 } 
    334  
    335  
    336 VspBspTree::~VspBspTree() 
    337 { 
    338         DEL_PTR(mRoot); 
    339         DEL_PTR(mRootCell); 
    340 } 
    341  
    342 int VspBspTree::AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent) 
    343 { 
    344         FaceContainer::const_iterator fi; 
    345          
    346         // copy the face data to polygons 
    347         for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi) 
    348         { 
    349                 Polygon3 *poly = new Polygon3((*fi), mesh); 
    350                  
    351                 if (poly->Valid()) 
    352                 { 
    353                         poly->mParent = parent; // set parent intersectable 
    354                         polys.push_back(poly); 
    355                 } 
    356                 else 
    357                         DEL_PTR(poly); 
    358         } 
    359         return (int)mesh->mFaces.size(); 
    360 } 
    361  
    362 int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells,  
    363                                                           PolygonContainer &polys,  
    364                                                           int maxObjects) 
    365 { 
    366         int limit = (maxObjects > 0) ?  
    367                 Min((int)viewCells.size(), maxObjects) : (int)viewCells.size(); 
    368    
    369         int polysSize = 0; 
    370  
    371         for (int i = 0; i < limit; ++ i) 
    372         { 
    373                 if (viewCells[i]->GetMesh()) // copy the mesh data to polygons 
    374                 { 
    375                         mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb 
    376                         polysSize += AddMeshToPolygons(viewCells[i]->GetMesh(), polys, viewCells[i]); 
    377                 } 
    378         } 
    379  
    380         return polysSize; 
    381 } 
    382  
    383 int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects) 
    384 { 
    385         int limit = (maxObjects > 0) ? Min((int)objects.size(), maxObjects) : (int)objects.size(); 
    386    
    387         for (int i = 0; i < limit; ++i) 
    388         { 
    389                 Intersectable *object = objects[i];//*it; 
    390                 Mesh *mesh = NULL; 
    391  
    392                 switch (object->Type()) // extract the meshes 
    393                 { 
    394                 case Intersectable::MESH_INSTANCE: 
    395                         mesh = dynamic_cast<MeshInstance *>(object)->GetMesh(); 
    396                         break; 
    397                 case Intersectable::VIEW_CELL: 
    398                         mesh = dynamic_cast<ViewCell *>(object)->GetMesh(); 
    399                         break; 
    400                         // TODO: handle transformed mesh instances 
    401                 default: 
    402                         Debug << "intersectable type not supported" << endl; 
    403                         break; 
    404                 } 
    405                  
    406         if (mesh) // copy the mesh data to polygons 
    407                 { 
    408                         mBox.Include(object->GetBox()); // add to BSP tree aabb 
    409                         AddMeshToPolygons(mesh, polys, mRootCell); 
    410                 } 
    411         } 
    412  
    413         return (int)polys.size(); 
    414 } 
    415  
    416 void VspBspTree::Construct(const VssRayContainer &sampleRays) 
    417 { 
    418     mStat.nodes = 1; 
    419         mBox.Initialize();      // initialise BSP tree bounding box 
    420          
    421         PolygonContainer polys; 
    422         RayInfoContainer *rays = new RayInfoContainer(); 
    423  
    424         VssRayContainer::const_iterator rit, rit_end = sampleRays.end(); 
    425  
    426         long startTime = GetTime(); 
    427  
    428         Debug << "**** Extracting polygons from rays ****\n"; 
    429  
    430         //-- extract polygons intersected by the rays 
    431         for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
    432         { 
    433                 VssRay *ray = *rit; 
    434          
    435                 if (ray->mTerminationObject) 
    436                 { 
    437                         MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject); 
    438                         AddMeshToPolygons(obj->GetMesh(), polys, obj); 
    439                 } 
    440  
    441                 if (ray->mOriginObject) 
    442                 { 
    443                         MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject); 
    444                         AddMeshToPolygons(obj->GetMesh(), polys, obj); 
    445                 } 
    446         } 
    447  
    448         //-- store rays 
    449         for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
    450         { 
    451                 rays->push_back(RayInfo(*rit)); 
    452         } 
    453  
    454         mStat.polys = (int)polys.size(); 
    455  
    456         Debug << "**** Finished polygon extraction ****" << endl; 
    457         Debug << (int)polys.size() << " polys extracted from " << (int)sampleRays.size() << " rays" << endl; 
    458         Debug << "extraction time: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
    459  
    460         Construct(new PolygonContainer(polys), rays); 
    461  
    462         // clean up polygons because they are not deleted in the tree 
    463         CLEAR_CONTAINER(polys); 
    464 } 
    465  
    466 void VspBspTree::Construct(PolygonContainer *polys, RayInfoContainer *rays) 
    467 { 
    468         std::stack<VspBspTraversalData> tStack; 
    469  
    470         mRoot = new VspBspLeaf(); 
    471  
    472         VspBspNodeGeometry *cell = new VspBspNodeGeometry(); 
    473         ConstructGeometry(mRoot, *cell); 
    474  
    475         VspBspTraversalData tData(mRoot, polys, 0, mRootCell, rays,  
    476                                                    ComputePvsSize(*rays), cell->GetArea(), cell); 
    477  
    478         tStack.push(tData); 
    479  
    480         mStat.Start(); 
    481         cout << "Contructing bsp tree ... "; 
    482         long startTime = GetTime(); 
    483         while (!tStack.empty())  
    484         { 
    485                 tData = tStack.top(); 
    486  
    487             tStack.pop(); 
    488  
    489                 // subdivide leaf node 
    490                 VspBspNode *r = Subdivide(tStack, tData); 
    491  
    492                 if (r == mRoot) 
    493                         Debug << "BSP tree construction time spent at root: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
    494         } 
    495  
    496         cout << "finished\n"; 
    497  
    498         mStat.Stop(); 
    499 } 
    500  
    501 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const 
    502 { 
    503         return  
    504                 (((int)data.mRays->size() <= mTermMinRays) || 
    505                  (data.mPvs <= mTermMinPvs) || 
    506                  (data.mArea <= mTermMinArea) || 
    507                  (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 
    508                  (data.mDepth >= mTermMaxDepth)); 
    509 } 
    510  
    511 VspBspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData) 
    512 { 
    513         //-- terminate traversal   
    514         if (TerminationCriteriaMet(tData))               
    515         { 
    516                 VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(tData.mNode); 
    517          
    518                 BspViewCell *viewCell = new BspViewCell(); 
    519                  
    520                 leaf->SetViewCell(viewCell); 
    521                 //TODO viewCell->mVspBspLeaves.push_back(leaf); 
    522  
    523                 //-- add pvs 
    524                 if (viewCell != mRootCell) 
    525                 { 
    526                         int conSamp = 0, sampCon = 0; 
    527                         leaf->AddToPvs(*tData.mRays, conSamp, sampCon); 
    528                          
    529                         mStat.contributingSamples += conSamp; 
    530                         mStat.sampleContributions += sampCon; 
    531                 } 
    532  
    533                 EvaluateLeafStats(tData); 
    534                  
    535                 //-- clean up 
    536  
    537                 DEL_PTR(tData.mPolygons); 
    538                 DEL_PTR(tData.mRays); 
    539                 DEL_PTR(tData.mGeometry); 
    540                  
    541                 return leaf; 
    542         } 
    543  
    544         //-- continue subdivision 
    545         PolygonContainer coincident; 
    546          
    547         VspBspTraversalData tFrontData(NULL, new PolygonContainer(), tData.mDepth + 1, mRootCell,  
    548                                                                 new RayInfoContainer(), 0, 0, new VspBspNodeGeometry()); 
    549         VspBspTraversalData tBackData(NULL, new PolygonContainer(), tData.mDepth + 1, mRootCell,  
    550                                                            new RayInfoContainer(), 0, 0, new VspBspNodeGeometry()); 
    551  
    552         // create new interior node and two leaf nodes 
    553         VspBspInterior *interior =  
    554                 SubdivideNode(tData, tFrontData, tBackData, coincident); 
    555  
    556 #ifdef _DEBUG    
    557         if (frontPolys->empty() && backPolys->empty() && (coincident.size() > 2)) 
    558         {       for (PolygonContainer::iterator it = coincident.begin(); it != coincident.end(); ++it) 
    559                         Debug << (*it) << " " << (*it)->GetArea() << " " << (*it)->mParent << endl ; 
    560                 Debug << endl;} 
    561 #endif 
    562  
    563         // don't need coincident polygons anymory 
    564         CLEAR_CONTAINER(coincident); 
    565  
    566         // push the children on the stack 
    567         tStack.push(tFrontData); 
    568         tStack.push(tBackData); 
    569  
    570         // cleanup 
    571         DEL_PTR(tData.mNode); 
    572         DEL_PTR(tData.mPolygons); 
    573         DEL_PTR(tData.mRays); 
    574         DEL_PTR(tData.mGeometry);                
    575  
    576         return interior; 
    577 } 
    578  
    579 VspBspInterior *VspBspTree::SubdivideNode(VspBspTraversalData &tData, 
    580                                                                         VspBspTraversalData &frontData, 
    581                                                                         VspBspTraversalData &backData, 
    582                                                                         PolygonContainer &coincident) 
    583 { 
    584         mStat.nodes += 2; 
    585          
    586         VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(tData.mNode); 
    587         // select subdivision plane 
    588         VspBspInterior *interior =  
    589                 new VspBspInterior(SelectPlane(leaf, tData));  
    590  
    591 #ifdef _DEBUG 
    592         Debug << interior << endl; 
    593 #endif 
    594          
    595         // subdivide rays into front and back rays 
    596         SplitRays(interior->mPlane, *tData.mRays, *frontData.mRays, *backData.mRays); 
    597          
    598         // subdivide polygons with plane 
    599         mStat.splits += interior->SplitPolygons(*tData.mPolygons,  
    600                                                     *frontData.mPolygons,  
    601                                                                                         *backData.mPolygons,  
    602                                                                                         coincident); 
    603  
    604     // compute pvs 
    605         frontData.mPvs = ComputePvsSize(*frontData.mRays); 
    606         backData.mPvs = ComputePvsSize(*backData.mRays); 
    607  
    608         // split geometry and compute area 
    609         if (1) 
    610         { 
    611                 tData.mGeometry->SplitGeometry(*frontData.mGeometry,  
    612                                                                            *backData.mGeometry,  
    613                                                                            *this,  
    614                                                                            interior->mPlane); 
    615          
    616                  
    617                 frontData.mArea = frontData.mGeometry->GetArea(); 
    618                 backData.mArea = backData.mGeometry->GetArea(); 
    619         } 
    620  
    621         // compute accumulated ray length 
    622         //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays); 
    623         //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays); 
    624  
    625         //-- create front and back leaf 
    626  
    627         VspBspInterior *parent = leaf->GetParent(); 
    628  
    629         // replace a link from node's parent 
    630         if (!leaf->IsRoot()) 
    631         { 
    632                 parent->ReplaceChildLink(leaf, interior); 
    633                 interior->SetParent(parent); 
    634         } 
    635         else // new root 
    636         { 
    637                 mRoot = interior; 
    638         } 
    639  
    640         // and setup child links 
    641         interior->SetupChildLinks(new VspBspLeaf(interior), new VspBspLeaf(interior)); 
    642          
    643         frontData.mNode = interior->mFront; 
    644         backData.mNode = interior->mBack; 
    645          
    646         //DEL_PTR(leaf); 
    647         return interior; 
    648 } 
    649  
    650 void VspBspTree::SortSplitCandidates(const PolygonContainer &polys,  
    651                                                                   const int axis,  
    652                                                                   vector<SortableEntry> &splitCandidates) const 
    653 { 
    654   splitCandidates.clear(); 
    655    
    656   int requestedSize = 2 * (int)polys.size(); 
    657   // creates a sorted split candidates array   
    658   splitCandidates.reserve(requestedSize); 
    659    
    660   PolygonContainer::const_iterator it, it_end = polys.end(); 
    661  
    662   AxisAlignedBox3 box; 
    663  
    664   // insert all queries  
    665   for(it = polys.begin(); it != it_end; ++ it) 
    666   { 
    667           box.Initialize(); 
    668           box.Include(*(*it)); 
    669            
    670           splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it)); 
    671       splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it)); 
    672   } 
    673    
    674   stable_sort(splitCandidates.begin(), splitCandidates.end()); 
    675 } 
    676  
    677  
    678 float VspBspTree::BestCostRatio(const PolygonContainer &polys, 
    679                                                          const AxisAlignedBox3 &box, 
    680                                                          const int axis, 
    681                                                          float &position, 
    682                                                          int &objectsBack, 
    683                                                          int &objectsFront) const 
    684 { 
    685         vector<SortableEntry> splitCandidates; 
    686  
    687         SortSplitCandidates(polys, axis, splitCandidates); 
    688          
    689         // go through the lists, count the number of objects left and right 
    690         // and evaluate the following cost funcion: 
    691         // C = ct_div_ci  + (ol + or)/queries 
    692          
    693         int objectsLeft = 0, objectsRight = (int)polys.size(); 
    694          
    695         float minBox = box.Min(axis); 
    696         float maxBox = box.Max(axis); 
    697         float boxArea = box.SurfaceArea(); 
    698    
    699         float minBand = minBox + mSplitBorder * (maxBox - minBox); 
    700         float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox); 
    701          
    702         float minSum = 1e20f; 
    703         vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end(); 
    704  
    705         for(ci = splitCandidates.begin(); ci != ci_end; ++ ci)  
    706         { 
    707                 switch ((*ci).type)  
    708                 { 
    709                         case SortableEntry::POLY_MIN: 
    710                                 ++ objectsLeft; 
    711                                 break; 
    712                         case SortableEntry::POLY_MAX: 
    713                             -- objectsRight; 
    714                                 break; 
    715                         default: 
    716                                 break; 
    717                 } 
    718                  
    719                 if ((*ci).value > minBand && (*ci).value < maxBand)  
    720                 { 
    721                         AxisAlignedBox3 lbox = box; 
    722                         AxisAlignedBox3 rbox = box; 
    723                         lbox.SetMax(axis, (*ci).value); 
    724                         rbox.SetMin(axis, (*ci).value); 
    725  
    726                         float sum = objectsLeft * lbox.SurfaceArea() +  
    727                                                 objectsRight * rbox.SurfaceArea(); 
    728        
    729                         if (sum < minSum)  
    730                         { 
    731                                 minSum = sum; 
    732                                 position = (*ci).value; 
    733  
    734                                 objectsBack = objectsLeft; 
    735                                 objectsFront = objectsRight; 
    736                         } 
    737                 } 
    738         } 
    739    
    740         float oldCost = (float)polys.size(); 
    741         float newCost = mAaCtDivCi + minSum / boxArea; 
    742         float ratio = newCost / oldCost; 
    743  
    744  
    745 #if 0 
    746   Debug << "====================" << endl; 
    747   Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox) 
    748       << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl; 
    749 #endif 
    750   return ratio; 
    751 } 
    752  
    753 bool VspBspTree::SelectAxisAlignedPlane(Plane3 &plane,  
    754                                                                          const PolygonContainer &polys) const 
    755 { 
    756         AxisAlignedBox3 box; 
    757         box.Initialize(); 
    758          
    759         // create bounding box of region 
    760         Polygon3::IncludeInBox(polys, box); 
    761          
    762         int objectsBack = 0, objectsFront = 0; 
    763         int axis = 0; 
    764         float costRatio = MAX_FLOAT; 
    765         Vector3 position; 
    766  
    767         //-- area subdivision 
    768         for (int i = 0; i < 3; ++ i)  
    769         { 
    770                 float p = 0; 
    771                 float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront); 
    772                  
    773                 if (r < costRatio) 
    774                 { 
    775                         costRatio = r; 
    776                         axis = i; 
    777                         position = p; 
    778                 } 
    779         } 
    780          
    781         if (costRatio >= mMaxCostRatio) 
    782                 return false; 
    783  
    784         Vector3 norm(0,0,0); norm[axis] = 1.0f; 
    785         plane = Plane3(norm, position); 
    786  
    787         return true; 
    788 } 
    789  
    790 Plane3 VspBspTree::SelectPlane(VspBspLeaf *leaf, VspBspTraversalData &data) 
    791 { 
    792         if ((mSplitPlaneStrategy & AXIS_ALIGNED) && 
    793                 ((int)data.mRays->size() > mTermMinRaysForAxisAligned)) 
    794         { 
    795                 Plane3 plane; 
    796                 if (SelectAxisAlignedPlane(plane, *data.mPolygons)) // TODO: should be rays 
    797                         return plane; 
    798         } 
    799  
    800         // simplest strategy: just take next polygon 
    801         if (mSplitPlaneStrategy & RANDOM_POLYGON) 
    802         { 
    803         if (!data.mPolygons->empty()) 
    804                 { 
    805                         Polygon3 *nextPoly = (*data.mPolygons)[Random((int)data.mPolygons->size())]; 
    806                         return nextPoly->GetSupportingPlane(); 
    807                 } 
    808                 else 
    809                 { 
    810                         //-- choose plane on midpoint of a ray 
    811                         const int candidateIdx = Random((int)data.mRays->size()); 
    812                                                                  
    813                         const Vector3 minPt = (*data.mRays)[candidateIdx].ExtrapOrigin(); 
    814                         const Vector3 maxPt = (*data.mRays)[candidateIdx].ExtrapTermination(); 
    815  
    816                         const Vector3 pt = (maxPt + minPt) * 0.5; 
    817  
    818                         const Vector3 normal =  (*data.mRays)[candidateIdx].mRay->GetDir(); 
    819                          
    820                         return Plane3(normal, pt); 
    821                 } 
    822  
    823                 return Plane3(); 
    824         } 
    825  
    826         // use heuristics to find appropriate plane 
    827         return SelectPlaneHeuristics(leaf, data);  
    828 } 
    829  
    830 Plane3 VspBspTree::SelectPlaneHeuristics(VspBspLeaf *leaf, VspBspTraversalData &data) 
    831 { 
    832         float lowestCost = MAX_FLOAT; 
    833         Plane3 bestPlane; 
    834         Plane3 plane; 
    835  
    836         int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
    837          
    838         int candidateIdx = limit; 
    839  
    840         for (int i = 0; i < limit; ++ i) 
    841         { 
    842                 candidateIdx = GetNextCandidateIdx(candidateIdx, *data.mPolygons); 
    843                  
    844                 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
    845                 // evaluate current candidate 
    846                 const float candidateCost =  
    847                         SplitPlaneCost(poly->GetSupportingPlane(), data); 
    848  
    849                 if (candidateCost < lowestCost) 
    850                 { 
    851                         bestPlane = poly->GetSupportingPlane(); 
    852                         lowestCost = candidateCost; 
    853                 } 
    854         } 
    855          
    856         //Debug << "lowest: " << lowestCost << endl; 
    857  
    858         //-- choose candidate planes extracted from rays 
    859         // we currently use different two methods chosen with 
    860         // equal probability 
    861          
    862         RayInfoContainer *rays = data.mRays; 
    863         // take 3 ray endpoints, where two are minimum and one a maximum 
    864         // point or the other way round 
    865         for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 
    866         { 
    867                 candidateIdx = Random((int)rays->size()); 
    868          
    869                 RayInfo rayInf = (*rays)[candidateIdx]; 
    870                 const Vector3 minPt = rayInf.ExtrapOrigin(); 
    871                 const Vector3 maxPt = rayInf.ExtrapTermination(); 
    872  
    873                 const Vector3 pt = (maxPt + minPt) * 0.5; 
    874                 const Vector3 normal = Normalize(rayInf.mRay->GetDir()); 
    875  
    876                 plane = Plane3(normal, pt); 
    877          
    878                 const float candidateCost = SplitPlaneCost(plane, data); 
    879  
    880                 if (candidateCost < lowestCost) 
    881                 { 
    882                         bestPlane = plane;       
    883                         lowestCost = candidateCost; 
    884                 } 
    885         } 
    886  
    887         // take plane normal as plane normal and the midpoint of the ray. 
    888         // PROBLEM: does not resemble any point where visibility is likely to change 
    889         //Debug << "lowest: " << lowestCost << endl; 
    890         for (int i = 0; i < mMaxRayCandidates / 2; ++ i) 
    891         { 
    892                 Vector3 pt[3]; 
    893                 int idx[3]; 
    894                 int cmaxT = 0; 
    895                 int cminT = 0; 
    896                 bool chooseMin = false; 
    897  
    898                 for (int j = 0; j < 3; j ++) 
    899                 { 
    900                         idx[j] = Random((int)rays->size() * 2); 
    901                                  
    902                         if (idx[j] >= (int)rays->size()) 
    903                         { 
    904                                 idx[j] -= (int)rays->size(); 
    905                                  
    906                                 chooseMin = (cminT < 2); 
    907                         } 
    908                         else 
    909                                 chooseMin = (cmaxT < 2); 
    910  
    911                         RayInfo rayInf = (*rays)[idx[j]]; 
    912                         pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 
    913                 }        
    914                          
    915                 plane = Plane3(pt[0], pt[1], pt[2]); 
    916  
    917                 const float candidateCost = SplitPlaneCost(plane, data); 
    918  
    919                 if (candidateCost < lowestCost) 
    920                 { 
    921                         //Debug << "choose ray plane 2: " << candidateCost << endl; 
    922                         bestPlane = plane; 
    923                          
    924                         lowestCost = candidateCost; 
    925                 } 
    926         }        
    927  
    928 #ifdef _DEBUG 
    929         Debug << "plane lowest cost: " << lowestCost << endl; 
    930 #endif 
    931         return bestPlane; 
    932 } 
    933  
    934 int VspBspTree::GetNextCandidateIdx(int currentIdx, PolygonContainer &polys) 
    935 { 
    936         const int candidateIdx = Random(currentIdx --); 
    937  
    938         // swap candidates to avoid testing same plane 2 times 
    939         std::swap(polys[currentIdx], polys[candidateIdx]); 
    940          
    941         return currentIdx; 
    942         //return Random((int)polys.size()); 
    943 } 
    944  
    945  
    946 bool VspBspTree::BoundRay(const Ray &ray, float &minT, float &maxT) const 
    947 { 
    948         maxT = 1e6; 
    949         minT = 0; 
    950          
    951         // test with tree bounding box 
    952         if (!mBox.GetMinMaxT(ray, &minT, &maxT)) 
    953                 return false; 
    954  
    955         if (minT < 0) // start ray from origin 
    956                 minT = 0; 
    957  
    958         // bound ray or line segment 
    959         if ((ray.GetType() == Ray::LOCAL_RAY) &&  
    960             !ray.intersections.empty() &&  
    961                 (ray.intersections[0].mT <= maxT)) 
    962         { 
    963                 maxT = ray.intersections[0].mT; 
    964         } 
    965  
    966         return true; 
    967 } 
    968  
    969 inline void VspBspTree::GenerateUniqueIdsForPvs() 
    970 { 
    971         Intersectable::NewMail(); sBackId = ViewCell::sMailId; 
    972         Intersectable::NewMail(); sFrontId = ViewCell::sMailId; 
    973         Intersectable::NewMail(); sFrontAndBackId = ViewCell::sMailId; 
    974 } 
    975  
    976 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane,  
    977                                                                  const VspBspTraversalData &data) 
    978 { 
    979         float val = 0; 
    980  
    981         float sumBalancedRays = 0; 
    982         float sumRaySplits = 0; 
    983          
    984         int backId = 0; 
    985         int frontId = 0; 
    986         int frontAndBackId = 0; 
    987  
    988         int frontPvs = 0; 
    989         int backPvs = 0; 
    990  
    991         // probability that view point lies in child 
    992         float pOverall = 0; 
    993         float pFront = 0; 
    994         float pBack = 0; 
    995  
    996         const bool pvsUseLen = false; 
    997  
    998         if (mSplitPlaneStrategy & PVS) 
    999         { 
    1000                 // create unique ids for pvs heuristics 
    1001                 GenerateUniqueIdsForPvs(); 
    1002          
    1003                 if (mPvsUseArea) // use front and back cell areas to approximate volume 
    1004                 {        
    1005                         // construct child geometry with regard to the candidate split plane 
    1006                         VspBspNodeGeometry frontCell; 
    1007                         VspBspNodeGeometry backCell; 
    1008  
    1009                         data.mGeometry->SplitGeometry(frontCell, backCell, *this, candidatePlane); 
    1010                  
    1011                         pFront = frontCell.GetArea(); 
    1012                         pBack = backCell.GetArea(); 
    1013  
    1014                         pOverall = data.mArea; 
    1015                 } 
    1016         } 
    1017                          
    1018         RayInfoContainer::const_iterator rit, rit_end = data.mRays->end(); 
    1019  
    1020         for (rit = data.mRays->begin(); rit != data.mRays->end(); ++ rit) 
    1021         { 
    1022                 VssRay *ray = (*rit).mRay; 
    1023                 const int cf = (*rit).ComputeRayIntersection(candidatePlane, (*rit).mRay->mT); 
    1024  
    1025                 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    1026                 { 
    1027                         sumBalancedRays += cf; 
    1028                 } 
    1029                  
    1030                 if (mSplitPlaneStrategy & BALANCED_RAYS) 
    1031                 { 
    1032                         if (cf == 0) 
    1033                                 ++ sumRaySplits; 
    1034                 } 
    1035  
    1036                 if (mSplitPlaneStrategy & PVS) 
    1037                 { 
    1038                         // in case the ray intersects an object 
    1039                         // assure that we only count the object  
    1040                         // once for the front and once for the back side of the plane 
    1041                          
    1042                         // add the termination object 
    1043                         AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs); 
    1044                          
    1045                         // add the source object 
    1046                         AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs); 
    1047                          
    1048                         // use number or length of rays to approximate volume 
    1049                         if (!mPvsUseArea) 
    1050                         { 
    1051                                 float len = 1; 
    1052  
    1053                                 if (pvsUseLen) // use length of rays 
    1054                                         len = (*rit).SqrSegmentLength(); 
    1055                          
    1056                                 pOverall += len; 
    1057  
    1058                                 if (cf == 1) 
    1059                                         pFront += len; 
    1060                                 if (cf == -1) 
    1061                                         pBack += len; 
    1062                                 if (cf == 0) 
    1063                                 { 
    1064                                         // use length of rays to approximate volume 
    1065                                         if (pvsUseLen)  
    1066                                         { 
    1067                                                 float newLen = len *  
    1068                                                         ((*rit).GetMaxT() - (*rit).mRay->mT) /  
    1069                                                         ((*rit).GetMaxT() - (*rit).GetMinT()); 
    1070                  
    1071                                                 if (candidatePlane.Side((*rit).ExtrapOrigin()) <= 0) 
    1072                                                 { 
    1073                                                         pBack += newLen; 
    1074                                                         pFront += len - newLen; 
    1075                                                 } 
    1076                                                 else 
    1077                                                 { 
    1078                                                         pFront += newLen; 
    1079                                                         pBack += len - newLen; 
    1080                                                 } 
    1081                                         } 
    1082                                         else 
    1083                                         { 
    1084                                                 ++ pFront; 
    1085                                                 ++ pBack; 
    1086                                         } 
    1087                                 } 
    1088                         } 
    1089                 } 
    1090         } 
    1091  
    1092         const float raysSize = (float)data.mRays->size() + Limits::Small; 
    1093  
    1094         if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    1095                 val += mLeastRaySplitsFactor * sumRaySplits / raysSize; 
    1096  
    1097         if (mSplitPlaneStrategy & BALANCED_RAYS) 
    1098                 val += mBalancedRaysFactor * fabs(sumBalancedRays) /  raysSize; 
    1099  
    1100         const float denom = pOverall * (float)data.mPvs * 2.0f + Limits::Small; 
    1101  
    1102         if (mSplitPlaneStrategy & PVS) 
    1103         { 
    1104                 val += mPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom; 
    1105  
    1106                 // give penalty to unbalanced split 
    1107                 if (0) 
    1108                 if (((pFront * 0.2 + Limits::Small) > pBack) ||  
    1109                         (pFront < (pBack * 0.2 + Limits::Small))) 
    1110                         val += 0.5; 
    1111         } 
    1112  
    1113 #ifdef _DEBUG 
    1114         Debug << "totalpvs: " << pvs << " ptotal: " << pOverall 
    1115                   << " frontpvs: " << frontPvs << " pFront: " << pFront  
    1116                   << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl; 
    1117 #endif 
    1118         return val; 
    1119 } 
    1120  
    1121 void VspBspTree::AddObjToPvs(Intersectable *obj, 
    1122                                                   const int cf, 
    1123                                                   int &frontPvs, 
    1124                                                   int &backPvs) const 
    1125 { 
    1126         if (!obj) 
    1127                 return; 
    1128         // TODO: does this really belong to no pvs? 
    1129         //if (cf == Ray::COINCIDENT) return; 
    1130  
    1131         // object belongs to both PVS 
    1132         if (cf >= 0) 
    1133         { 
    1134                 if ((obj->mMailbox != sFrontId) &&  
    1135                         (obj->mMailbox != sFrontAndBackId)) 
    1136                 { 
    1137                         ++ frontPvs; 
    1138  
    1139                         if (obj->mMailbox == sBackId) 
    1140                                 obj->mMailbox = sFrontAndBackId;         
    1141                         else 
    1142                                 obj->mMailbox = sFrontId;                                                                
    1143                 } 
    1144         } 
    1145          
    1146         if (cf <= 0) 
    1147         { 
    1148                 if ((obj->mMailbox != sBackId) && 
    1149                         (obj->mMailbox != sFrontAndBackId)) 
    1150                 { 
    1151                         ++ backPvs; 
    1152  
    1153                         if (obj->mMailbox == sFrontId) 
    1154                                 obj->mMailbox = sFrontAndBackId;  
    1155                         else 
    1156                                 obj->mMailbox = sBackId;                                 
    1157                 } 
    1158         } 
    1159 } 
    1160  
    1161 void VspBspTree::CollectLeaves(vector<VspBspLeaf *> &leaves) const 
    1162 { 
    1163         stack<VspBspNode *> nodeStack; 
    1164         nodeStack.push(mRoot); 
    1165   
    1166         while (!nodeStack.empty())  
    1167         { 
    1168                 VspBspNode *node = nodeStack.top(); 
    1169      
    1170                 nodeStack.pop(); 
    1171      
    1172                 if (node->IsLeaf())  
    1173                 { 
    1174                         VspBspLeaf *leaf = (VspBspLeaf *)node;           
    1175                         leaves.push_back(leaf); 
    1176                 }  
    1177                 else  
    1178                 { 
    1179                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1180  
    1181                         nodeStack.push(interior->GetBack()); 
    1182                         nodeStack.push(interior->GetFront()); 
    1183                 } 
    1184         } 
    1185 } 
    1186  
    1187 AxisAlignedBox3 VspBspTree::GetBoundingBox() const 
    1188 { 
    1189         return mBox; 
    1190 } 
    1191  
    1192 VspBspNode *VspBspTree::GetRoot() const 
    1193 { 
    1194         return mRoot; 
    1195 } 
    1196  
    1197 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 
    1198 { 
    1199         // the node became a leaf -> evaluate stats for leafs 
    1200         VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(data.mNode); 
    1201  
    1202         // store maximal and minimal depth 
    1203         if (data.mDepth > mStat.maxDepth) 
    1204                 mStat.maxDepth = data.mDepth; 
    1205  
    1206         if (data.mDepth < mStat.minDepth) 
    1207                 mStat.minDepth = data.mDepth; 
    1208  
    1209         // accumulate depth to compute average depth 
    1210         mStat.accumDepth += data.mDepth; 
    1211          
    1212  
    1213         if (data.mDepth >= mTermMaxDepth) 
    1214                 ++ mStat.maxDepthNodes; 
    1215  
    1216         if (data.mPvs < mTermMinPvs) 
    1217                 ++ mStat.minPvsNodes; 
    1218  
    1219         if ((int)data.mRays->size() < mTermMinRays) 
    1220                 ++ mStat.minRaysNodes; 
    1221  
    1222         if (data.GetAvgRayContribution() > mTermMaxRayContribution) 
    1223                 ++ mStat.maxRayContribNodes; 
    1224          
    1225         if (data.mGeometry->GetArea() <= mTermMinArea)  
    1226                 ++ mStat.minAreaNodes; 
    1227  
    1228 #ifdef _DEBUG 
    1229         Debug << "BSP stats: " 
    1230                   << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), " 
    1231                   << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), " 
    1232                   << "Area: " << data.mArea << " (min: " << mTermMinArea << "), " 
    1233                   << "#polygons: " << (int)data.mPolygons->size() << " (max: " << mTermMinPolys << "), " 
    1234                   << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "  
    1235                   << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, " 
    1236                   << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl; 
    1237 #endif 
    1238 } 
    1239  
    1240 int VspBspTree::CastRay(Ray &ray) 
    1241 { 
    1242         int hits = 0; 
    1243    
    1244         stack<VspBspRayTraversalData> tStack; 
    1245    
    1246         float maxt, mint; 
    1247  
    1248         if (!BoundRay(ray, mint, maxt)) 
    1249                 return 0; 
    1250  
    1251         Intersectable::NewMail(); 
    1252  
    1253         Vector3 entp = ray.Extrap(mint); 
    1254         Vector3 extp = ray.Extrap(maxt); 
    1255    
    1256         VspBspNode *node = mRoot; 
    1257         VspBspNode *farChild = NULL; 
    1258          
    1259         while (1) 
    1260         { 
    1261                 if (!node->IsLeaf())  
    1262                 { 
    1263                         VspBspInterior *in = (VspBspInterior *) node; 
    1264                          
    1265                         Plane3 *splitPlane = in->GetPlane(); 
    1266  
    1267                         int entSide = splitPlane->Side(entp); 
    1268                         int extSide = splitPlane->Side(extp); 
    1269  
    1270                         Vector3 intersection; 
    1271  
    1272                         if (entSide < 0) 
    1273                         { 
    1274                                 node = in->GetBack(); 
    1275  
    1276                                 if(extSide <= 0) // plane does not split ray => no far child 
    1277                                         continue; 
    1278                                          
    1279                                 farChild = in->GetFront(); // plane splits ray 
    1280  
    1281                         } else if (entSide > 0) 
    1282                         { 
    1283                                 node = in->GetFront(); 
    1284  
    1285                                 if (extSide >= 0) // plane does not split ray => no far child 
    1286                                         continue; 
    1287  
    1288                                 farChild = in->GetBack(); // plane splits ray                    
    1289                         } 
    1290                         else // ray and plane are coincident 
    1291                         { 
    1292                                 // WHAT TO DO IN THIS CASE ? 
    1293                                 //break; 
    1294                                 node = in->GetFront(); 
    1295                                 continue; 
    1296                         } 
    1297  
    1298                         // push data for far child 
    1299                         tStack.push(VspBspRayTraversalData(farChild, extp, maxt)); 
    1300  
    1301                         // find intersection of ray segment with plane 
    1302                         float t; 
    1303                         extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &t); 
    1304                         maxt *= t; 
    1305                          
    1306                 } else // reached leaf => intersection with view cell 
    1307                 { 
    1308                         VspBspLeaf *leaf = dynamic_cast<VspBspLeaf *>(node); 
    1309        
    1310                         if (!leaf->mViewCell->Mailed()) 
    1311                         { 
    1312                                 //ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf)); 
    1313                                 leaf->mViewCell->Mail(); 
    1314                                 ++ hits; 
    1315                         } 
    1316                          
    1317                         //-- fetch the next far child from the stack 
    1318                         if (tStack.empty()) 
    1319                                 break; 
    1320        
    1321                         entp = extp; 
    1322                         mint = maxt; // NOTE: need this? 
    1323  
    1324                         if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f) 
    1325                                 break; 
    1326  
    1327                         VspBspRayTraversalData &s = tStack.top(); 
    1328  
    1329                         node = s.mNode; 
    1330                         extp = s.mExitPoint; 
    1331                         maxt = s.mMaxT; 
    1332  
    1333                         tStack.pop(); 
    1334                 } 
    1335         } 
    1336  
    1337         return hits; 
    1338 } 
    1339  
    1340 bool VspBspTree::Export(const string filename) 
    1341 { 
    1342         Exporter *exporter = Exporter::GetExporter(filename); 
    1343  
    1344         if (exporter)  
    1345         { 
    1346                 //exporter->ExportVspBspTree(*this); 
    1347                 return true; 
    1348         }        
    1349  
    1350         return false; 
    1351 } 
    1352  
    1353 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const 
    1354 { 
    1355         stack<VspBspNode *> nodeStack; 
    1356         nodeStack.push(mRoot); 
    1357  
    1358         ViewCell::NewMail(); 
    1359  
    1360         while (!nodeStack.empty())  
    1361         { 
    1362                 VspBspNode *node = nodeStack.top(); 
    1363                 nodeStack.pop(); 
    1364  
    1365                 if (node->IsLeaf())  
    1366                 { 
    1367                         ViewCell *viewCell = dynamic_cast<VspBspLeaf *>(node)->mViewCell; 
    1368  
    1369                         if (!viewCell->Mailed())  
    1370                         { 
    1371                                 viewCell->Mail(); 
    1372                                 viewCells.push_back(viewCell); 
    1373                         } 
    1374                 } 
    1375                 else  
    1376                 { 
    1377                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1378  
    1379                         nodeStack.push(interior->mFront); 
    1380                         nodeStack.push(interior->mBack); 
    1381                 } 
    1382         } 
    1383 } 
    1384  
    1385 void VspBspTree::EvaluateViewCellsStats(VspBspViewCellsStatistics &stat) const 
    1386 { 
    1387         stat.Reset(); 
    1388  
    1389         stack<VspBspNode *> nodeStack; 
    1390         nodeStack.push(mRoot); 
    1391  
    1392         ViewCell::NewMail(); 
    1393  
    1394         // exclude root cell 
    1395         mRootCell->Mail(); 
    1396  
    1397         while (!nodeStack.empty())  
    1398         { 
    1399                 VspBspNode *node = nodeStack.top(); 
    1400                 nodeStack.pop(); 
    1401  
    1402                 if (node->IsLeaf())  
    1403                 { 
    1404                         ++ stat.bspLeaves; 
    1405  
    1406                         BspViewCell *viewCell = dynamic_cast<VspBspLeaf *>(node)->mViewCell; 
    1407  
    1408                         if (!viewCell->Mailed())  
    1409                         { 
    1410                                 viewCell->Mail(); 
    1411                                  
    1412                                 ++ stat.viewCells; 
    1413                                 const int pvsSize = viewCell->GetPvs().GetSize(); 
    1414  
    1415                 stat.pvs += pvsSize; 
    1416  
    1417                                 if (pvsSize < 1) 
    1418                                         ++ stat.emptyPvs; 
    1419  
    1420                                 if (pvsSize > stat.maxPvs) 
    1421                                         stat.maxPvs = pvsSize; 
    1422  
    1423                                 if (pvsSize < stat.minPvs) 
    1424                                         stat.minPvs = pvsSize; 
    1425  
    1426                                 //TODO 
    1427                                 //if ((int)viewCell->mVspBspLeaves.size() > stat.maxVspBspLeaves) 
    1428                                 //      stat.maxVspBspLeaves = (int)viewCell->mVspBspLeaves.size();              
    1429                         } 
    1430                 } 
    1431                 else  
    1432                 { 
    1433                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1434  
    1435                         nodeStack.push(interior->mFront); 
    1436                         nodeStack.push(interior->mBack); 
    1437                 } 
    1438         } 
    1439 } 
    1440  
    1441 VspBspTreeStatistics &VspBspTree::GetStat() 
    1442 { 
    1443         return mStat; 
    1444 } 
    1445  
    1446 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const 
    1447 { 
    1448         float len = 0; 
    1449  
    1450         RayInfoContainer::const_iterator it, it_end = rays.end(); 
    1451  
    1452         for (it = rays.begin(); it != it_end; ++ it) 
    1453                 len += (*it).SegmentLength(); 
    1454  
    1455         return len; 
    1456 } 
    1457  
    1458 int VspBspTree::SplitRays(const Plane3 &plane, 
    1459                                            RayInfoContainer &rays,  
    1460                                            RayInfoContainer &frontRays,  
    1461                                            RayInfoContainer &backRays) 
    1462 { 
    1463         int splits = 0; 
    1464  
    1465         while (!rays.empty()) 
    1466         { 
    1467                 RayInfo bRay = rays.back(); 
    1468                 VssRay *ray = bRay.mRay; 
    1469  
    1470                 rays.pop_back(); 
    1471          
    1472                 // get classification and receive new t 
    1473                 const int cf =  bRay.ComputeRayIntersection(plane, ray->mT); 
    1474  
    1475                 switch(cf) 
    1476                 { 
    1477                 case -1: 
    1478                         backRays.push_back(bRay); 
    1479                         break; 
    1480                 case 1: 
    1481                         break; 
    1482                         frontRays.push_back(bRay); 
    1483                 case 0:  
    1484                         //-- split ray 
    1485  
    1486                         // if start point behind plane 
    1487                         if (plane.Side(bRay.ExtrapOrigin()) <= 0) 
    1488                         { 
    1489                                 backRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 
    1490                                 frontRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 
    1491                         } 
    1492                         else 
    1493                         { 
    1494                                 frontRays.push_back(RayInfo(ray, bRay.GetMinT(), ray->mT)); 
    1495                                 backRays.push_back(RayInfo(ray, ray->mT, bRay.GetMaxT())); 
    1496                         } 
    1497                         break; 
    1498                 default: 
    1499                         Debug << "Should not come here 4" << endl; 
    1500                         break; 
    1501                 } 
    1502         } 
    1503  
    1504         return splits; 
    1505 } 
    1506  
    1507 void VspBspTree::ExtractHalfSpaces(VspBspNode *n, vector<Plane3> &halfSpaces) const 
    1508 { 
    1509         VspBspNode *lastNode; 
    1510         do 
    1511         { 
    1512                 lastNode = n; 
    1513  
    1514                 // want to get planes defining geometry of this node => don't take 
    1515                 // split plane of node itself 
    1516                 n = n->GetParent(); 
    1517                  
    1518                 if (n) 
    1519                 { 
    1520                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(n); 
    1521                         Plane3 halfSpace = *dynamic_cast<VspBspInterior *>(interior)->GetPlane(); 
    1522  
    1523             if (interior->mFront != lastNode) 
    1524                                 halfSpace.ReverseOrientation(); 
    1525  
    1526                         halfSpaces.push_back(halfSpace); 
    1527                 } 
    1528         } 
    1529         while (n); 
    1530 } 
    1531  
    1532 void VspBspTree::ConstructGeometry(VspBspNode *n, VspBspNodeGeometry &cell) const 
    1533 { 
    1534         PolygonContainer polys; 
    1535         ConstructGeometry(n, polys); 
    1536         cell.mPolys = polys; 
    1537 } 
    1538  
    1539 void VspBspTree::ConstructGeometry(VspBspNode *n, PolygonContainer &cell) const 
    1540 { 
    1541         vector<Plane3> halfSpaces; 
    1542         ExtractHalfSpaces(n, halfSpaces); 
    1543  
    1544         PolygonContainer candidatePolys; 
    1545  
    1546         // bounded planes are added to the polygons (reverse polygons 
    1547         // as they have to be outfacing 
    1548         for (int i = 0; i < (int)halfSpaces.size(); ++ i) 
    1549         { 
    1550                 Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]); 
    1551                  
    1552                 if (p->Valid()) 
    1553                 { 
    1554                         candidatePolys.push_back(p->CreateReversePolygon()); 
    1555                         DEL_PTR(p); 
    1556                 } 
    1557         } 
    1558  
    1559         // add faces of bounding box (also could be faces of the cell) 
    1560         for (int i = 0; i < 6; ++ i) 
    1561         { 
    1562                 VertexContainer vertices; 
    1563          
    1564                 for (int j = 0; j < 4; ++ j) 
    1565                         vertices.push_back(mBox.GetFace(i).mVertices[j]); 
    1566  
    1567                 candidatePolys.push_back(new Polygon3(vertices)); 
    1568         } 
    1569  
    1570         for (int i = 0; i < (int)candidatePolys.size(); ++ i) 
    1571         { 
    1572                 // polygon is split by all other planes 
    1573                 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 
    1574                 { 
    1575                         if (i == j) // polygon and plane are coincident 
    1576                                 continue; 
    1577  
    1578                         VertexContainer splitPts; 
    1579                         Polygon3 *frontPoly, *backPoly; 
    1580  
    1581                         const int cf = candidatePolys[i]->ClassifyPlane(halfSpaces[j]); 
    1582                          
    1583                         switch (cf) 
    1584                         { 
    1585                                 case Polygon3::SPLIT: 
    1586                                         frontPoly = new Polygon3(); 
    1587                                         backPoly = new Polygon3(); 
    1588  
    1589                                         candidatePolys[i]->Split(halfSpaces[j],  
    1590                                                                                          *frontPoly,  
    1591                                                                                          *backPoly); 
    1592  
    1593                                         DEL_PTR(candidatePolys[i]); 
    1594  
    1595                                         if (frontPoly->Valid()) 
    1596                                                 candidatePolys[i] = frontPoly; 
    1597                                         else 
    1598                                                 DEL_PTR(frontPoly); 
    1599  
    1600                                         DEL_PTR(backPoly); 
    1601                                         break; 
    1602                                 case Polygon3::BACK_SIDE: 
    1603                                         DEL_PTR(candidatePolys[i]); 
    1604                                         break; 
    1605                                 // just take polygon as it is 
    1606                                 case Polygon3::FRONT_SIDE: 
    1607                                 case Polygon3::COINCIDENT: 
    1608                                 default: 
    1609                                         break; 
    1610                         } 
    1611                 } 
    1612                  
    1613                 if (candidatePolys[i]) 
    1614                         cell.push_back(candidatePolys[i]); 
    1615         } 
    1616 } 
    1617  
    1618 void VspBspTree::ConstructGeometry(BspViewCell *vc, PolygonContainer &cell) const 
    1619 { 
    1620         /* 
    1621         TODO 
    1622         vector<VspBspLeaf *> leaves = vc->mBspLeaves; 
    1623  
    1624         vector<VspBspLeaf *>::const_iterator it, it_end = leaves.end(); 
    1625  
    1626         for (it = leaves.begin(); it != it_end; ++ it) 
    1627                 ConstructGeometry(*it, vcGeom);*/ 
    1628 } 
    1629  
    1630 int VspBspTree::FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors,  
    1631                                                    const bool onlyUnmailed) const 
    1632 { 
    1633         PolygonContainer cell; 
    1634  
    1635         ConstructGeometry(n, cell); 
    1636  
    1637         stack<VspBspNode *> nodeStack; 
    1638         nodeStack.push(mRoot); 
    1639                  
    1640         // planes needed to verify that we found neighbor leaf. 
    1641         vector<Plane3> halfSpaces; 
    1642         ExtractHalfSpaces(n, halfSpaces); 
    1643  
    1644         while (!nodeStack.empty())  
    1645         { 
    1646                 VspBspNode *node = nodeStack.top(); 
    1647                 nodeStack.pop(); 
    1648  
    1649                 if (node->IsLeaf()) 
    1650                 { 
    1651             if (node != n && (!onlyUnmailed || !node->Mailed())) 
    1652                         { 
    1653                                 // test all planes of current node if candidate really 
    1654                                 // is neighbour 
    1655                                 PolygonContainer neighborCandidate; 
    1656                                 ConstructGeometry(node, neighborCandidate); 
    1657                                  
    1658                                 bool isAdjacent = true; 
    1659                                 for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i) 
    1660                                 { 
    1661                                         const int cf =  
    1662                                                 Polygon3::ClassifyPlane(neighborCandidate, halfSpaces[i]); 
    1663  
    1664                                         if (cf == Polygon3::BACK_SIDE) 
    1665                                                 isAdjacent = false; 
    1666                                 } 
    1667  
    1668                                 if (isAdjacent) 
    1669                                         neighbors.push_back(dynamic_cast<VspBspLeaf *>(node)); 
    1670  
    1671                                 CLEAR_CONTAINER(neighborCandidate); 
    1672                         } 
    1673                 } 
    1674                 else  
    1675                 { 
    1676                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1677          
    1678                         const int cf = Polygon3::ClassifyPlane(cell, interior->mPlane); 
    1679  
    1680                         if (cf == Polygon3::FRONT_SIDE) 
    1681                                 nodeStack.push(interior->mFront); 
    1682                         else 
    1683                                 if (cf == Polygon3::BACK_SIDE) 
    1684                                         nodeStack.push(interior->mBack); 
    1685                                 else  
    1686                                 { 
    1687                                         // random decision 
    1688                                         nodeStack.push(interior->mBack); 
    1689                                         nodeStack.push(interior->mFront); 
    1690                                 } 
    1691                 } 
    1692         } 
    1693          
    1694         CLEAR_CONTAINER(cell); 
    1695         return (int)neighbors.size(); 
    1696 } 
    1697  
    1698 VspBspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace) 
    1699 { 
    1700     stack<VspBspNode *> nodeStack; 
    1701         nodeStack.push(mRoot); 
    1702          
    1703         int mask = rand(); 
    1704    
    1705         while (!nodeStack.empty())  
    1706         { 
    1707                 VspBspNode *node = nodeStack.top(); 
    1708                 nodeStack.pop(); 
    1709            
    1710                 if (node->IsLeaf())  
    1711                 { 
    1712                         return dynamic_cast<VspBspLeaf *>(node); 
    1713                 }  
    1714                 else  
    1715                 { 
    1716                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1717                          
    1718                         VspBspNode *next; 
    1719          
    1720                         PolygonContainer cell; 
    1721  
    1722                         // todo: not very efficient: constructs full cell everytime 
    1723                         ConstructGeometry(interior, cell); 
    1724  
    1725                         const int cf = Polygon3::ClassifyPlane(cell, halfspace); 
    1726  
    1727                         if (cf == Polygon3::BACK_SIDE) 
    1728                                 next = interior->mFront; 
    1729                         else 
    1730                                 if (cf == Polygon3::FRONT_SIDE) 
    1731                                         next = interior->mFront; 
    1732                         else  
    1733                         { 
    1734                                 // random decision 
    1735                                 if (mask & 1) 
    1736                                         next = interior->mBack; 
    1737                                 else 
    1738                                         next = interior->mFront; 
    1739                                 mask = mask >> 1; 
    1740                         } 
    1741  
    1742                         nodeStack.push(next); 
    1743                 } 
    1744         } 
    1745          
    1746         return NULL; 
    1747 } 
    1748  
    1749 VspBspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed) 
    1750 { 
    1751         stack<VspBspNode *> nodeStack; 
    1752          
    1753         nodeStack.push(mRoot); 
    1754  
    1755         int mask = rand(); 
    1756          
    1757         while (!nodeStack.empty())  
    1758         { 
    1759                 VspBspNode *node = nodeStack.top(); 
    1760                 nodeStack.pop(); 
    1761                  
    1762                 if (node->IsLeaf())  
    1763                 { 
    1764                         if ( (!onlyUnmailed || !node->Mailed()) ) 
    1765                                 return dynamic_cast<VspBspLeaf *>(node); 
    1766                 } 
    1767                 else  
    1768                 { 
    1769                         VspBspInterior *interior = dynamic_cast<VspBspInterior *>(node); 
    1770  
    1771                         // random decision 
    1772                         if (mask & 1) 
    1773                                 nodeStack.push(interior->mBack); 
    1774                         else 
    1775                                 nodeStack.push(interior->mFront); 
    1776  
    1777                         mask = mask >> 1; 
    1778                 } 
    1779         } 
    1780          
    1781         return NULL; 
    1782 } 
    1783  
    1784 int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const 
    1785 { 
    1786         int pvsSize = 0; 
    1787  
    1788         RayInfoContainer::const_iterator rit, rit_end = rays.end(); 
    1789  
    1790         Intersectable::NewMail(); 
    1791  
    1792         for (rit = rays.begin(); rit != rays.end(); ++ rit) 
    1793         { 
    1794                 VssRay *ray = (*rit).mRay; 
    1795                  
    1796                 if (ray->mOriginObject) 
    1797                 { 
    1798                         if (!ray->mOriginObject->Mailed()) 
    1799                         { 
    1800                                 ray->mOriginObject->Mail(); 
    1801                                 ++ pvsSize; 
    1802                         } 
    1803                 } 
    1804                 if (ray->mTerminationObject) 
    1805                 { 
    1806                         if (!ray->mTerminationObject->Mailed()) 
    1807                         { 
    1808                                 ray->mTerminationObject->Mail(); 
    1809                                 ++ pvsSize; 
    1810                         } 
    1811                 } 
    1812         } 
    1813  
    1814         return pvsSize; 
    1815 } 
    1816  
    1817 /************************************************************* 
    1818  *            VspBspNodeGeometry Implementation                 * 
    1819  *************************************************************/ 
    1820  
    1821 VspBspNodeGeometry::~VspBspNodeGeometry() 
    1822 { 
    1823         CLEAR_CONTAINER(mPolys); 
    1824 } 
    1825  
    1826 float VspBspNodeGeometry::GetArea() const  
    1827 {  
    1828         return Polygon3::GetArea(mPolys); 
    1829 } 
    1830  
    1831 void VspBspNodeGeometry::SplitGeometry(VspBspNodeGeometry &front, 
    1832                                                                         VspBspNodeGeometry &back, 
    1833                                                                         const VspBspTree &tree,                                           
    1834                                                                         const Plane3 &splitPlane) const 
    1835 {        
    1836         // get cross section of new polygon 
    1837         Polygon3 *planePoly = tree.GetBoundingBox().CrossSection(splitPlane); 
    1838  
    1839         planePoly = SplitPolygon(planePoly, tree); 
    1840  
    1841         //-- plane poly splits all other cell polygons 
    1842         for (int i = 0; i < (int)mPolys.size(); ++ i) 
    1843         { 
    1844                 const int cf = mPolys[i]->ClassifyPlane(splitPlane, 0.00001f); 
    1845                          
    1846                 // split new polygon with all previous planes 
    1847                 switch (cf) 
    1848                 { 
    1849                         case Polygon3::SPLIT: 
    1850                                 { 
    1851                                         Polygon3 *poly = new Polygon3(mPolys[i]->mVertices); 
    1852  
    1853                                         Polygon3 *frontPoly = new Polygon3(); 
    1854                                         Polygon3 *backPoly = new Polygon3(); 
    1855                                  
    1856                                         poly->Split(splitPlane, *frontPoly, *backPoly); 
    1857  
    1858                                         DEL_PTR(poly); 
    1859  
    1860                                         if (frontPoly->Valid()) 
    1861                                                 front.mPolys.push_back(frontPoly); 
    1862                                         if (backPoly->Valid()) 
    1863                                                 back.mPolys.push_back(backPoly); 
    1864                                 } 
    1865                                  
    1866                                 break; 
    1867                         case Polygon3::BACK_SIDE: 
    1868                                 back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));                       
    1869                                 break; 
    1870                         case Polygon3::FRONT_SIDE: 
    1871                                 front.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));      
    1872                                 break; 
    1873                         case Polygon3::COINCIDENT: 
    1874                                 //front.mPolys.push_back(CreateReversePolygon(mPolys[i])); 
    1875                                 back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices)); 
    1876                                 break; 
    1877                         default: 
    1878                                 break; 
    1879                 } 
    1880         } 
    1881  
    1882         //-- finally add the new polygon to the child cells 
    1883         if (planePoly) 
    1884         { 
    1885                 // add polygon with normal pointing into positive half space to back cell 
    1886                 back.mPolys.push_back(planePoly); 
    1887                 // add polygon with reverse orientation to front cell 
    1888                 front.mPolys.push_back(planePoly->CreateReversePolygon()); 
    1889         } 
    1890  
    1891         //Debug << "returning new geometry " << mPolys.size() << " f: " << front.mPolys.size() << " b: " << back.mPolys.size() << endl; 
    1892         //Debug << "old area " << GetArea() << " f: " << front.GetArea() << " b: " << back.GetArea() << endl; 
    1893 } 
    1894  
    1895 Polygon3 *VspBspNodeGeometry::SplitPolygon(Polygon3 *planePoly, 
    1896                                                                                 const VspBspTree &tree) const 
    1897 { 
    1898         // polygon is split by all other planes 
    1899         for (int i = 0; (i < (int)mPolys.size()) && planePoly; ++ i) 
    1900         { 
    1901                 Plane3 plane = mPolys[i]->GetSupportingPlane(); 
    1902  
    1903                 const int cf =  
    1904                         planePoly->ClassifyPlane(plane, 0.00001f); 
    1905                          
    1906                 // split new polygon with all previous planes 
    1907                 switch (cf) 
    1908                 { 
    1909                         case Polygon3::SPLIT: 
    1910                                 { 
    1911                                         Polygon3 *frontPoly = new Polygon3(); 
    1912                                         Polygon3 *backPoly = new Polygon3(); 
    1913  
    1914                                         planePoly->Split(plane, *frontPoly, *backPoly); 
    1915                                         DEL_PTR(planePoly); 
    1916  
    1917                                         if (backPoly->Valid()) 
    1918                                                 planePoly = backPoly; 
    1919                                         else 
    1920                                                 DEL_PTR(backPoly); 
    1921                                 } 
    1922                                 break; 
    1923                         case Polygon3::FRONT_SIDE: 
    1924                                 DEL_PTR(planePoly); 
    1925                 break; 
    1926                         // polygon is taken as it is 
    1927                         case Polygon3::BACK_SIDE: 
    1928                         case Polygon3::COINCIDENT: 
    1929                         default: 
    1930                                 break; 
    1931                 } 
    1932         } 
    1933  
    1934         return planePoly; 
    1935 } 
    1936  
    1937 void VspBspViewCellsStatistics::Print(ostream &app) const 
    1938 { 
    1939         app << "===== VspBspViewCells statistics ===============\n"; 
    1940  
    1941         app << setprecision(4); 
    1942  
    1943         //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n"; 
    1944  
    1945         app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl; 
    1946  
    1947         app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl; 
    1948  
    1949         app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl; 
    1950  
    1951         app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl; 
    1952  
    1953         app << "#N_PEMPTYPVS ( view cells with PVS smaller 2 )\n" << emptyPvs << endl; 
    1954  
    1955         app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl; 
    1956  
    1957         app << "#N_AVGBSPLEAVES (average number of BSP leaves per view cell )\n" << AvgVspBspLeaves() << endl; 
    1958  
    1959         app << "#N_MAXBSPLEAVES ( maximal number of BSP leaves per view cell )\n" << maxVspBspLeaves << endl; 
    1960          
    1961         app << "===== END OF VspBspViewCells statistics ==========\n"; 
    1962 } 
    1963  
    1964 BspViewCell *VspBspTree::GetRootCell() const 
    1965 { 
    1966         return mRootCell; 
    1967 } 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h

    r445 r448  
    99#include "VssRay.h" 
    1010#include "RayInfo.h" 
     11#include "ViewCellBsp.h" 
    1112 
    1213class ViewCell; 
     
    1415class Plane3; 
    1516class VspBspTree;   
    16 class VspBspInterior; 
    17 class VspBspNode; 
     17class BspInterior; 
     18class BspNode; 
    1819class AxisAlignedBox3; 
    1920class Ray; 
    2021 
    21 class VspBspNodeGeometry 
    22 { 
    23 public: 
    24         VspBspNodeGeometry() 
    25         {};   
    26  
    27         ~VspBspNodeGeometry(); 
    28  
    29         float GetArea() const; 
    30          
    31         /** Computes new cell based on the old cell definition and a new split plane 
    32                 @param side indicates which side of the halfspace  
    33         */ 
    34         void SplitGeometry(VspBspNodeGeometry &front,  
    35                                            VspBspNodeGeometry &back, 
    36                                            const VspBspTree &tree, 
    37                                            const Plane3 &splitPlane) const; 
    38  
    39         Polygon3 *SplitPolygon(Polygon3 *poly, const VspBspTree &tree) const; 
    40  
    41         PolygonContainer mPolys; 
    42 }; 
    43  
    44 /** Data structure used for optimized ray casting. 
     22/*class BspNodeGeometry; 
     23class BspTreeStatistics; 
     24class BspViewCellsStatistics; 
     25class BspNode; 
     26class BspLeaf; 
     27class BspInterior; 
    4528*/ 
    46 struct VspBspRayTraversalData  
    47 { 
    48     VspBspNode *mNode; 
    49     Vector3 mExitPoint; 
    50     float mMaxT; 
    51      
    52     VspBspRayTraversalData() {} 
    53  
    54     VspBspRayTraversalData(VspBspNode *n, const Vector3 &extp, const float maxt): 
    55     mNode(n), mExitPoint(extp), mMaxT(maxt)  
    56         {} 
    57 }; 
    58  
    59 class VspBspTreeStatistics: public StatisticsBase 
    60 { 
    61 public: 
    62         // total number of nodes 
    63         int nodes; 
    64         // number of splits 
    65         int splits; 
    66         // totals number of rays 
    67         int rays; 
    68         // maximal reached depth 
    69         int maxDepth; 
    70         // minimal depth 
    71         int minDepth; 
    72          
    73         // max depth nodes 
    74         int maxDepthNodes; 
    75         // minimum depth nodes 
    76         int minDepthNodes; 
    77         // max depth nodes 
    78         int minPvsNodes; 
    79         // nodes with minimum PVS 
    80         int minRaysNodes; 
    81         // max ray contribution nodes 
    82         int maxRayContribNodes; 
    83         // minimum area nodes 
    84         int minAreaNodes; 
    85  
    86         // max number of rays per node 
    87         int maxObjectRefs; 
    88         // accumulated depth (used to compute average) 
    89         int accumDepth; 
    90         // number of initial polygons 
    91         int polys; 
    92         /// samples contributing to pvs 
    93         int contributingSamples; 
    94         /// sample contributions to pvs 
    95         int sampleContributions; 
    96         /// largest pvs 
    97         int largestPvs; 
    98  
    99         // Constructor 
    100         VspBspTreeStatistics()  
    101         { 
    102                 Reset(); 
    103         } 
    104  
    105         int Nodes() const {return nodes;} 
    106         int Interior() const { return nodes / 2; } 
    107         int Leaves() const { return (nodes / 2) + 1; } 
    108          
    109         // TODO: computation wrong 
    110         double AvgDepth() const { return accumDepth / (double)Leaves();};  
    111    
    112         void Reset()  
    113         { 
    114                 nodes = 0; 
    115                 splits = 0; 
    116                  
    117                 maxDepth = 0; 
    118                 minDepth = 99999; 
    119                 polys = 0; 
    120                 accumDepth = 0; 
    121          
    122                 maxDepthNodes = 0; 
    123                 minPvsNodes = 0; 
    124                 minRaysNodes = 0; 
    125                 maxRayContribNodes = 0; 
    126                 minAreaNodes = 0; 
    127  
    128                 contributingSamples = 0; 
    129                 sampleContributions = 0; 
    130         } 
    131  
    132         void Print(ostream &app) const; 
    133  
    134         friend ostream &operator<<(ostream &s, const VspBspTreeStatistics &stat)  
    135         { 
    136                 stat.Print(s); 
    137                 return s; 
    138         }  
    139 }; 
    140  
    141 class VspBspViewCellsStatistics: public StatisticsBase 
    142 { 
    143 public: 
    144  
    145         /// number of view cells 
    146         int viewCells; 
    147  
    148         /// size of the PVS 
    149         int pvs; 
    150    
    151         /// largest PVS of all view cells 
    152         int maxPvs; 
    153  
    154         /// smallest PVS of all view cells 
    155         int minPvs; 
    156  
    157         /// view cells with empty PVS 
    158         int emptyPvs; 
    159  
    160         /// number of bsp leaves covering the view space 
    161         int bspLeaves; 
    162  
    163         /// largest number of leaves covered by one view cell   
    164         int maxVspBspLeaves; 
    165  
    166     // Constructor 
    167         VspBspViewCellsStatistics()  
    168         { 
    169                 Reset(); 
    170         } 
    171  
    172         double AvgVspBspLeaves() const {return (double)bspLeaves / (double)viewCells;}; 
    173         double AvgPvs() const {return (double)pvs / (double)viewCells;}; 
    174    
    175         void Reset()  
    176         { 
    177                 viewCells = 0;   
    178                 pvs = 0;   
    179                 maxPvs = 0; 
    180  
    181                 minPvs = 999999; 
    182                 emptyPvs = 0; 
    183                 bspLeaves = 0; 
    184                 maxVspBspLeaves = 0; 
    185         } 
    186  
    187         void Print(ostream &app) const; 
    188  
    189         friend ostream &operator<<(ostream &s, const VspBspViewCellsStatistics &stat)  
    190         { 
    191                 stat.Print(s); 
    192                 return s; 
    193         }   
    194 }; 
    195  
    196 /** 
    197     VspBspNode abstract class serving for interior and leaf node implementation 
    198 */ 
    199 class VspBspNode  
    200 { 
    201         friend class VspBspTree; 
    202  
    203 public: 
    204         VspBspNode(); 
    205         virtual ~VspBspNode(){}; 
    206         VspBspNode(VspBspInterior *parent); 
    207  
    208         /** Determines whether this node is a leaf or not 
    209         @return true if leaf 
    210         */ 
    211         virtual bool IsLeaf() const = 0; 
    212  
    213         /** Determines whether this node is a root 
    214         @return true if root 
    215         */ 
    216         virtual bool IsRoot() const; 
    217  
    218         /** Returns parent node. 
    219         */ 
    220         VspBspInterior *GetParent(); 
    221  
    222         /** Sets parent node. 
    223         */ 
    224         void SetParent(VspBspInterior *parent); 
    225  
    226          
    227         static int sMailId; 
    228         int mMailbox; 
    229    
    230         void Mail() { mMailbox = sMailId; } 
    231         static void NewMail() { ++ sMailId; } 
    232         bool Mailed() const { return mMailbox == sMailId; } 
    233  
    234 protected: 
    235  
    236         /// parent of this node 
    237         VspBspInterior *mParent; 
    238 }; 
    239  
    240 /** BSP interior node implementation  
    241 */ 
    242 class VspBspInterior : public VspBspNode  
    243 { 
    244         friend class VspBspTree; 
    245 public: 
    246         /** Standard contructor taking split plane as argument. 
    247         */ 
    248         VspBspInterior(const Plane3 &plane); 
    249         ~VspBspInterior(); 
    250         /** @return false since it is an interior node  
    251         */ 
    252         bool IsLeaf() const; 
    253  
    254         VspBspNode *GetBack(); 
    255         VspBspNode *GetFront(); 
    256  
    257         Plane3 *GetPlane(); 
    258  
    259         void ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild); 
    260         void SetupChildLinks(VspBspNode *b, VspBspNode *f); 
    261  
    262         /** Splits polygons with respect to the split plane. 
    263                 @param polys the polygons to be split. the polygons are consumed and 
    264                            distributed to the containers frontPolys, backPolys, coincident. 
    265                 @param frontPolys returns the polygons in the front of the split plane 
    266                 @param backPolys returns the polygons in the back of the split plane 
    267                 @param coincident returns the polygons coincident to the split plane 
    268  
    269                 @returns the number of splits    
    270         */ 
    271         int SplitPolygons(PolygonContainer &polys,  
    272                                           PolygonContainer &frontPolys,  
    273                                           PolygonContainer &backPolys,  
    274                                           PolygonContainer &coincident); 
    275  
    276         friend ostream &operator<<(ostream &s, const VspBspInterior &A) 
    277         { 
    278                 return s << A.mPlane; 
    279         } 
    280  
    281 protected: 
    282  
    283         /// Splitting plane corresponding to this node 
    284         Plane3 mPlane; 
    285         /// back node 
    286         VspBspNode *mBack; 
    287         /// front node 
    288         VspBspNode *mFront; 
    289 }; 
    290  
    291 /** BSP leaf node implementation. 
    292 */ 
    293 class VspBspLeaf : public VspBspNode  
    294 { 
    295         friend class VspBspTree; 
    296  
    297 public: 
    298         VspBspLeaf(); 
    299         VspBspLeaf(BspViewCell *viewCell); 
    300         VspBspLeaf(VspBspInterior *parent); 
    301         VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell); 
    302  
    303         /** @return true since it is an interior node  
    304         */ 
    305         bool IsLeaf() const; 
    306          
    307         /** Returns pointer of view cell. 
    308         */ 
    309         BspViewCell *GetViewCell() const; 
    310  
    311         /** Sets pointer to view cell. 
    312         */ 
    313         void SetViewCell(BspViewCell *viewCell); 
    314  
    315         /** Adds ray sample contributions to the PVS. 
    316                 @param sampleContributions the number contributions of the samples 
    317                 @param contributingSampels the number of contributing rays 
    318                  
    319         */ 
    320         void AddToPvs(const RayInfoContainer &rays,  
    321                                   int &sampleContributions, 
    322                                   int &contributingSamples,  
    323                                   bool storeLeavesWithRays = false); 
    324  
    325 protected: 
    326  
    327         /// if NULL this does not correspond to feasible viewcell 
    328         BspViewCell *mViewCell; 
    329 }; 
    33029 
    33130/** 
     
    34544        {   
    34645                /// the current node 
    347                 VspBspNode *mNode; 
     46                BspNode *mNode; 
    34847                /// polygonal data for splitting 
    34948                PolygonContainer *mPolygons; 
    35049                /// current depth 
    35150                int mDepth; 
    352                 /// the view cell associated with this subdivsion 
    353                 ViewCell *mViewCell; 
     51                 
    35452                /// rays piercing this node 
    35553                RayInfoContainer *mRays; 
    35654                /// area of current node 
    35755                float mArea; 
    358                 /// geometry of current node induced by split planes 
    359                 VspBspNodeGeometry *mGeometry; 
    360  
     56                /// geometry of node as induced by planes 
     57                BspNodeGeometry *mGeometry; 
     58                 
    36159                /// pvs size 
    36260                int mPvs; 
     
    37472                mPolygons(NULL), 
    37573                mDepth(0), 
    376                 mViewCell(NULL), 
    37774                mRays(NULL), 
    37875                mPvs(0), 
     
    38178                {} 
    38279                 
    383                 VspBspTraversalData(VspBspNode *node,  
     80                VspBspTraversalData(BspNode *node,  
    38481                                                 PolygonContainer *polys,  
    38582                                                 const int depth,  
    386                                                  ViewCell *viewCell, 
    38783                                                 RayInfoContainer *rays, 
    38884                                                 int pvs, 
    38985                                                 float area, 
    390                                                  VspBspNodeGeometry *cell):  
     86                                                 BspNodeGeometry *geom):  
    39187                mNode(node),  
    39288                mPolygons(polys),  
    39389                mDepth(depth),  
    394                 mViewCell(viewCell), 
    39590                mRays(rays), 
    39691                mPvs(pvs), 
    39792                mArea(area), 
    398                 mGeometry(cell) 
     93                mGeometry(geom) 
     94                {} 
     95 
     96                VspBspTraversalData(PolygonContainer *polys,  
     97                                                        const int depth,  
     98                                                        RayInfoContainer *rays, 
     99                                                        BspNodeGeometry *geom):  
     100                mNode(NULL),  
     101                mPolygons(polys),  
     102                mDepth(depth),  
     103                mRays(rays), 
     104                mPvs(0), 
     105                mArea(0), 
     106                mGeometry(geom) 
    399107                {} 
    400108    }; 
     
    406114        VspBspTree(); 
    407115 
     116        /** Default destructor. 
     117        */ 
    408118        ~VspBspTree(); 
    409119 
    410         const VspBspTreeStatistics &GetStatistics() const;  
     120        /** Returns BSP Tree statistics. 
     121        */ 
     122        const BspTreeStatistics &GetStatistics() const;  
    411123   
    412124 
     
    420132        /** Returns list of BSP leaves. 
    421133        */ 
    422         void CollectLeaves(vector<VspBspLeaf *> &leaves) const; 
     134        void CollectLeaves(vector<BspLeaf *> &leaves) const; 
    423135 
    424136        /** Returns box which bounds the whole tree. 
     
    428140        /** Returns root of BSP tree. 
    429141        */ 
    430         VspBspNode *GetRoot() const; 
     142        BspNode *GetRoot() const; 
    431143 
    432144        /** Exports VspBsp tree to file. 
     
    450162        /** Returns statistics. 
    451163        */ 
    452         VspBspTreeStatistics &GetStat(); 
     164        BspTreeStatistics &GetStat(); 
    453165 
    454166        /** finds neighbouring leaves of this tree node. 
    455167        */ 
    456         int FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors,  
     168        int FindNeighbors(BspNode *n,  
     169                                          vector<BspLeaf *> &neighbors,  
    457170                                          const bool onlyUnmailed) const; 
    458171 
     
    460173                leading to this node. 
    461174        */ 
    462         void ConstructGeometry(VspBspNode *n, PolygonContainer &cell) const; 
     175        void ConstructGeometry(BspNode *n, PolygonContainer &cell) const; 
    463176 
    464177        /** Constructs geometry associated with the half space intersections  
     
    469182        /** Construct geometry and stores it in a geometry node container. 
    470183        */ 
    471         void ConstructGeometry(VspBspNode *n, VspBspNodeGeometry &cell) const; 
     184        void ConstructGeometry(BspNode *n, BspNodeGeometry &cell) const; 
    472185 
    473186        /** Returns random leaf of BSP tree. 
    474187                @param halfspace defines the halfspace from which the leaf is taken. 
    475188        */ 
    476         VspBspLeaf *GetRandomLeaf(const Plane3 &halfspace); 
     189        BspLeaf *GetRandomLeaf(const Plane3 &halfspace); 
    477190 
    478191        /** Returns random leaf of BSP tree. 
    479192                @param onlyUnmailed if only unmailed leaves should be returned. 
    480193        */ 
    481         VspBspLeaf *GetRandomLeaf(const bool onlyUnmailed = false); 
     194        BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false); 
    482195 
    483196        /** Traverses tree and counts all view cells as well as their PVS size. 
    484197        */ 
    485         void EvaluateViewCellsStats(VspBspViewCellsStatistics &stat) const; 
     198        void EvaluateViewCellsStats(BspViewCellsStatistics &stat) const; 
    486199 
    487200 
     
    489202        */ 
    490203        BspViewCell *GetRootCell() const; 
     204 
     205        /** Returns epsilon of this tree. 
     206        */ 
     207        float GetEpsilon() const; 
    491208 
    492209protected: 
     
    521238                @returns new root of the subtree 
    522239        */ 
    523         VspBspNode *Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData); 
    524  
    525         /** Constructs the tree from the given list of polygons and rays. 
     240        BspNode *Subdivide(VspBspTraversalStack &tStack,  
     241                                           VspBspTraversalData &tData); 
     242 
     243        /** Constructs the tree from the given traversal data. 
    526244                @param polys stores set of polygons on which subdivision may be based 
    527245                @param rays storesset of rays on which subdivision may be based 
    528246        */ 
    529         void Construct(PolygonContainer *polys, RayInfoContainer *rays); 
     247        void Construct(const PolygonContainer &polys, RayInfoContainer *rays); 
    530248 
    531249        /** Selects the best possible splitting plane.  
     
    536254                @returns the split plane 
    537255        */ 
    538         Plane3 SelectPlane(VspBspLeaf *leaf,  
     256        Plane3 SelectPlane(BspLeaf *leaf,  
    539257                                           VspBspTraversalData &data); 
    540258 
     
    564282        */ 
    565283 
    566         VspBspInterior *SubdivideNode(VspBspTraversalData &tData, 
     284        BspInterior *SubdivideNode(VspBspTraversalData &tData, 
    567285                                                           VspBspTraversalData &frontData, 
    568286                                                           VspBspTraversalData &backData, 
     
    575293                @param rays bundle of rays on which the split can be based 
    576294        */ 
    577         Plane3 SelectPlaneHeuristics(VspBspLeaf *leaf, 
     295        Plane3 SelectPlaneHeuristics(BspLeaf *leaf, 
    578296                                                                 VspBspTraversalData &data); 
    579297 
     
    639357        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const; 
    640358 
    641         /** Bounds ray and returns minT and maxT. 
    642                 @returns true if ray hits BSP tree bounding box 
    643         */ 
    644         bool BoundRay(const Ray &ray, float &minT, float &maxT) const; 
    645  
    646359        /** Subdivides the rays into front and back rays according to the split plane. 
    647360                 
     
    662375        /** Extracts the split planes representing the space bounded by node n. 
    663376        */ 
    664         void ExtractHalfSpaces(VspBspNode *n, vector<Plane3> &halfSpaces) const; 
     377        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const; 
    665378 
    666379        /** Adds the object to the pvs of the front and back leaf with a given classification. 
     
    686399        float AccumulatedRayLength(const RayInfoContainer &rays) const; 
    687400 
    688  
     401        /** Splits polygons with respect to the split plane. 
     402 
     403                @param plane the split plane 
     404                @param polys the polygons to be split. the polygons are consumed and 
     405                           distributed to the containers frontPolys, backPolys, coincident. 
     406                @param frontPolys returns the polygons in the front of the split plane 
     407                @param backPolys returns the polygons in the back of the split plane 
     408                @param coincident returns the polygons coincident to the split plane 
     409 
     410                @returns the number of splits    
     411        */ 
     412        int SplitPolygons(const Plane3 &plane, 
     413                                          PolygonContainer &polys,  
     414                                          PolygonContainer &frontPolys,  
     415                                          PolygonContainer &backPolys,  
     416                                          PolygonContainer &coincident) const; 
     417 
     418        /** Adds ray sample contributions to the PVS. 
     419                @param sampleContributions the number contributions of the samples 
     420                @param contributingSampels the number of contributing rays 
     421                 
     422        */ 
     423        void AddToPvs(BspLeaf *leaf, 
     424                                  const RayInfoContainer &rays,  
     425                                  int &sampleContributions, 
     426                                  int &contributingSamples); 
    689427 
    690428        /// Pointer to the root of the tree 
    691         VspBspNode *mRoot; 
    692                  
    693         VspBspTreeStatistics mStat; 
     429        BspNode *mRoot; 
     430                 
     431        BspTreeStatistics mStat; 
    694432 
    695433        /// Strategies for choosing next split plane. 
     
    749487        bool mPvsUseArea; 
    750488 
     489        float mEpsilon; 
     490 
     491        int mMaxTests; 
     492 
    751493private: 
    752494         
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp

    r440 r448  
    459459         
    460460        mStat.nodes = 1; 
    461          
    462         mBox.Initialize(); 
    463          
    464         for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 
    465         { 
    466                 leaf->AddRay(RayInfo(*ri)); 
    467  
    468                 mBox.Include((*ri)->GetOrigin()); 
    469                 mBox.Include((*ri)->GetTermination());  
    470         } 
    471          
     461        mBox.Initialize(); 
     462 
     463        //-- compute bounding box 
    472464        if (forcedBoundingBox) 
    473465                mBox = *forcedBoundingBox; 
     466        else 
     467                for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 
     468                { 
     469                        mBox.Include((*ri)->GetOrigin()); 
     470                        mBox.Include((*ri)->GetTermination());  
     471                } 
    474472 
    475473        Debug << "bbox = " << mBox << endl; 
     474 
     475        for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri) 
     476        { 
     477                //leaf->AddRay(RayInfo(*ri)); 
     478                VssRay *ray = *ri; 
     479                 
     480                float minT, maxT; 
     481 
     482                // TODO: not very efficient to implictly cast between rays types ... 
     483                if (mBox.GetRaySegment(*ray, minT, maxT)) 
     484                { 
     485                        float len = ray->Length(); 
     486                         
     487                        if (!len)  
     488                                len = Limits::Small; 
     489                 
     490                        leaf->AddRay(RayInfo(ray, minT / len, maxT / len));  
     491                } 
     492        } 
    476493         
    477494        mStat.rays = (int)leaf->mRays.size(); 
     
    13171334                                                                         stack<RayTraversalData> &tstack) 
    13181335{ 
    1319         VspKdTreeInterior *in =  (VspKdTreeInterior *) data.mNode; 
     1336        VspKdTreeInterior *in = dynamic_cast<VspKdTreeInterior *>(data.mNode); 
    13201337   
    13211338        if (in->mAxis <= VspKdTreeNode::SPLIT_Z)  
     
    16881705     
    16891706        AxisAlignedBox3 box(node->mParent->mBox); 
    1690         if (node->mParent->mFront == node) 
     1707        if (node->mParent->GetFront() == node) 
    16911708                box.SetMin(node->mParent->mAxis, node->mParent->mPosition); 
    16921709        else 
     
    17631780                        VspKdTreeInterior *interior = dynamic_cast<VspKdTreeInterior *>(node); 
    17641781 
    1765                         nodeStack.push(interior->mBack); 
    1766                         nodeStack.push(interior->mFront); 
    1767                 } 
    1768         } 
    1769 } 
     1782                        nodeStack.push(interior->GetBack()); 
     1783                        nodeStack.push(interior->GetFront()); 
     1784                } 
     1785        } 
     1786} 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp

    r446 r448  
    384384  VssTree *vssTree = NULL; 
    385385 
    386   RayContainer bspRays; 
    387  
    388386  while (totalSamples < mInitialSamples) { 
    389387        int passContributingSamples = 0; 
     
    454452  mSceneGraph->CollectObjects(&objects); 
    455453 
    456   //mViewCellsManager->Construct(mVssRays, objects); 
     454  // construct view cells 
     455  mViewCellsManager->Construct(objects, mVssRays, mViewSpaceBox); 
    457456 
    458457  vssTree = new VssTree; 
     
    489488  int samples = 0; 
    490489  int pass = 0; 
     490 
     491  /// Rays used for post processing and visualizations. 
     492  RayContainer storedRays; 
     493  // cast view cell samples 
    491494  while (1) { 
    492495        int num = mVssSamplesPerPass; 
     
    503506          num = GenerateImportanceRays(vssTree, num, rays); 
    504507        } 
    505                  
    506                  
     508                         
    507509        for (int i=0; i < rays.size(); i++) 
    508510          CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays); 
     
    528530        } 
    529531 
    530         // cast rays into BSP tree 
    531         /*if (ViewCell::sHierarchy == ViewCell::BSP)  
    532           { 
    533                 for (int i = 0; i < (int)vssRays.size(); ++ i) 
    534                   { 
    535                         CastRay(*mBspTree, *vssRays[i]); 
    536                   } 
    537           } 
    538 */ 
     532        //-- prepare traversal rays for view cell intersections 
     533        RayContainer passRays; 
     534 
     535        VssRayContainer::const_iterator it, it_end = vssRays.end(); 
     536         
     537        for (it = vssRays.begin(); it != it_end; ++ it) 
     538                passRays.push_back(new Ray(*(*it))); 
     539         
     540        int sampleContributions = 0; 
     541        int contributingSamples = 0; 
     542 
     543        /// compute view cell contribution of rays 
     544        mViewCellsManager->ComputeSampleContributions(passRays, 
     545                                                                                                  sampleContributions,  
     546                                                                                                  contributingSamples); 
     547         
     548        //-- save rays for post processing 
     549        if (((int)storedRays.size() < mViewCellsManager->GetPostProcessSamples()) || 
     550                ((int)storedRays.size() < mViewCellsManager->GetVisualizationSamples())) 
     551        { 
     552                RayContainer::const_iterator it, it_end = passRays.end(); 
     553 
     554                for (it = passRays.begin(); it != it_end; ++ it) 
     555                        storedRays.push_back(new Ray(*(*it))); 
     556        } 
     557        else 
     558        { 
     559                CLEAR_CONTAINER(passRays); 
     560        } 
     561 
    539562        samples+=num; 
    540563        float pvs = vssTree->GetAvgPvsSize(); 
     
    547570        pass++; 
    548571  } 
    549          
     572 
     573  //-- post process view cells 
     574  mViewCellsManager->PostProcess(objects, storedRays); 
     575  mViewCellsManager->Visualize(objects, storedRays); 
     576 
     577  CLEAR_CONTAINER(storedRays); 
     578 
    550579  delete vssTree; 
    551580 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VssRay.h

    r446 r448  
    135135  Vector3 GetNormalizedDir() const { return (mTermination - mOrigin)*mInvSize; } 
    136136 
     137  float Length() const { return Distance(mOrigin, mTermination); } 
     138 
    137139  Vector3 Extrap(const float t) const { 
    138140        return GetOrigin() + t * GetDir(); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h

    r446 r448  
    1919class ViewCell; 
    2020class BspTree; 
     21class VspBspTree; 
     22class BspNode; 
    2123 
    2224class X3dExporter : public Exporter 
     
    9294  ExportGeometry(const ObjectContainer &objects); 
    9395 
     96  bool 
     97  ExportRays(const RayContainer &rays, 
     98                         const float length=1000, 
     99                         const RgbColor &color = RgbColor(1,1,1)); 
     100  bool 
     101  ExportRays(const VssRayContainer &rays, 
     102                         const RgbColor &color = RgbColor(1,1,1)); 
     103 
    94104  virtual void  
    95105  ExportBspSplitPlanes(const BspTree &tree); 
     
    101111  ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves); 
    102112 
    103   bool 
    104   ExportRays(const RayContainer &rays, 
    105                                                  const float length=1000, 
    106                                                  const RgbColor &color = RgbColor(1,1,1)); 
    107  
    108         bool 
    109         ExportRays(const VssRayContainer &rays, 
    110                                                  const RgbColor &color = RgbColor(1,1,1)); 
    111                  
    112113  virtual void 
    113114  ExportBspViewCellPartition(const BspTree &tree, const int maxPvs = 0); 
     
    116117  ExportBspLeaves(const BspTree &tree, const int maxPvs = 0); 
    117118 
     119 
     120  virtual void  
     121  ExportBspSplits(const VspBspTree &tree, const bool exportDepth); 
     122 
     123  virtual void 
     124  ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0); 
     125 
    118126protected: 
     127 
    119128 
    120129  virtual void 
     
    126135  bool 
    127136  ExportBspTreeRayDensity(const BspTree &tree); 
     137   
     138  void 
     139  AddBoxToMesh(const AxisAlignedBox3 &box, 
     140                           Mesh *mesh); 
    128141 
    129         void 
    130         AddBoxToMesh(const AxisAlignedBox3 &box, 
    131                                                          Mesh *mesh); 
    132                  
     142  void ExportBspNodeSplits(BspNode *root, 
     143                                                   const AxisAlignedBox3 &box,  
     144                                                   const bool exportDepth, 
     145                                                   const bool epsilon); 
    133146}; 
    134147  
  • trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp

    r446 r448  
    5858        p->KdTreeStatistics(cout); 
    5959         
    60         // parse view cell hierarchy options 
    61         p->ParseViewCellsOptions(); 
    62    
    6360        // parse view cells related options 
    6461        p->PrepareViewCells(); 
Note: See TracChangeset for help on using the changeset viewer.