Ignore:
Timestamp:
01/08/06 05:56:40 (19 years ago)
Author:
mattausch
Message:

implemented view cells exporting / loading
improved vsp bsp tree (only axis aligbed until a level), reuse results from Plane
testing, collectmergeneighbors
implemented view cell meshes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp

    r503 r508  
    1919 
    2020//-- static members 
     21 
    2122/** Evaluates split plane classification with respect to the plane's 
    2223        contribution for a minimum number of ray splits. 
     
    3536float BspMergeCandidate::sOverallCost = 0; 
    3637 
    37 /****************************************************************/ 
    38 /*                  class VspBspTree implementation             */ 
    39 /****************************************************************/ 
     38/********************************************************************/ 
     39/*                  class VspBspTree implementation                 */ 
     40/********************************************************************/ 
    4041 
    4142VspBspTree::VspBspTree(): 
     
    4445mCostNormalizer(Limits::Small), 
    4546mViewCellsManager(NULL), 
    46 mStoreRays(false), 
    4747mOutOfBoundsCell(NULL), 
    48 mShowInvalidSpace(false) 
     48mShowInvalidSpace(false), 
     49mStoreRays(false) 
    4950{ 
    5051        bool randomize = false; 
     
    8889        environment->GetIntValue("ViewCells.maxPvs", mMaxPvs); 
    8990 
     91        //-- termination criteria for axis aligned split 
     92        environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution",  
     93                mTermMaxRayContriForAxisAligned); 
     94        environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 
     95                mTermMinRaysForAxisAligned); 
     96 
     97        //environment->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory); 
     98        environment->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory); 
    9099 
    91100        //-- debug output 
     
    135144} 
    136145 
     146BspViewCell *VspBspTree::GetOutOfBoundsCell() 
     147{ 
     148        return mOutOfBoundsCell; 
     149} 
     150 
    137151 
    138152BspViewCell *VspBspTree::GetOrCreateOutOfBoundsCell() 
    139153{ 
    140154        if (!mOutOfBoundsCell) 
     155        { 
    141156                mOutOfBoundsCell = new BspViewCell(); 
    142  
     157                mOutOfBoundsCell->SetId(-1); 
     158        } 
    143159        return mOutOfBoundsCell; 
    144160} 
     
    326342} 
    327343 
     344 
     345// return memory usage in MB 
     346float VspBspTree::GetMemUsage() const 
     347{ 
     348        return 
     349                (sizeof(VspBspTree) + 
     350                 mStat.Leaves() * sizeof(BspLeaf) + 
     351                 mStat.Interior() * sizeof(BspInterior) + 
     352                 mStat.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f); 
     353} 
     354 
     355 
     356 
    328357void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 
    329358{ 
     
    350379 
    351380        long startTime = GetTime(); 
     381         
     382        bool mOutOfMemory = false; 
    352383 
    353384        while (!tStack.empty()) 
    354385        { 
    355386                tData = tStack.top(); 
    356  
    357             tStack.pop(); 
     387            tStack.pop();                
     388 
     389                if (0 && !mOutOfMemory) 
     390                { 
     391                        float mem = GetMemUsage(); 
     392 
     393                        if (mem > mMaxMemory) 
     394                        { 
     395                                mOutOfMemory = true; 
     396                                Debug << "memory limit reached: " << mem << endl; 
     397                        } 
     398                } 
    358399 
    359400                // subdivide leaf node 
     
    365406        } 
    366407 
     408        Debug << "Used Memory: " << GetMemUsage() << " MB" << endl; 
    367409        cout << "finished\n"; 
    368410 
    369411        mStat.Stop(); 
    370412} 
     413 
    371414 
    372415bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const 
     
    377420                 (data.mArea <= mTermMinArea) || 
    378421                 (mStat.Leaves() >= mMaxViewCells) || 
    379                 // (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 
     422                (data.GetAvgRayContribution() >= mTermMaxRayContribution) || 
    380423                 (data.mDepth >= mTermMaxDepth)); 
    381424} 
     425 
    382426 
    383427BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, 
     
    386430        BspNode *newNode = tData.mNode; 
    387431 
    388         if (!TerminationCriteriaMet(tData)) 
     432        if (!mOutOfMemory || !TerminationCriteriaMet(tData)) 
    389433        { 
    390434                PolygonContainer coincident; 
     
    423467                } 
    424468                else 
    425                 { 
    426                         // create new view cell for this leaf 
     469                {       // create new view cell for this leaf                    
    427470                        viewCell = new BspViewCell(); 
    428471                } 
     
    465508{ 
    466509        BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 
    467  
    468         int maxCostMisses = tData.mMaxCostMisses; 
    469  
     510         
    470511        // select subdivision plane 
    471512        Plane3 splitPlane; 
    472         if (!SelectPlane(splitPlane, leaf, tData)) 
     513        int maxCostMisses = tData.mMaxCostMisses; 
     514        bool success = SelectPlane(splitPlane,  
     515                                                           leaf,  
     516                                                           tData, 
     517                                                           frontData, 
     518                                                           backData); 
     519        if (!success) 
    473520        { 
    474521                ++ maxCostMisses; 
     
    492539 
    493540        //-- the front and back traversal data is filled with the new values 
     541        frontData.mDepth = tData.mDepth + 1; 
    494542        frontData.mPolygons = new PolygonContainer(); 
    495         frontData.mDepth = tData.mDepth + 1; 
    496543        frontData.mRays = new RayInfoContainer(); 
    497         frontData.mGeometry = new BspNodeGeometry(); 
    498  
     544         
     545        backData.mDepth = tData.mDepth + 1; 
    499546        backData.mPolygons = new PolygonContainer(); 
    500         backData.mDepth = tData.mDepth + 1; 
    501547        backData.mRays = new RayInfoContainer(); 
    502         backData.mGeometry = new BspNodeGeometry(); 
    503  
     548         
    504549        // subdivide rays 
    505550        SplitRays(interior->GetPlane(), 
     
    524569        backData.mPvs = ComputePvsSize(*backData.mRays); 
    525570 
    526         // split geometry and compute area 
    527         if (1) 
    528         { 
    529                 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 
    530                                                                            *backData.mGeometry, 
    531                                                                            interior->GetPlane(), 
    532                                                                            mBox, 
    533                                                                            mEpsilon); 
    534  
    535                 frontData.mArea = frontData.mGeometry->GetArea(); 
    536                 backData.mArea = backData.mGeometry->GetArea(); 
    537         } 
    538  
    539         // compute accumulated ray length 
    540         //frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays); 
    541         //backData.mAccRayLength = AccumulatedRayLength(*backData.mRays); 
     571        // split front and back node geometry and compute area 
     572        if (mPvsUseArea) 
     573        { 
     574                // if not already computed 
     575                if (!frontData.mGeometry && !backData.mGeometry) 
     576                { 
     577                        frontData.mGeometry = new BspNodeGeometry(); 
     578                        backData.mGeometry = new BspNodeGeometry(); 
     579 
     580                        tData.mGeometry->SplitGeometry(*frontData.mGeometry, 
     581                                                                                   *backData.mGeometry, 
     582                                                                                   interior->GetPlane(), 
     583                                                                                   mBox, 
     584                                                                                   mEpsilon); 
     585                 
     586                        frontData.mArea = frontData.mGeometry->GetArea(); 
     587                        backData.mArea = backData.mGeometry->GetArea(); 
     588                } 
     589        } 
     590        else 
     591        { 
     592                frontData.mArea = (float)frontData.mRays->size(); 
     593                backData.mArea = (float)backData.mRays->size(); 
     594        } 
    542595 
    543596        //-- create front and back leaf 
     
    565618        return interior; 
    566619} 
     620 
    567621 
    568622void VspBspTree::AddToPvs(BspLeaf *leaf, 
     
    757811                                                                                 const VspBspTraversalData &tData, 
    758812                                                                                 int &axis, 
    759                                                                                  float &position, 
    760                                                                                  int &raysBack, 
    761                                                                                  int &raysFront, 
    762                                                                                  int &pvsBack, 
    763                                                                                  int &pvsFront) 
    764 { 
    765         AxisAlignedBox3 box; 
    766         box.Initialize(); 
    767  
    768         // create bounding box of region 
    769         RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 
    770  
    771         for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 
    772                 box.Include((*ri).ExtrapTermination()); 
    773  
     813                                                                                 BspNodeGeometry **frontGeom, 
     814                                                                                 BspNodeGeometry **backGeom, 
     815                                                                                 float &frontArea, 
     816                                                                                 float &backArea) 
     817{ 
    774818        const bool useCostHeuristics = false; 
    775819 
     
    777821        float nPosition[3]; 
    778822        float nCostRatio[3]; 
     823        float nFrontArea[3]; 
     824        float nBackArea[3]; 
     825 
     826        BspNodeGeometry *nFrontGeom[3]; 
     827        BspNodeGeometry *nBackGeom[3]; 
     828 
    779829        int bestAxis = -1; 
    780830 
    781         const int sAxis = box.Size().DrivingAxis(); 
     831        // create bounding box of node extent 
     832        AxisAlignedBox3 box; 
     833        box.Initialize(); 
     834         
     835#if 0 
     836        RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 
     837 
     838        for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 
     839                box.Include((*ri).ExtrapTermination()); 
     840#else 
     841        PolygonContainer::const_iterator it, it_end = tData.mGeometry->mPolys.end(); 
     842 
     843        for(it = tData.mGeometry->mPolys.begin(); it < it_end; ++ it) 
     844                box.Include(*(*it)); 
     845 
     846#endif 
     847        int sAxis = box.Size().DrivingAxis(); 
    782848 
    783849        for (axis = 0; axis < 3; ++ axis) 
    784850        { 
     851                nFrontGeom[axis] = new BspNodeGeometry(); 
     852                nBackGeom[axis] = new BspNodeGeometry(); 
     853 
    785854                if (!mOnlyDrivingAxis || axis == sAxis) 
    786855                { 
     
    789858                                nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 
    790859                                Vector3 normal(0,0,0); normal[axis] = 1; 
    791  
    792                                 nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]), tData); 
     860                                 
     861                                nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]),  
     862                                                                                                  tData, *nFrontGeom[axis], *nBackGeom[axis], 
     863                                                                                                  nFrontArea[axis], nBackArea[axis]); 
    793864                        } 
    794865                        else 
     
    809880                        else if (nCostRatio[axis] < nCostRatio[bestAxis]) 
    810881                        { 
    811                                 /*Debug << "pvs front " << nPvsBack[axis] 
    812                                           << " pvs back " << nPvsFront[axis] 
    813                                           << " overall pvs " << leaf->GetPvsSize() << endl;*/ 
    814882                                bestAxis = axis; 
    815883                        } 
     
    820888        //-- assign values 
    821889        axis = bestAxis; 
    822         position = nPosition[bestAxis]; 
    823  
    824         raysBack = 0;//nRaysBack[bestAxis]; 
    825         raysFront = 0;//nRaysFront[bestAxis]; 
    826  
    827         pvsBack = 0;//nPvsBack[bestAxis]; 
    828         pvsFront = 0;//nPvsFront[bestAxis]; 
    829  
    830         Vector3 normal(0,0,0); normal[bestAxis] = 1; 
     890        frontArea = nFrontArea[bestAxis]; 
     891        backArea = nBackArea[bestAxis]; 
     892 
     893        // assign best split nodes geometry  
     894        *frontGeom = nFrontGeom[bestAxis]; 
     895        *backGeom = nBackGeom[bestAxis]; 
     896        // and delete other geometry 
     897        delete nFrontGeom[(bestAxis + 1) % 3]; 
     898        delete nBackGeom[(bestAxis + 2) % 3]; 
     899 
     900        //-- split plane 
     901    Vector3 normal(0,0,0); normal[bestAxis] = 1; 
    831902        plane = Plane3(normal, nPosition[bestAxis]); 
    832          
     903 
    833904        return nCostRatio[bestAxis]; 
    834905} 
    835906 
    836907 
    837 /* 
    838 float VspBspTree::EvalCostRatio(const VspBspTraversalData &tData, 
    839                                                                 const AxisAlignedBox3 &box, 
    840                                                                 const int axis, 
    841                                                                 const float position, 
    842                                                                 int &raysBack, 
    843                                                                 int &raysFront, 
    844                                                                 int &pvsBack, 
    845                                                                 int &pvsFront) 
    846 { 
    847         raysBack = 0; 
    848         raysFront = 0; 
    849         pvsFront = 0; 
    850         pvsBack = 0; 
    851  
    852         Intersectable::NewMail(3); 
    853  
    854         // eval pvs size 
    855         const int pvsSize = tData.mPvs; 
    856  
    857         // create unique ids for pvs heuristics 
    858         GenerateUniqueIdsForPvs(); 
    859  
    860         // this is the main ray classification loop! 
    861         for(RayInfoContainer::iterator ri = tData.mRays->begin(); 
    862                         ri != tData.mRays->end(); ++ ri) 
    863         { 
    864                 if (!(*ri).mRay->IsActive()) 
    865                         continue; 
    866  
    867                 // determine the side of this ray with respect to the plane 
    868                 float t; 
    869                 int side = (*ri).ComputeRayIntersection(axis, position, t); 
    870                          
    871                 if (side <= 0) 
    872                         ++ raysBack; 
    873  
    874                 if (side >= 0) 
    875                         ++ raysFront; 
    876  
    877                 AddObjToPvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 
    878         } 
    879  
    880         //-- only one of these options should be one 
    881  
    882         if (0) //-- only pvs 
    883         { 
    884                 const float sum = float(pvsBack + pvsFront); 
    885                 const float oldCost = (float)pvsSize; 
    886  
    887                 return sum / oldCost; 
    888         } 
    889  
    890         //-- pvs + probability heuristics 
    891         float pBack, pFront, pOverall; 
    892  
    893         if (0) 
    894         { 
    895                 // box length substitute for probability 
    896                 const float minBox = box.Min(axis); 
    897                 const float maxBox = box.Max(axis); 
    898  
    899                 pBack = position - minBox; 
    900                 pFront = maxBox - position; 
    901                 pOverall = maxBox - minBox; 
    902         } 
    903  
    904         if (1) //-- area substitute for probability 
    905         { 
    906                  
    907                 const bool useMidSplit = true; 
    908                 //const bool useMidSplit = false; 
    909                          
    910                 pOverall = box.SurfaceArea(); 
    911                          
    912                 if (!useMidSplit) 
    913                 { 
    914                         Vector3 pos = box.Max(); pos[axis] = position; 
    915                         pBack = AxisAlignedBox3(box.Min(), pos).SurfaceArea(); 
    916  
    917                         pos = box.Min(); pos[axis] = position; 
    918                         pFront = AxisAlignedBox3(pos, box.Max()).SurfaceArea(); 
    919                 } 
    920                 else 
    921                 { 
    922                         //-- simplified computation for mid split 
    923                         const int axis2 = (axis + 1) % 3; 
    924                         const int axis3 = (axis + 2) % 3; 
    925  
    926                         const float faceArea =  
    927                                 (box.Max(axis2) - box.Min(axis2)) * 
    928                                 (box.Max(axis3) - box.Min(axis3)); 
    929  
    930                         pBack = pFront = pOverall * 0.5f + faceArea; 
    931                 } 
    932         } 
    933  
    934         //-- ray density substitute for probability 
    935         if (0) 
    936         { 
    937                 pBack = (float)raysBack; 
    938                 pFront = (float)raysFront; 
    939                 pOverall = (float)tData.mRays->size(); 
    940         } 
    941  
    942         //Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl; 
    943         //Debug << pFront << " " << pBack << " " << pOverall << endl; 
    944  
    945         // float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 
    946         const float newCost = pvsBack * pBack + pvsFront * pFront; 
    947         //  float oldCost = leaf->mRays.size(); 
    948         const float oldCost = (float)pvsSize * pOverall; 
    949  
    950         return  (mCtDivCi + newCost) / oldCost; 
    951 } 
    952 */ 
    953  
    954  
    955 bool VspBspTree::SelectPlane(Plane3 &plane, 
     908bool VspBspTree::SelectPlane(Plane3 &bestPlane, 
    956909                                                         BspLeaf *leaf, 
    957                                                          VspBspTraversalData &data) 
     910                                                         VspBspTraversalData &data, 
     911                                                         VspBspTraversalData &frontData, 
     912                                                         VspBspTraversalData &backData) 
    958913{ 
    959914        // simplest strategy: just take next polygon 
     
    962917        if (!data.mPolygons->empty()) 
    963918                { 
    964                         const int randIdx = (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 
     919                        const int randIdx =  
     920                                (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 
    965921                        Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 
    966922 
    967                         plane = nextPoly->GetSupportingPlane(); 
     923                        bestPlane = nextPoly->GetSupportingPlane(); 
    968924                        return true; 
    969925                } 
    970926        } 
    971927 
    972         // use heuristics to find appropriate plane 
    973         return SelectPlaneHeuristics(plane, leaf, data); 
     928        //-- use heuristics to find appropriate plane 
     929 
     930        // intermediate plane 
     931        Plane3 plane; 
     932        float lowestCost = MAX_FLOAT; 
     933                 
     934        const bool onlyAxisAligned  =  
     935                (mSplitPlaneStrategy & AXIS_ALIGNED) && 
     936                ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 
     937                ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 
     938         
     939        // split polygons if no axis aligned splits 
     940        const int limit = onlyAxisAligned ? 0 :  
     941                Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
     942 
     943        float candidateCost; 
     944 
     945        int maxIdx = (int)data.mPolygons->size(); 
     946 
     947        for (int i = 0; i < limit; ++ i) 
     948        { 
     949                //-- assure that no index is taken twice 
     950                const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 
     951                Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
     952 
     953                // swap candidate to the end to avoid testing same plane 
     954                std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 
     955                //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 
     956 
     957                // evaluate current candidate 
     958                BspNodeGeometry fGeom, bGeom; 
     959                float fArea, bArea; 
     960                plane = poly->GetSupportingPlane(); 
     961                candidateCost = SplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 
     962                 
     963                if (candidateCost < lowestCost) 
     964                { 
     965                        bestPlane = plane; 
     966                        lowestCost = candidateCost; 
     967                } 
     968        } 
     969 
     970        //-- evaluate axis aligned splits 
     971        int axis; 
     972        BspNodeGeometry *fGeom, *bGeom; 
     973        float fArea, bArea; 
     974 
     975        candidateCost = SelectAxisAlignedPlane(plane, data, axis, 
     976                                                                                   &fGeom, &bGeom,  
     977                                                                                   fArea, bArea);                                                 
     978 
     979        if (candidateCost < lowestCost) 
     980        {        
     981                bestPlane = plane; 
     982                lowestCost = candidateCost; 
     983 
     984                //-- assign already computed values 
     985                frontData.mGeometry = fGeom; 
     986                backData.mGeometry = bGeom; 
     987                frontData.mArea = fArea; 
     988                backData.mArea = bArea; 
     989 
     990                //! error also computed if cost ratio is missed 
     991                ++ mStat.splits[axis]; 
     992        } 
     993        else 
     994        { 
     995                DEL_PTR(fGeom); 
     996                DEL_PTR(bGeom); 
     997        } 
     998 
     999#ifdef _DEBUG 
     1000        Debug << "plane lowest cost: " << lowestCost << endl; 
     1001#endif 
     1002 
     1003        // cost ratio miss 
     1004        if (lowestCost > mTermMaxCostRatio) 
     1005                return false; 
     1006 
     1007        return true; 
    9741008} 
    9751009 
     
    10481082 
    10491083 
    1050 bool VspBspTree::SelectPlaneHeuristics(Plane3 &bestPlane, 
    1051                                                                            BspLeaf *leaf, 
    1052                                                                            VspBspTraversalData &data) 
    1053 { 
    1054         float lowestCost = MAX_FLOAT; 
    1055         // intermediate plane 
    1056         Plane3 plane; 
    1057         bool useAxisAlignedPlane = false; 
    1058  
    1059         const int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates); 
    1060         int maxIdx = (int)data.mPolygons->size(); 
    1061  
    1062         float candidateCost; 
    1063  
    1064         for (int i = 0; i < limit; ++ i) 
    1065         { 
    1066                 //-- assure that no index is taken twice 
    1067                 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 
    1068                 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 
    1069  
    1070                 // swap candidate to the end to avoid testing same plane 
    1071                 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 
    1072  
    1073                 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 
    1074  
    1075                 // evaluate current candidate 
    1076                 candidateCost = SplitPlaneCost(poly->GetSupportingPlane(), data); 
    1077  
    1078                 if (candidateCost < lowestCost) 
    1079                 { 
    1080                         bestPlane = poly->GetSupportingPlane(); 
    1081                         lowestCost = candidateCost; 
    1082                 } 
    1083         } 
    1084  
    1085         //-- axis aligned splits 
    1086         int axis; 
    1087         float position; 
    1088         int raysBack; 
    1089         int raysFront; 
    1090         int pvsFront; 
    1091         int pvsBack; 
    1092  
    1093         candidateCost = SelectAxisAlignedPlane(plane,  
    1094                                                                                    data,  
    1095                                                                                    axis, 
    1096                                                                                    position, 
    1097                                                                                    raysBack, 
    1098                                                                                    raysFront, 
    1099                                                                                    pvsFront, 
    1100                                                                                    pvsBack); 
    1101  
    1102         if (candidateCost < lowestCost) 
    1103         {        
    1104                 if (!useAxisAlignedPlane) 
    1105                 { 
    1106                         useAxisAlignedPlane = true; 
    1107                         //if (data.mPolygons->size() > 0) 
    1108                         //      Debug << "haha" << endl; 
    1109                         //! error also computed if cost ratio is missed 
    1110                         ++ mStat.splits[axis]; 
    1111                 } 
    1112  
    1113                 bestPlane = plane; 
    1114                 lowestCost = candidateCost; 
    1115         } 
    1116  
    1117 #ifdef _DEBUG 
    1118         Debug << "plane lowest cost: " << lowestCost << endl; 
    1119 #endif 
    1120  
    1121         // cost ratio miss 
    1122         if (lowestCost > mTermMaxCostRatio) 
    1123                 return false; 
    1124  
    1125         return true; 
    1126 } 
    1127  
    1128  
    11291084inline void VspBspTree::GenerateUniqueIdsForPvs() 
    11301085{ 
     
    11361091 
    11371092float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
    1138                                                                  const VspBspTraversalData &data) const 
     1093                                                                 const VspBspTraversalData &data, 
     1094                                                                 BspNodeGeometry &geomFront, 
     1095                                                                 BspNodeGeometry &geomBack, 
     1096                                                                 float &areaFront, 
     1097                                                                 float &areaBack) const 
    11391098{ 
    11401099        float cost = 0; 
     
    11431102        float sumRaySplits = 0; 
    11441103 
    1145         int frontPvs = 0; 
    1146         int backPvs = 0; 
    1147  
    1148         // probability that view point lies in child 
     1104        int pvsFront = 0; 
     1105        int pvsBack = 0; 
     1106 
     1107        // probability that view point lies in back / front node 
    11491108        float pOverall = 0; 
    11501109        float pFront = 0; 
    11511110        float pBack = 0; 
    11521111 
     1112        int raysFront = 0; 
     1113        int raysBack = 0; 
     1114        int totalPvs = 0; 
     1115 
    11531116        if (mSplitPlaneStrategy & PVS) 
    11541117        { 
     
    11591122                { 
    11601123                        // construct child geometry with regard to the candidate split plane 
    1161                         BspNodeGeometry frontCell; 
    1162                         BspNodeGeometry backCell; 
    1163  
    1164                         data.mGeometry->SplitGeometry(frontCell, 
    1165                                                                                   backCell, 
     1124                        data.mGeometry->SplitGeometry(geomFront, 
     1125                                                                                  geomBack, 
    11661126                                                                                  candidatePlane, 
    11671127                                                                                  mBox, 
    11681128                                                                                  mEpsilon); 
    11691129 
    1170                         pFront = frontCell.GetArea(); 
    1171                         pBack = backCell.GetArea(); 
    1172  
     1130                        areaFront = geomFront.GetArea(); 
     1131                        areaBack = geomBack.GetArea(); 
     1132 
     1133                        pBack = areaBack; 
     1134                        pFront = areaFront; 
    11731135                        pOverall = data.mArea; 
     1136                } 
     1137                else // use number of rays to approximate volume 
     1138                { 
     1139                        pOverall = (float)data.mRays->size(); 
     1140                        pFront = (float)raysFront; 
     1141                        pBack = (float)raysBack; 
    11741142                } 
    11751143        } 
     
    11891157                limit = (int)data.mRays->size(); 
    11901158        } 
    1191  
     1159         
    11921160        for (int i = 0; i < limit; ++ i) 
    11931161        { 
    1194                 const int testIdx = useRand ? (int)RandomValue(0, (Real)(limit - 1)) : i; 
     1162                const int testIdx = useRand ?  
     1163                        (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
    11951164                RayInfo rayInf = (*data.mRays)[testIdx]; 
    11961165 
     1166                float t; 
    11971167                VssRay *ray = rayInf.mRay; 
    1198                 float t; 
    11991168                const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
     1169 
     1170        if (cf >= 0) 
     1171                        ++ raysFront; 
     1172                if (cf <= 0) 
     1173                        ++ raysBack; 
    12001174 
    12011175                if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     
    12121186                if (mSplitPlaneStrategy & PVS) 
    12131187                { 
    1214                         // in case the ray intersects an object 
    1215                         // assure that we only count the object 
    1216                         // once for the front and once for the back side of the plane 
    1217                         AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs); 
    1218                         AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs); 
    1219  
    1220                         // use number of rays to approximate volume 
    1221                         if (!mPvsUseArea) 
    1222                         { 
    1223                                 pOverall = (float)data.mRays->size(); 
    1224  
    1225                                 if (cf >= 0) 
    1226                                         ++ pFront; 
    1227                                 if (cf <= 0) 
    1228                                         ++ pBack; 
    1229                         } 
     1188                        // find front and back pvs for origing and termination object 
     1189                        AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
     1190                        AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
    12301191                } 
    12311192        } 
     
    12421203        if (mSplitPlaneStrategy & PVS) 
    12431204        { 
    1244                 const float oldCost = pOverall * (float)data.mPvs + Limits::Small; 
    1245                 cost += mPvsFactor * (frontPvs * pFront + backPvs * pBack) / oldCost; 
    1246  
    1247                 //cost += mPvsFactor * 0.5 * (frontPvs * pFront + backPvs * pBack) / oldCost; 
    1248                 //Debug << "new cost: " << cost << " over" << frontPvs * pFront + backPvs * pBack << " old cost " << oldCost << endl; 
    1249  
    1250                 if (0) // give penalty to unbalanced split 
    1251                         if (((pFront * 0.2 + Limits::Small) > pBack) || 
    1252                                 (pFront < (pBack * 0.2 + Limits::Small))) 
    1253                                         cost += 0.5; 
     1205                const float oldCost = pOverall * (float)totalPvs + Limits::Small; 
     1206                cost += mPvsFactor * (pvsFront * pFront + pvsBack * pBack) / oldCost; 
    12541207        } 
    12551208 
    12561209#ifdef _DEBUG 
    12571210        Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 
    1258                   << " frontpvs: " << frontPvs << " pFront: " << pFront 
    1259                   << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl; 
     1211                  << " frontpvs: " << pvsFront << " pFront: " << pFront 
     1212                  << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 
    12601213#endif 
    12611214 
     
    12631216        return cost / (float)mCostNormalizer; 
    12641217} 
     1218 
    12651219 
    12661220void VspBspTree::AddObjToPvs(Intersectable *obj, 
    12671221                                                         const int cf, 
    12681222                                                         int &frontPvs, 
    1269                                                          int &backPvs) const 
     1223                                                         int &backPvs, 
     1224                                                         int &totalPvs) const 
    12701225{ 
    12711226        if (!obj) 
    12721227                return; 
     1228         
     1229        if ((obj->mMailbox != sFrontId) && 
     1230                (obj->mMailbox != sBackId) && 
     1231                (obj->mMailbox != sFrontAndBackId)) 
     1232        { 
     1233                ++ totalPvs; 
     1234        } 
     1235 
    12731236        // TODO: does this really belong to no pvs? 
    12741237        //if (cf == Ray::COINCIDENT) return; 
     
    12811244                { 
    12821245                        ++ frontPvs; 
    1283  
     1246                 
    12841247                        if (obj->mMailbox == sBackId) 
    12851248                                obj->mMailbox = sFrontAndBackId; 
     
    12951258                { 
    12961259                        ++ backPvs; 
    1297  
     1260                 
    12981261                        if (obj->mMailbox == sFrontId) 
    12991262                                obj->mMailbox = sFrontAndBackId; 
     
    13221285                        BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
    13231286                        if (leaf->TreeValid() &&  
    1324                                 (!onlyUnmailed || leaf->Mailed()) && 
     1287                                (!onlyUnmailed || !leaf->Mailed()) && 
    13251288                                ((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize))) 
    13261289                        { 
     
    13511314 
    13521315 
    1353 BspViewCell *VspBspTree::GetOutOfBoundsCell() const 
    1354 { 
    1355         return mOutOfBoundsCell; 
    1356 } 
    1357  
    1358  
    13591316void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data) 
    13601317{ 
     
    13681325        if (data.mPvs > mStat.maxPvs) 
    13691326                mStat.maxPvs = data.mPvs; 
     1327         
    13701328        if (data.mDepth < mStat.minDepth) 
    13711329                mStat.minDepth = data.mDepth; 
     1330 
    13721331        if (data.mDepth >= mTermMaxDepth) 
    13731332                ++ mStat.maxDepthNodes; 
     1333        // accumulate rays to compute rays /  leaf 
     1334        mStat.accumRays += (int)data.mRays->size(); 
    13741335 
    13751336        if (data.mPvs < mTermMinPvs) 
     
    13831344 
    13841345        if (data.mArea <= mTermMinArea) 
    1385         { 
    1386                 //Debug << "area: " << data.mArea / mBox.SurfaceArea() << " min area: " << mTermMinArea / mBox.SurfaceArea() << endl; 
    13871346                ++ mStat.minAreaNodes; 
    1388         } 
     1347         
    13891348        // accumulate depth to compute average depth 
    13901349        mStat.accumDepth += data.mDepth; 
     
    14981457} 
    14991458 
    1500 bool VspBspTree::Export(const string filename) 
    1501 { 
    1502         Exporter *exporter = Exporter::GetExporter(filename); 
    1503  
    1504         if (exporter) 
    1505         { 
    1506                 //exporter->ExportVspBspTree(*this); 
    1507                 return true; 
    1508         } 
    1509  
    1510         return false; 
    1511 } 
    1512  
    15131459void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const 
    15141460{ 
     
    15161462 
    15171463        if (!mRoot) 
    1518         return; 
     1464                return; 
    15191465 
    15201466        nodeStack.push(mRoot); 
     
    15431489                { 
    15441490                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    1545                          
     1491                 
    15461492                        nodeStack.push(interior->GetFront()); 
    15471493                        nodeStack.push(interior->GetBack()); 
     
    22452191{ 
    22462192        BspLeaf::NewMail(); 
    2247  
     2193         
    22482194        vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 
    22492195 
     2196        Debug << "mergequeue size: " << mMergeQueue.size() << endl; 
    22502197        // find merge candidates and push them into queue 
    22512198        for (it = leaves.begin(); it != it_end; ++ it) 
     
    22682215                // TODO: test if at least one ray goes from one leaf to the other 
    22692216                for (nit = neighbors.begin(); nit != nit_end; ++ nit) 
    2270                 {                        
    2271                         mMergeQueue.push(BspMergeCandidate(leaf, *nit)); 
    2272                 } 
    2273         } 
     2217                { 
     2218                        if ((*nit)->GetViewCell() != leaf->GetViewCell()) 
     2219                                mMergeQueue.push(BspMergeCandidate(leaf, *nit)); 
     2220                } 
     2221        } 
     2222 
     2223        Debug << "new mergequeue size: " << mMergeQueue.size() << endl; 
    22742224 
    22752225        return (int)leaves.size(); 
     
    22832233        long startTime = GetTime(); 
    22842234        ConstructBspRays(bspRays, rays); 
    2285         Debug << (int)bspRays.size() << " bsp rays constructed in " << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl; 
     2235        Debug << (int)bspRays.size() << " bsp rays constructed in "  
     2236                  << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl; 
    22862237 
    22872238        map<BspLeaf *, vector<BspLeaf*> > neighborMap; 
     
    23242275            leaf = (*iit).mLeaf; 
    23252276 
    2326                         // view space not valid 
    2327                         if (!leaf->TreeValid() || !prevLeaf->TreeValid()) 
     2277                        // view space not valid or same view cell 
     2278                        if (!leaf->TreeValid() || !prevLeaf->TreeValid() || 
     2279                                (leaf->GetViewCell() == prevLeaf->GetViewCell())) 
    23282280                                continue; 
    23292281 
     
    23792331        vector<BspLeaf *> leaves; 
    23802332        CollectLeaves(leaves, true, mMaxPvs); 
    2381         Debug << "found " << (int)leaves.size() << " new leaves" << endl; 
    2382         //CollectMergeCandidates(leaves); 
     2333        Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 
     2334        // TODO 
     2335        CollectMergeCandidates(leaves); 
    23832336 
    23842337        return numLeaves; 
     
    25082461 
    25092462 
    2510 ViewCell * 
    2511 VspBspTree::GetViewCell(const Vector3 &point) 
     2463ViewCell *VspBspTree::GetViewCell(const Vector3 &point) 
    25122464{ 
    25132465  if (mRoot == NULL) 
     
    27372689} 
    27382690 
    2739 #define USE_ASCII 0 
    2740 bool VspBspTree::WriteVspBspTree() 
    2741 { 
    2742         char fileName[100]; 
    2743         environment->GetStringValue("VspBspTree.viewCellsFilename", fileName); 
     2691 
     2692bool VspBspTree::Export(ofstream &stream) 
     2693{ 
     2694        ExportNode(mRoot, stream); 
     2695 
     2696        return true; 
     2697} 
     2698 
     2699 
     2700void VspBspTree::ExportNode(BspNode *node, ofstream &stream) 
     2701{ 
     2702        if (node->IsLeaf()) 
     2703        { 
     2704                BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
     2705                         
     2706                int id = -1; 
     2707                if (leaf->GetViewCell() != mOutOfBoundsCell) 
     2708                        id = leaf->GetViewCell()->GetId(); 
     2709 
     2710                stream << "<Leaf viewCellId=\"" << id << "\" />" << endl; 
     2711        } 
     2712        else 
     2713        { 
     2714                BspInterior *interior = dynamic_cast<BspInterior *>(node); 
    27442715         
    2745         /*VssRayContainer::const_iterator it, it_end = samples.end(); 
    2746          
    2747 #if USE_ASCII 
    2748         ofstream samplesOut(fileName); 
    2749         if (!samplesOut.is_open()) 
    2750                 return false; 
    2751  
    2752         for (it = samples.begin(); it != it_end; ++ it) 
    2753         { 
    2754                 VssRay *ray = *it; 
    2755                 int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;                
    2756                 int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;        
    2757  
    2758                 samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " "  
    2759                                    << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " "  
    2760                                    << sourceid << " " << termid << "\n"; 
    2761         } 
    2762 #else 
    2763         ofstream samplesOut(fileName, ios::binary); 
    2764         if (!samplesOut.is_open()) 
    2765                 return false; 
    2766  
    2767         for (it = samples.begin(); it != it_end; ++ it) 
    2768         {        
    2769                 VssRay *ray = *it; 
    2770                 Vector3 origin(ray->GetOrigin()); 
    2771                 Vector3 termination(ray->GetTermination()); 
    2772                  
    2773                 int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;                
    2774                 int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;                
    2775  
    2776                 samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3)); 
    2777                 samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3)); 
    2778                 samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int)); 
    2779                 samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int)); 
    2780     } 
    2781 #endif 
    2782  
    2783         samplesOut.close(); 
    2784         */ 
    2785         return true; 
    2786 } 
    2787  
    2788 bool VspBspTree::LoadVspBspTree() 
    2789 { 
    2790         /*std::stable_sort(objects.begin(), objects.end(), ilt); 
    2791         char fileName[100]; 
    2792         environment->GetStringValue("Preprocessor.samplesFilename", fileName); 
    2793          
    2794     Vector3 origin, termination; 
    2795         // HACK: needed only for lower_bound algorithm to find the  
    2796         // intersected objects 
    2797         MeshInstance sObj(NULL); 
    2798         MeshInstance tObj(NULL); 
    2799  
    2800 #if USE_ASCII 
    2801         ifstream samplesIn(fileName, ios::binary); 
    2802         if (!samplesIn.is_open()) 
    2803                 return false; 
    2804  
    2805         string buf; 
    2806         while (!(getline(samplesIn, buf)).eof()) 
    2807         { 
    2808                 sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d",  
    2809                            &origin.x, &origin.y, &origin.z, 
    2810                            &termination.x, &termination.y, &termination.z,  
    2811                            &(sObj.mId), &(tObj.mId)); 
    2812                  
    2813                 Intersectable *sourceObj = NULL; 
    2814                 Intersectable *termObj = NULL; 
    2815                  
    2816                 if (sObj.mId >= 0) 
    2817                 { 
    2818                         ObjectContainer::iterator oit = 
    2819                                 lower_bound(objects.begin(), objects.end(), &sObj, ilt); 
    2820                         sourceObj = *oit; 
    2821                 } 
    2822                  
    2823                 if (tObj.mId >= 0) 
    2824                 { 
    2825                         ObjectContainer::iterator oit = 
    2826                                 lower_bound(objects.begin(), objects.end(), &tObj, ilt); 
    2827                         termObj = *oit; 
    2828                 } 
    2829  
    2830                 samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); 
    2831         } 
    2832 #else 
    2833         ifstream samplesIn(fileName, ios::binary); 
    2834         if (!samplesIn.is_open()) 
    2835                 return false; 
    2836  
    2837         while (1) 
    2838         { 
    2839                  samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3)); 
    2840                  samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3)); 
    2841                  samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int)); 
    2842                  samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int)); 
    2843                  
    2844                  if (samplesIn.eof()) 
    2845                         break; 
    2846  
    2847                 Intersectable *sourceObj = NULL; 
    2848                 Intersectable *termObj = NULL; 
    2849                  
    2850                 if (sObj.mId >= 0) 
    2851                 { 
    2852                         ObjectContainer::iterator oit = 
    2853                                 lower_bound(objects.begin(), objects.end(), &sObj, ilt); 
    2854                         sourceObj = *oit; 
    2855                 } 
    2856                  
    2857                 if (tObj.mId >= 0) 
    2858                 { 
    2859                         ObjectContainer::iterator oit = 
    2860                                 lower_bound(objects.begin(), objects.end(), &tObj, ilt); 
    2861                         termObj = *oit; 
    2862                 } 
    2863  
    2864                 samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); 
    2865         } 
    2866  
    2867 #endif 
    2868         samplesIn.close(); 
    2869 */ 
    2870         return true; 
    2871 } 
    2872  
     2716                Plane3 plane = interior->GetPlane(); 
     2717                stream << "<Interior plane=\"" << plane.mNormal.x << " "  
     2718                           << plane.mNormal.y << " " << plane.mNormal.z << " "  
     2719                           << plane.mD << "\">" << endl; 
     2720 
     2721                ExportNode(interior->GetBack(), stream); 
     2722                ExportNode(interior->GetFront(), stream); 
     2723 
     2724                stream << "</Interior>" << endl; 
     2725        } 
     2726} 
    28732727 
    28742728/************************************************************************/ 
Note: See TracChangeset for help on using the changeset viewer.