Ignore:
Timestamp:
02/01/06 19:29:59 (18 years ago)
Author:
mattausch
Message:

implemented variance
started implementing merge history

File:
1 edited

Legend:

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

    r564 r580  
    44#include "MeshKdTree.h" 
    55#include "Triangle3.h" 
     6#include "common.h" 
     7#include "Environment.h" 
     8#include "ViewCellsManager.h" 
     9#include "Exporter.h" 
     10 
    611#include <time.h> 
    712#include <iomanip> 
     13#include <stack> 
     14 
     15 
     16 
     17template <typename T> class myless 
     18{ 
     19public: 
     20         
     21        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const 
     22        bool operator() (T v1, T v2) const 
     23        { 
     24                return (v1->GetTimeStamp() > v2->GetTimeStamp()); 
     25        } 
     26}; 
     27 
     28 
     29typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > TraversalQueue; 
     30 
     31int ViewCell::sMailId = 21843194198; 
     32int ViewCell::sReservedMailboxes = 1; 
     33 
     34//int upperPvsLimit = 120; 
     35//int lowerPvsLimit = 5; 
     36 
     37float MergeCandidate::sRenderCostWeight = 0; 
     38 
     39 
     40// pvs penalty can be different from pvs size 
     41inline float EvalPvsPenalty(const int pvs,  
     42                                                        const int lower, 
     43                                                        const int upper) 
     44{ 
     45        // clamp to minmax values 
     46        if (pvs < lower) 
     47                return (float)lower; 
     48        if (pvs > upper) 
     49                return (float)upper; 
     50 
     51        return (float)pvs; 
     52} 
     53 
     54 
     55int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2) 
     56{ 
     57        int pvs = pvs1.GetSize(); 
     58 
     59        // compute new pvs size 
     60        ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end(); 
     61 
     62        Intersectable::NewMail(); 
     63 
     64        for (it = pvs1.mEntries.begin(); it != it_end; ++ it) 
     65        { 
     66                (*it).first->Mail(); 
     67        } 
     68 
     69        it_end = pvs2.mEntries.end(); 
     70 
     71        for (it = pvs2.mEntries.begin(); it != it_end; ++ it) 
     72        { 
     73                Intersectable *obj = (*it).first; 
     74                if (!obj->Mailed()) 
     75                        ++ pvs; 
     76        } 
     77 
     78        return pvs; 
     79} 
     80 
    881 
    982ViewCell::ViewCell():  
     
    1285mArea(-1), 
    1386mVolume(-1), 
    14 mValid(true) 
     87mValid(true), 
     88mParent(NULL), 
     89mTimeStamp(0) 
    1590{ 
    1691} 
     
    2196mArea(-1), 
    2297mVolume(-1), 
    23 mValid(true) 
     98mValid(true), 
     99mParent(NULL), 
     100mTimeStamp(0) 
    24101{ 
    25102} 
     
    43120 
    44121 
    45 void ViewCell::AddPassingRay(const Ray &ray, const int contributions) 
    46 { 
    47         mPassingRays.AddRay(ray, contributions); 
    48 } 
    49  
    50  
    51122float ViewCell::GetVolume() const 
    52123{ 
     
    113184 
    114185 
     186/*bool ViewCell::IsLeaf() const 
     187{ 
     188        return true; 
     189}*/ 
     190 
     191 
     192void ViewCell::SetParent(ViewCellInterior *parent) 
     193{ 
     194        mParent = parent; 
     195} 
     196 
     197 
     198bool ViewCell::IsRoot() const 
     199{ 
     200        return !mParent; 
     201} 
     202 
     203 
     204ViewCellInterior *ViewCell::GetParent() const 
     205{ 
     206        return mParent; 
     207} 
     208 
     209 
     210void ViewCell::SetTimeStamp(const int timeStamp) 
     211{ 
     212        mTimeStamp = timeStamp; 
     213} 
     214 
     215 
     216int ViewCell::GetTimeStamp() const 
     217{ 
     218        return mTimeStamp; 
     219} 
     220 
     221 
     222/************************************************************************/ 
     223/*                class ViewCellInterior implementation                 */ 
     224/************************************************************************/ 
     225 
     226 
     227ViewCellInterior::ViewCellInterior() 
     228{ 
     229} 
     230 
     231 
     232ViewCellInterior::~ViewCellInterior() 
     233{ 
     234        ViewCellContainer::const_iterator it, it_end = mChildren.end(); 
     235 
     236        for (it = mChildren.begin(); it != it_end; ++ it) 
     237                delete (*it); 
     238} 
     239 
     240 
     241ViewCellInterior::ViewCellInterior(Mesh *mesh):  
     242ViewCell(mesh) 
     243{ 
     244} 
     245 
     246 
     247bool ViewCellInterior::IsLeaf() const 
     248{ 
     249        return false; 
     250} 
     251 
     252 
     253void ViewCellInterior::SetupChildLink(ViewCell *l) 
     254{ 
     255    mChildren.push_back(l); 
     256    l->mParent = this; 
     257} 
     258 
     259 
     260 
    115261/************************************************************************/ 
    116262/*                class ViewCellsStatistics implementation              */ 
    117263/************************************************************************/ 
    118264 
     265 
     266 
     267 
    119268void ViewCellsStatistics::Print(ostream &app) const 
    120269{ 
     
    145294        app << "========== End of View Cells Statistics ==========\n"; 
    146295} 
     296 
     297 
     298/*************************************************************************/ 
     299/*                    class ViewCellsTree implementation                 */ 
     300/*************************************************************************/ 
     301 
     302 
     303ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm): 
     304mRoot(NULL), 
     305mUseAreaForPvs(false), 
     306mViewCellsManager(vcm) 
     307{ 
     308        environment->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells); 
     309 
     310        //-- merge options 
     311        environment->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight); 
     312        environment->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells); 
     313        environment->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio); 
     314         
     315        MergeCandidate::sRenderCostWeight = mRenderCostWeight; 
     316 
     317        mStats.open("mergeStats.log"); 
     318} 
     319 
     320 
     321int ViewCellsTree::GetSize(ViewCell *vc) const 
     322{ 
     323        int vcSize = 0; 
     324 
     325        stack<ViewCell *> tstack; 
     326 
     327        tstack.push(vc); 
     328 
     329        while (!tstack.empty()) 
     330        { 
     331                ViewCell *vc = tstack.top(); 
     332                tstack.pop(); 
     333 
     334                if (vc->IsLeaf()) 
     335                { 
     336                        ++ vcSize; 
     337                } 
     338                else 
     339                { 
     340                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc); 
     341                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end(); 
     342                        for (it = interior->mChildren.begin(); it != it_end; ++ it) 
     343                                tstack.push(*it); 
     344                         
     345                } 
     346        } 
     347 
     348        return vcSize; 
     349} 
     350 
     351 
     352void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const 
     353{ 
     354        stack<ViewCell *> tstack; 
     355 
     356        tstack.push(vc); 
     357 
     358        while (!tstack.empty()) 
     359        { 
     360                ViewCell *vc = tstack.top(); 
     361                tstack.pop(); 
     362 
     363                if (vc->IsLeaf()) 
     364                { 
     365                        leaves.push_back(vc); 
     366                } 
     367                else 
     368                { 
     369                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc); 
     370                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end(); 
     371                        for (it = interior->mChildren.begin(); it != it_end; ++ it) 
     372                                tstack.push(*it); 
     373                         
     374                } 
     375        } 
     376} 
     377 
     378 
     379ViewCellsTree::~ViewCellsTree() 
     380{ 
     381        DEL_PTR(mRoot); 
     382} 
     383 
     384 
     385int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays,  
     386                                                                          const ObjectContainer &objects) 
     387{ 
     388        // number of view cells equals the number of leaves  
     389        // (without the invalid ones ) 
     390        //mNumViewCells = mBspStats.Leaves();//- mBspStats.invalidLeaves; 
     391        mNumViewCells = (int)mViewCellsManager->GetViewCells().size(); 
     392 
     393        float variance = 0; 
     394        int totalPvs = 0; 
     395        float totalCost = 0; 
     396 
     397        //-- compute statistics values of initial view cells 
     398        mViewCellsManager->EvaluateRenderStatistics(totalCost, 
     399                                                                                                mExpectedCost, 
     400                                                                                                mDeviation, 
     401                                                                                                variance, 
     402                                                                                                totalPvs, 
     403                                                                                                mAvgRenderCost); 
     404 
     405 
     406        //-- fill merge queue 
     407        vector<MergeCandidate> candidates; 
     408 
     409        mViewCellsManager->CollectMergeCandidates(rays, candidates); 
     410        while(!candidates.empty()) 
     411        { 
     412                MergeCandidate mc = candidates.back(); 
     413                candidates.pop_back(); 
     414                EvalMergeCost(mc); 
     415                mMergeQueue.push(mc); 
     416        } 
     417 
     418        Debug << "************************* merge ***********************************" << endl;   
     419        Debug << "deviation: " << mDeviation << endl; 
     420        Debug << "avg render cost: " << mAvgRenderCost << endl; 
     421        Debug << "expected cost: " <<mExpectedCost << endl; 
     422 
     423 
     424        ViewCellsManager::PvsStatistics pvsStats; 
     425        mViewCellsManager->GetPvsStatistics(pvsStats); 
     426 
     427        static float expectedValue = pvsStats.avgPvs; 
     428         
     429        // the current view cells are kept in this container 
     430        // we start with the current view cells from the 
     431        // view cell manager. They will change with 
     432        // subsequent merges 
     433        ViewCellContainer &viewCells = mViewCellsManager->GetViewCells(); 
     434 
     435 
     436        ViewCell::NewMail(); 
     437 
     438        MergeStatistics mergeStats; 
     439        mergeStats.Start(); 
     440         
     441        long startTime = GetTime(); 
     442 
     443        mergeStats.collectTime = TimeDiff(startTime, GetTime()); 
     444        mergeStats.candidates = (int)mMergeQueue.size(); 
     445        startTime = GetTime(); 
     446 
     447        // frequency stats are updated 
     448        const int statsOut = 100; 
     449 
     450        // passes are needed for statistics, because we don't want to record 
     451        // every merge 
     452        int pass = 0; 
     453        int mergedPerPass = 0; 
     454        float realExpectedCost = mExpectedCost; 
     455        float realAvgRenderCost = mAvgRenderCost; 
     456        int realNumViewCells = mNumViewCells; 
     457         
     458        // maximal ratio of old expected render cost to expected render 
     459        // when the the render queue has to be reset. 
     460        float avgCostMaxDeviation; 
     461        int maxMergesPerPass; 
     462        int numActiveViewCells = 0; 
     463 
     464        environment->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", maxMergesPerPass); 
     465        environment->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", avgCostMaxDeviation); 
     466 
     467        cout << "actual merge starts now ... " << endl; 
     468         
     469        //ResetMergeQueue(); 
     470 
     471        //-- use priority queue to merge leaf pairs 
     472 
     473        while (!mMergeQueue.empty() && (realNumViewCells > mMergeMinViewCells) && 
     474                   (mMergeQueue.top().GetRenderCost() < mMergeMaxCostRatio * totalCost)) 
     475        { 
     476                //-- reset merge queue if the ratio of current expected cost / real expected cost 
     477                //   too small or after a given number of merges 
     478                if(0) 
     479                if ((mergedPerPass > maxMergesPerPass) || 
     480                        (avgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost)) 
     481                { 
     482                        Debug << "************ reset queue *****************\n" 
     483                                  << "ratios: " << avgCostMaxDeviation  
     484                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost 
     485                                  << " merged per pass : " << mergedPerPass << " of maximal " << maxMergesPerPass << endl; 
     486 
     487                        Debug << "Values before reset: "   
     488                                  << " erc: " << mExpectedCost  
     489                                  << " avgrc: " << mAvgRenderCost 
     490                                  << " dev: " << mDeviation << endl; 
     491         
     492                        // adjust render cost 
     493                        ++ pass; 
     494 
     495                        mergedPerPass = 0; 
     496                        mExpectedCost = realExpectedCost; 
     497                        mAvgRenderCost = realAvgRenderCost; 
     498                        mNumViewCells = realNumViewCells; 
     499                         
     500                        const int numActiveViewCells = UpdateMergedViewCells(viewCells); 
     501 
     502                    ResetMergeQueue(); 
     503 
     504                         
     505                        Debug << "Values after reset: "   
     506                                  << " erc: " << mExpectedCost  
     507                                  << " avg: " << mAvgRenderCost  
     508                                  << " dev: " << mDeviation << endl; 
     509 
     510                        if (mExportMergedViewCells) 
     511                        { 
     512                                ExportMergedViewCells(viewCells, objects, numActiveViewCells); 
     513                        } 
     514                } 
     515 
     516#ifdef _DEBUG 
     517                Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() <<  
     518                          << " rel mergecost: " << mMergeQueue.top().GetRenderCost() / mExpectedCost <<  
     519                          << " max ratio: " << mMergeMaxCostRatio << endl 
     520                          << " expected value: " << realExpectedCost << endl; 
     521#endif 
     522 
     523         
     524                MergeCandidate mc = mMergeQueue.top(); 
     525                mMergeQueue.pop(); 
     526         
     527                // both view cells equal! 
     528                if (mc.mLeftViewCell == mc.mRightViewCell) 
     529                        continue; 
     530 
     531                if (mc.IsValid()) 
     532                { 
     533                        ViewCell::NewMail(); 
     534                                                 
     535                        -- realNumViewCells; 
     536                        ++ mergeStats.merged; 
     537                        ++ mergedPerPass; 
     538 
     539 
     540                        //-- update statistical values 
     541 
     542                        // total render cost and deviation has changed 
     543                        // real expected cost will be larger than expected cost used for the 
     544                        // cost heuristics, but cannot recompute costs on each increase of the  
     545                        // expected cost 
     546 
     547                        totalCost += mc.GetRenderCost(); 
     548                        mDeviation += mc.GetDeviationIncr(); 
     549                                                 
     550                        realExpectedCost = totalCost / (float)realNumViewCells; 
     551                         
     552                        const float currentMergeCost = mc.GetMergeCost(); 
     553 
     554                        // merge the view cells of leaf1 and leaf2 
     555                        int pvsDiff; 
     556                        ViewCellInterior *mergedVc =  
     557                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff); 
     558 
     559                        totalPvs += pvsDiff; 
     560                        // set timestamp 
     561                        mergedVc->SetTimeStamp(mergeStats.merged); 
     562 
     563                        realAvgRenderCost = (float)totalPvs / (float)realNumViewCells; 
     564#if VC_HISTORY 
     565                        if (mc.mLeftViewCell->IsSibling(mc.mRightViewCell)) 
     566                                ++ mergeStats.siblings; 
     567#endif 
     568                        if (((mergeStats.merged % statsOut) == 0) ||  
     569                                (realNumViewCells == mMergeMinViewCells)) 
     570                        { 
     571                                cout << "merged " << mergeStats.merged << " view cells" << endl; 
     572 
     573                                mStats  
     574                                        << "#Pass\n" << pass << endl 
     575                                        << "#Merged\n" << mergeStats.merged << endl  
     576                                        << "#Viewcells\n" << realNumViewCells << endl  
     577                                        << "#CurrentCost\n" << currentMergeCost << endl 
     578                                        << "#RelativeCost\n" << currentMergeCost / mOverallCost << endl 
     579                                        << "#CurrentPvs\n" << mc.GetLeftViewCell()->GetPvs().GetSize() << endl 
     580                                        << "#MergedSiblings\n" << mergeStats.siblings << endl 
     581                                        << "#AvgTreeDist\n" << mergeStats.AvgTreeDist() << endl 
     582                                        << "#UsedExpectedCost\n" << mExpectedCost << endl 
     583                                        << "#RealExpectedCost\n" << realExpectedCost << endl 
     584                                        << "#RealAvgRenderCost\n" << realAvgRenderCost << endl 
     585                                        << "#AvgRenderCost\n" << mAvgRenderCost << endl 
     586                                        << "#expectedCostRatio\n" << mExpectedCost / realExpectedCost << endl 
     587                                        << "#Deviation\n" << mDeviation / (float)realNumViewCells << endl 
     588                                        << "#TotalDeviation\n" << mDeviation<< endl; 
     589                        } 
     590                } 
     591                else 
     592                {  
     593                        // merge candidate not valid, because one of the leaves was already 
     594                        // merged with another one => validate and reinsert into queue 
     595                        SetMergeCandidateValid(mc); 
     596                        mMergeQueue.push(mc); 
     597                } 
     598        } 
     599 
     600        // adjust stats and reset queue one final time 
     601        mExpectedCost = realExpectedCost; 
     602        mAvgRenderCost = realAvgRenderCost; 
     603        mNumViewCells = realNumViewCells; 
     604 
     605        UpdateMergedViewCells(viewCells); 
     606        ResetMergeQueue(); 
     607 
     608 
     609        // create a root node if the merge was not done till root level, 
     610        // else take the single node as new root 
     611        if ((int)viewCells.size() > 1) 
     612        { 
     613                ViewCellInterior *root = new ViewCellInterior(); 
     614 
     615                ViewCellContainer::const_iterator it, it_end = viewCells.end(); 
     616                for (it = viewCells.begin(); it != it_end; ++ it) 
     617                        root->SetupChildLink(*it); 
     618 
     619                mRoot = root; 
     620        } 
     621        else if ((int)viewCells.size() == 1) 
     622        { 
     623                mRoot = viewCells[0]; 
     624        } 
     625 
     626        mergeStats.expectedRenderCost = realExpectedCost; 
     627        mergeStats.deviation = mDeviation; 
     628 
     629        // we want to optimize this heuristics 
     630        mergeStats.heuristics =  
     631                mDeviation * (1.0f - mRenderCostWeight) +  
     632                mExpectedCost * mRenderCostWeight; 
     633 
     634        mergeStats.mergeTime = TimeDiff(startTime, GetTime()); 
     635        mergeStats.Stop(); 
     636 
     637        Debug << mergeStats << endl << endl; 
     638 
     639 
     640        //TODO: should return sample contributions? 
     641        return mergeStats.merged; 
     642} 
     643 
     644 
     645void ViewCellsTree::ResetMergeQueue() 
     646{ 
     647        cout << "reset merge queue ... "; 
     648         
     649        vector<MergeCandidate> buf; 
     650        buf.reserve(mMergeQueue.size()); 
     651                         
     652         
     653        // store merge candidates in intermediate buffer 
     654        while (!mMergeQueue.empty()) 
     655        { 
     656                MergeCandidate mc = mMergeQueue.top(); 
     657                mMergeQueue.pop(); 
     658                 
     659                // recalculate cost 
     660                SetMergeCandidateValid(mc); 
     661                buf.push_back(mc);                               
     662        } 
     663 
     664        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end(); 
     665 
     666        // reinsert back into queue 
     667        for (bit = buf.begin(); bit != bit_end; ++ bit) 
     668        {       
     669                mMergeQueue.push(*bit);  
     670        } 
     671 
     672        cout << "finished" << endl; 
     673} 
     674 
     675 
     676int ViewCellsTree::UpdateMergedViewCells(ViewCellContainer &viewCells) 
     677{ 
     678        int numActiveViewCells = 0; 
     679 
     680        // find all already merged view cells and remove them from view cells 
     681        int i = 0; 
     682 
     683        while (1) 
     684        { 
     685                while (!viewCells.empty() && (!viewCells.back()->GetParent())) 
     686                { 
     687                        viewCells.pop_back(); 
     688                } 
     689 
     690                // all merged view cells have been found 
     691                if (i >= viewCells.size())  
     692                        break; 
     693 
     694                // already merged view cell, put it to end of vector 
     695                if (!viewCells[i]->IsRoot()) 
     696                        swap(viewCells[i], viewCells.back()); 
     697                 
     698                ++ i; 
     699        } 
     700 
     701        // add new view cells to container only if they don't have been  
     702        // merged in the mean time 
     703        while (!mActiveViewCells.empty()) 
     704        { 
     705                if (!mActiveViewCells.back()->GetParent()) 
     706                { 
     707                        viewCells.push_back(mActiveViewCells.back()); 
     708                        ++ numActiveViewCells; 
     709                } 
     710 
     711                mActiveViewCells.pop_back(); 
     712        } 
     713 
     714        // update standard deviation 
     715        ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 
     716         
     717        mDeviation = 0; 
     718 
     719        for (vit = viewCells.begin(); vit != vit_end; ++ vit) 
     720        { 
     721                int lower = mViewCellsManager->GetMinPvsSize(); 
     722                int upper = mViewCellsManager->GetMaxPvsSize(); 
     723                float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper); 
     724                 
     725                mDeviation += fabs(mAvgRenderCost - penalty); 
     726        } 
     727 
     728        mDeviation /= (float)viewCells.size(); 
     729 
     730        // clear the view cells which were merged 
     731        mInactiveViewCells.clear(); 
     732        // remove the new view cells 
     733        mActiveViewCells.clear(); 
     734 
     735        return numActiveViewCells; 
     736} 
     737 
     738 
     739void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,  
     740                                                                                  const ObjectContainer &objects, 
     741                                                                                  const int numActiveViewCells) 
     742{ 
     743         
     744 
     745        char s[64]; 
     746 
     747        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size()); 
     748        Exporter *exporter = Exporter::GetExporter(s); 
     749 
     750        if (exporter) 
     751        { 
     752                cout << "exporting " << (int)viewCells.size() << " merged view cells ... "; 
     753                exporter->ExportGeometry(objects); 
     754                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl; 
     755                ViewCellContainer::const_iterator it, it_end = viewCells.end(); 
     756 
     757                int i = 0; 
     758                for (it = viewCells.begin(); it != it_end; ++ it) 
     759                { 
     760                        Material m; 
     761                        // assign special material to new view cells 
     762                        // new view cells are on the back of container 
     763                        if (i ++ >= (viewCells.size() - numActiveViewCells)) 
     764                        { 
     765                                //m = RandomMaterial(); 
     766                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f); 
     767                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f); 
     768                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f); 
     769                        } 
     770                        else 
     771                        { 
     772                                float col = RandomValue(0.1f, 0.4f); 
     773                                m.mDiffuseColor.r = col; 
     774                                m.mDiffuseColor.g = col; 
     775                                m.mDiffuseColor.b = col; 
     776                        } 
     777 
     778                        exporter->SetForcedMaterial(m); 
     779                        mViewCellsManager->ExportViewCellGeometry(exporter, *it); 
     780                } 
     781                delete exporter; 
     782                cout << "finished" << endl; 
     783        } 
     784} 
     785 
     786 
     787// TODO: should be done in view cells manager 
     788ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l, ViewCell *r, int &pvsDiff) //const 
     789{ 
     790        ViewCellInterior *vc = mViewCellsManager->MergeViewCells(*l, *r); 
     791 
     792        // if merge was unsuccessful 
     793        if (!vc) return NULL; 
     794 
     795        // set new size of view cell 
     796        if (mUseAreaForPvs) 
     797                vc->SetArea(l->GetArea() + l->GetArea()); 
     798        else 
     799                vc->SetVolume(r->GetVolume() + r->GetVolume()); 
     800         
     801        // important so other merge candidates sharing this view cell 
     802        // are notified that the merge cost must be updated!! 
     803        vc->Mail(); 
     804 
     805        const int pvs1 = l->GetPvs().GetSize(); 
     806        const int pvs2 = r->GetPvs().GetSize(); 
     807 
     808 
     809        //-- clean up old view cells 
     810        if (0 && !mExportMergedViewCells) 
     811        { 
     812                DEL_PTR(l); 
     813                DEL_PTR(r); 
     814        } 
     815        else  
     816        { 
     817                mInactiveViewCells.push_back(l); 
     818                mInactiveViewCells.push_back(r); 
     819                 
     820                mActiveViewCells.push_back(vc); 
     821        } 
     822 
     823        pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2; 
     824 
     825        return vc; 
     826} 
     827 
     828 
     829 
     830 
     831int ViewCellsTree::RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects) 
     832{ 
     833        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl; 
     834         
     835        // Use priority queue of remaining leaf pairs  
     836        // The candidates either share the same view cells or 
     837        // are border leaves which share a boundary. 
     838        // We test if they can be shuffled, i.e., 
     839        // either one leaf is made part of one view cell or the other 
     840        // leaf is made part of the other view cell. It is tested if the 
     841        // remaining view cells are "better" than the old ones. 
     842        // 
     843        // repeat the merging test numPasses times. For example, it could be 
     844        // that a shuffle only makes sense if another pair was shuffled before. 
     845        // Therefore we keep two queues and shift the merge candidates between 
     846        // those two queues until numPasses is reached 
     847         
     848        queue<MergeCandidate> queue1; 
     849        queue<MergeCandidate> queue2; 
     850 
     851        queue<MergeCandidate> *shuffleQueue = &queue1; 
     852        queue<MergeCandidate> *backQueue = &queue2; 
     853 
     854        while (!mMergeQueue.empty()) 
     855        { 
     856                MergeCandidate mc = mMergeQueue.top(); 
     857                shuffleQueue->push(mc); 
     858                mMergeQueue.pop(); 
     859        } 
     860 
     861        const int numPasses = 5; 
     862        int pass = 0; 
     863        int passShuffled = 0; 
     864        int shuffled = 0; 
     865        int shuffledViewCells = 0; 
     866 
     867        ViewCell::NewMail(); 
     868         
     869        do 
     870        { 
     871                passShuffled = 0; 
     872                while (!shuffleQueue->empty()) 
     873                { 
     874                        MergeCandidate mc = shuffleQueue->front(); 
     875                        shuffleQueue->pop(); 
     876 
     877                        // both view cells equal or already shuffled 
     878                        if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||  
     879                                (GetSize(mc.GetLeftViewCell()) == 1) ||  
     880                                (GetSize(mc.GetRightViewCell()) == 1)) 
     881                        {                        
     882                                continue; 
     883                        } 
     884 
     885                        // candidate for shuffling 
     886                        const bool wasShuffled =  
     887                                ShuffleLeaves(mc.GetLeftViewCell(), mc.GetRightViewCell()); 
     888                 
     889                        // shuffled or put into other queue for further refine 
     890                        if (wasShuffled) 
     891                        { 
     892                                ++ passShuffled; 
     893 
     894                                if (!mc.GetLeftViewCell()->Mailed()) 
     895                                { 
     896                                        mc.GetLeftViewCell()->Mail(); 
     897                                        ++ shuffledViewCells; 
     898                                } 
     899                                if (!mc.GetRightViewCell()->Mailed()) 
     900                                { 
     901                                        mc.GetRightViewCell()->Mail(); 
     902                                        ++ shuffledViewCells; 
     903                                } 
     904                        } 
     905                        else 
     906                        { 
     907                                backQueue->push(mc); 
     908                        } 
     909                } 
     910 
     911                // now the back queue is the current shuffle queue 
     912                swap(shuffleQueue, backQueue); 
     913                shuffled += passShuffled; 
     914                Debug << "shuffled in pass: " << passShuffled << endl; 
     915        } 
     916        while (((++ pass) < numPasses) && passShuffled); 
     917 
     918        while (!shuffleQueue->empty()) 
     919        { 
     920                shuffleQueue->pop(); 
     921        } 
     922 
     923        return shuffledViewCells; 
     924} 
     925 
     926 
     927 
     928 
     929inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2) 
     930{ 
     931        return pvs1.AddPvs(pvs2); 
     932} 
     933 
     934 
     935// recomputes pvs size minus pvs of leaf l 
     936#if 0 
     937inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2) 
     938{ 
     939        ObjectPvs pvs; 
     940        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end(); 
     941        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it) 
     942                if (*it != l) 
     943                        pvs.AddPvs(*(*it)->mPvs); 
     944        return pvs.GetSize(); 
     945} 
     946#endif 
     947 
     948 
     949// computes pvs1 minus pvs2 
     950inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2) 
     951{ 
     952        return pvs1.SubtractPvs(pvs2); 
     953} 
     954 
     955 
     956float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,  
     957                                                                         ViewCell *vc1,  
     958                                                                         ViewCell *vc2) const 
     959{ 
     960        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs); 
     961        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs()); 
     962        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs()); 
     963 
     964        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize(); 
     965        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize(); 
     966 
     967        const float pvsPenalty1 =  
     968                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit); 
     969 
     970        const float pvsPenalty2 = 
     971                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit); 
     972 
     973 
     974        // don't shuffle leaves with pvs > max 
     975        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize())) 
     976        { 
     977                return 1e20f; 
     978        } 
     979 
     980        float p1, p2; 
     981 
     982    if (mUseAreaForPvs) 
     983        { 
     984                p1 = vc1->GetArea() - leaf->GetArea(); 
     985                p2 = vc2->GetArea() + leaf->GetArea(); 
     986        } 
     987        else 
     988        { 
     989                p1 = vc1->GetVolume() - leaf->GetVolume(); 
     990                p2 = vc2->GetVolume() + leaf->GetVolume(); 
     991        } 
     992 
     993        const float renderCost1 = pvsPenalty1 * p1; 
     994        const float renderCost2 = pvsPenalty2 * p2; 
     995 
     996        float dev1, dev2; 
     997 
     998        if (1) 
     999        { 
     1000                dev1 = fabs(mAvgRenderCost - pvsPenalty1); 
     1001                dev2 = fabs(mAvgRenderCost - pvsPenalty2); 
     1002        } 
     1003        else 
     1004        { 
     1005                dev1 = fabs(mExpectedCost - renderCost1); 
     1006                dev2 = fabs(mExpectedCost - renderCost2); 
     1007        } 
     1008         
     1009        return mRenderCostWeight * (renderCost1 + renderCost2) + 
     1010                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumViewCells; 
     1011} 
     1012 
     1013 
     1014void ViewCellsTree::ShuffleLeaf(ViewCell *leaf, 
     1015                                                                ViewCell *vc1,  
     1016                                                                ViewCell *vc2) const 
     1017{ 
     1018        // compute new pvs and area 
     1019        vc1->GetPvs().SubtractPvs(leaf->GetPvs()); 
     1020        vc2->GetPvs().AddPvs(leaf->GetPvs()); 
     1021         
     1022        if (mUseAreaForPvs) 
     1023        { 
     1024                vc1->SetArea(vc1->GetArea() - leaf->GetArea()); 
     1025                vc2->SetArea(vc2->GetArea() + leaf->GetArea()); 
     1026        } 
     1027        else 
     1028        { 
     1029                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume()); 
     1030                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume()); 
     1031        } 
     1032 
     1033        // TODO 
     1034#if VC_HISTORY 
     1035        /// add to second view cell 
     1036        vc2->mLeaves.push_back(leaf); 
     1037 
     1038        // erase leaf from old view cell 
     1039        vector<BspLeaf *>::iterator it = vc1->mLeaves.begin(); 
     1040 
     1041        for (; *it != leaf; ++ it); 
     1042        vc1->mLeaves.erase(it); 
     1043 
     1044        /*vc1->GetPvs().mEntries.clear(); 
     1045        for (; it != vc1->mLeaves.end(); ++ it) 
     1046        { 
     1047                if (*it == leaf) 
     1048                        vc1->mLeaves.erase(it); 
     1049                else 
     1050                        vc1->GetPvs().AddPvs(*(*it)->mPvs); 
     1051        }*/ 
     1052 
     1053        leaf->SetViewCell(vc2); // finally change view cell 
     1054#endif 
     1055} 
     1056 
     1057 
     1058bool ViewCellsTree::ShuffleLeaves(ViewCell *l, ViewCell *r) const 
     1059{ 
     1060        float cost1, cost2; 
     1061 
     1062        //-- first test if shuffling would decrease cost 
     1063        cost1 = GetCostHeuristics(l); 
     1064        cost2 = GetCostHeuristics(r); 
     1065 
     1066        const float oldCost = cost1 + cost2; 
     1067         
     1068        float shuffledCost1 = Limits::Infinity; 
     1069        float shuffledCost2 = Limits::Infinity; 
     1070 
     1071        // the view cell should not be empty after the shuffle 
     1072#if VC_HISTORY 
     1073        shuffledCost1 = EvalShuffleCost(l, vc1, vc2); 
     1074        /shuffledCost2 = EvalShuffleCost(r, vc2, vc1); 
     1075 
     1076        // if cost of shuffle is less than old cost => shuffle 
     1077        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2)) 
     1078                return false; 
     1079         
     1080         
     1081        if (shuffledCost1 < shuffledCost2) 
     1082        { 
     1083                ShuffleLeaf(leaf1, vc1, vc2); 
     1084                leaf1->Mail(); 
     1085        } 
     1086        else 
     1087        { 
     1088                ShuffleLeaf(leaf2, vc2, vc1); 
     1089                leaf2->Mail(); 
     1090        } 
     1091#endif 
     1092        return true; 
     1093} 
     1094 
     1095 
     1096float ViewCellsTree::GetVariance(ViewCell *vc) const 
     1097{ 
     1098        const int upper = mViewCellsManager->GetMaxPvsSize(); 
     1099        const int lower = mViewCellsManager->GetMinPvsSize(); 
     1100 
     1101        if (1) 
     1102        { 
     1103                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper); 
     1104                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumViewCells; 
     1105        } 
     1106 
     1107    const float leafCost = GetRenderCost(vc); 
     1108        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost); 
     1109} 
     1110 
     1111 
     1112float ViewCellsTree::GetDeviation(ViewCell *vc) const 
     1113{ 
     1114        const int upper = mViewCellsManager->GetMaxPvsSize(); 
     1115        const int lower = mViewCellsManager->GetMinPvsSize(); 
     1116 
     1117        if (1) 
     1118        { 
     1119                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper); 
     1120                return fabs(mAvgRenderCost - penalty) / (float)mNumViewCells; 
     1121        } 
     1122 
     1123    const float renderCost = GetRenderCost(vc); 
     1124        return fabs(mExpectedCost - renderCost); 
     1125} 
     1126 
     1127 
     1128 
     1129float ViewCellsTree::GetRenderCost(ViewCell *vc) const 
     1130{ 
     1131        if (mUseAreaForPvs) 
     1132                return vc->GetPvs().GetSize() * vc->GetArea(); 
     1133 
     1134        return vc->GetPvs().GetSize() * vc->GetVolume(); 
     1135} 
     1136 
     1137 
     1138float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const 
     1139{ 
     1140        return GetRenderCost(vc) * mRenderCostWeight +  
     1141                   GetDeviation(vc) * (1.0f - mRenderCostWeight); 
     1142} 
     1143 
     1144 
     1145void ViewCellsTree::SetMergeCandidateValid(MergeCandidate &mc) const 
     1146{ 
     1147        while (mc.mLeftViewCell->mParent) 
     1148        { 
     1149                mc.mLeftViewCell = mc.mLeftViewCell->mParent; 
     1150        } 
     1151 
     1152        while (mc.mRightViewCell->mParent) 
     1153        { 
     1154                mc.mRightViewCell = mc.mRightViewCell->mParent; 
     1155        } 
     1156 
     1157        EvalMergeCost(mc); 
     1158} 
     1159 
     1160 
     1161void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const 
     1162{ 
     1163        //-- compute pvs difference 
     1164        const int newPvs =  
     1165                ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(),  
     1166                                                         mc.mRightViewCell->GetPvs()); 
     1167                         
     1168        const float newPenalty =  
     1169                EvalPvsPenalty(newPvs, 
     1170                                           mViewCellsManager->GetMinPvsSize(), 
     1171                                           mViewCellsManager->GetMaxPvsSize()); 
     1172 
     1173        ViewCell *vc1 = mc.mLeftViewCell; 
     1174        ViewCell *vc2 = mc.mRightViewCell; 
     1175 
     1176        //-- compute ratio of old cost 
     1177        //   (i.e., added size of left and right view cell times pvs size) 
     1178        //   to new rendering cost (i.e, size of merged view cell times pvs size) 
     1179        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2); 
     1180 
     1181    const float newCost = mUseAreaForPvs ?  
     1182                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) : 
     1183                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume()); 
     1184 
     1185 
     1186        // strong penalty if pvs size too large 
     1187        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize())) 
     1188        { 
     1189                mc.mRenderCost = 1e20f; 
     1190        } 
     1191        else 
     1192        { 
     1193                mc.mRenderCost = (newCost - oldCost) /  
     1194                        mViewCellsManager->GetViewSpaceBox().GetVolume(); 
     1195        }        
     1196         
     1197 
     1198        //-- merge cost also takes deviation into account 
     1199        float newDev, oldDev; 
     1200 
     1201        if (1) 
     1202                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumViewCells; 
     1203        else 
     1204                newDev = fabs(mExpectedCost - newCost) / (float)mNumViewCells; 
     1205         
     1206        oldDev = GetDeviation(vc1) + GetDeviation(vc2); 
     1207 
     1208        // compute deviation increase 
     1209        mc.mDeviationIncr = newDev - oldDev; 
     1210         
     1211        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl; 
     1212        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl; 
     1213} 
     1214 
     1215 
     1216void ViewCellsTree::CompressViewCellsPvs() 
     1217{ 
     1218        stack<ViewCell *> tstack; 
     1219 
     1220 
     1221} 
     1222 
     1223 
     1224void  ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells, const int numViewCells) 
     1225{ 
     1226        TraversalQueue tqueue; 
     1227 
     1228        while (!tqueue.empty()) 
     1229        { 
     1230                ViewCell *vc = tqueue.top(); 
     1231 
     1232                tqueue.pop(); 
     1233        } 
     1234} 
     1235 
     1236 
     1237/**************************************************************************/ 
     1238/*                     MergeCandidate implementation                      */ 
     1239/**************************************************************************/ 
     1240 
     1241 
     1242MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r): 
     1243mRenderCost(0), 
     1244mDeviationIncr(0), 
     1245mLeftViewCell(l), 
     1246mRightViewCell(r) 
     1247{ 
     1248        //EvalMergeCost(); 
     1249} 
     1250 
     1251 
     1252void MergeCandidate::SetRightViewCell(ViewCell *v) 
     1253{ 
     1254        mRightViewCell = v; 
     1255} 
     1256 
     1257 
     1258void MergeCandidate::SetLeftViewCell(ViewCell *v) 
     1259{ 
     1260        mLeftViewCell = v; 
     1261} 
     1262 
     1263 
     1264ViewCell *MergeCandidate::GetRightViewCell() const 
     1265{ 
     1266        return mRightViewCell; 
     1267} 
     1268 
     1269 
     1270ViewCell *MergeCandidate::GetLeftViewCell() const 
     1271{ 
     1272        return mLeftViewCell; 
     1273} 
     1274 
     1275 
     1276ViewCell *MergeCandidate::GetInitialRightViewCell() const 
     1277{ 
     1278        return mInitialRightViewCell; 
     1279} 
     1280 
     1281 
     1282ViewCell *MergeCandidate::GetInitialLeftViewCell() const 
     1283{ 
     1284        return mInitialLeftViewCell; 
     1285} 
     1286 
     1287 
     1288bool MergeCandidate::IsValid() const 
     1289{ 
     1290        return !(mLeftViewCell->mParent && mRightViewCell->mParent); 
     1291} 
     1292 
     1293 
     1294float MergeCandidate::GetRenderCost() const 
     1295{ 
     1296        return mRenderCost; 
     1297} 
     1298 
     1299 
     1300float MergeCandidate::GetDeviationIncr() const 
     1301{ 
     1302        return mDeviationIncr; 
     1303} 
     1304 
     1305 
     1306float MergeCandidate::GetMergeCost() const 
     1307{ 
     1308        return mRenderCost * sRenderCostWeight +  
     1309                   mDeviationIncr * (1.0f - sRenderCostWeight); 
     1310} 
     1311 
     1312 
     1313/************************************************************************/ 
     1314/*                    MergeStatistics implementation                    */ 
     1315/************************************************************************/ 
     1316 
     1317 
     1318void MergeStatistics::Print(ostream &app) const 
     1319{ 
     1320        app << "===== Merge statistics ===============\n"; 
     1321 
     1322        app << setprecision(4); 
     1323 
     1324        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n"; 
     1325 
     1326        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n"; 
     1327 
     1328        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n"; 
     1329 
     1330        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n"; 
     1331 
     1332        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n"; 
     1333 
     1334        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n"; 
     1335 
     1336        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n"; 
     1337 
     1338        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n"; 
     1339 
     1340        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n"; 
     1341 
     1342        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n"; 
     1343 
     1344        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n"; 
     1345 
     1346        app << "#DEVIATION ( deviation )\n" << deviation << "\n"; 
     1347 
     1348        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n"; 
     1349         
     1350 
     1351        app << "===== END OF BspTree statistics ==========\n"; 
     1352} 
Note: See TracChangeset for help on using the changeset viewer.