Changeset 542 for trunk/VUT


Ignore:
Timestamp:
01/16/06 03:23:29 (19 years ago)
Author:
mattausch
Message:
 
Location:
trunk/VUT/GtpVisibilityPreprocessor
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env

    r540 r542  
    1313#;../data/vienna/vienna-plane.x3d 
    1414#       filename ../data/vienna/viewcells-25-sel.x3d 
    15 #       filename ../data/atlanta/atlanta2.x3d 
     15        filename ../data/atlanta/atlanta2.x3d 
    1616#       filename ../data/soda/soda.dat 
    17         filename ../data/soda/soda5.dat 
     17#       filename ../data/soda/soda5.dat 
    1818} 
    1919 
     
    2121        # stored sample rays 
    2222        samplesFilename rays.out 
    23         useGlRenderer true 
     23        useGlRenderer false 
    2424#       type sampling 
    2525        type vss 
     
    2929VssPreprocessor { 
    3030        samplesPerPass  100000 
    31         initialSamples 200000 
    32         vssSamples 200000 
     31        initialSamples 300000 
     32        vssSamples 1000000 
    3333        vssSamplesPerPass 100000 
    3434        useImportanceSampling true 
     
    5252        maxDepth        40 
    5353        minPvs          30 
    54         minRays         500 
     54        minRays         800 
    5555        minSize         0.001 
    5656        maxCostRatio    1.5 
    5757        maxRayContribution 0.5 
    5858                 
    59         maxTotalMemory  200 
    60         maxStaticMemory 100 
     59        maxTotalMemory  50 
     60        maxStaticMemory 20 
    6161         
    6262        splitType regular 
     
    6666         
    6767        interleaveDirSplits     true 
    68     dirSplitDepth 10 
     68    dirSplitDepth 0 
    6969         
    7070        numberOfEndPointDomains 10000 
     
    174174        #type kdTree 
    175175        #type vspKdTree 
    176         #type bspTree 
     176        type bspTree 
    177177        type vspBspTree 
    178178         
     
    182182        maxViewCells 100000 
    183183        #percentage of total visible objects where pvs is considered invalid 
    184         maxPvsRatio 0.5 
    185                  
    186         delayedConstruction false 
     184        maxPvsRatio 0.3 
     185                 
     186        delayedConstruction true 
    187187                 
    188188                 
    189189        PostProcess { 
    190190                # how much samples are used for post processing 
    191                 samples 20000 
     191                samples 200000 
    192192        } 
    193193 
     
    224224 
    225225        Construction { 
    226                 samples 300000 
     226                samples 500000 
    227227        } 
    228228         
     
    230230                maxDepth                40 
    231231                minPvs                  50 
    232                 minRays                 700 
     232                minRays                 800 
    233233                minSize                 0.001 
    234234                maxCostRatio            0.9 
    235235                missTolerance           4 
    236                 maxRayContribution      0.05 
     236                maxRayContribution      0.5 
    237237        } 
    238238         
    239239        maxTotalMemory  100 
    240         maxStaticMemory 50 
     240        maxStaticMemory 40 
    241241 
    242242        splitType       regular 
    243243        #splitType      heuristics 
    244         splitUseOnlyDrivingAxis true 
     244        splitUseOnlyDrivingAxis false 
    245245        ct_div_ci       0.0 
    246246         
     
    248248        PostProcess { 
    249249                maxCostRatio 0.005 
    250                 minViewCells 200 
     250                minViewCells 1000 
    251251                maxPvsSize   50000 
    252252        } 
     
    259259VspBspTree { 
    260260        Construction { 
    261                 samples 100000 
     261                samples 300000 
    262262                epsilon 0.005 
    263263                randomize false 
     
    280280        maxTests 10000 
    281281         
     282        maxTotalMemory  50 
     283        maxStaticMemory 50 
     284         
    282285        # factors for evaluating split plane costs 
    283286        Factor { 
     
    289292        Termination { 
    290293                # parameters used for autopartition 
    291                 minRays                 1000 
     294                minRays                 500 
    292295                minPolygons             -1 
    293296                maxDepth                30 
    294297                minPvs                  10 
    295                 minArea                 0.00008 
    296                 #minArea                0.000 
    297                 maxRayContribution      0.3 
    298                 maxCostRatio            0.93 
     298                #minArea                0.0001 
     299                minArea                 -1 
     300                maxRayContribution      0.9 
     301                maxCostRatio            99999.93 
    299302                missTolerance           3 
    300303                #maxAccRayLength        100 
    301304                 
    302                 maxViewCells            200 
     305                maxViewCells            2001 
    303306                 
    304307                # used for pvs criterium 
     
    306309                 
    307310                AxisAligned { 
    308                         minRays                 5000 
     311                        minRays                 4000 
    309312                        maxRayContribution      0.5 
    310313                } 
     
    315318        Visualization { 
    316319                # x3d visualization of the split planes 
    317                 exportSplits false 
     320                exportSplits true 
    318321        } 
    319322         
    320323        PostProcess { 
    321                 maxCostRatio 0.1 
     324                maxCostRatio 0.001 
    322325                minViewCells 1000 
    323                 maxPvsSize   10000 
    324326                useRaysForMerge true 
    325327        } 
  • trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp

    r540 r542  
    20302030        mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) ); 
    20312031        mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) ); 
    2032  
    2033 } 
     2032} 
     2033 
     2034 
     2035void AxisAlignedBox3::ExtractPolys(PolygonContainer &polys) const 
     2036{ 
     2037        Polygon3 *face1 = new Polygon3(); 
     2038        polys.push_back(face1);    
     2039 
     2040    face1->mVertices.push_back(Vector3(mMin.x,mMin.y,mMax.z)); 
     2041        face1->mVertices.push_back(Vector3(mMin.x,mMax.y,mMax.z)); 
     2042        face1->mVertices.push_back(Vector3(mMin.x,mMax.y,mMin.z)); 
     2043        face1->mVertices.push_back(Vector3(mMin.x,mMin.y,mMin.z)); 
     2044 
     2045        Polygon3 *face2 = new Polygon3();   
     2046        polys.push_back(face2); 
     2047 
     2048    face2->mVertices.push_back(Vector3(mMax.x,mMin.y,mMin.z)); 
     2049    face2->mVertices.push_back(Vector3(mMax.x,mMax.y,mMin.z)); 
     2050    face2->mVertices.push_back(Vector3(mMax.x,mMax.y,mMax.z)); 
     2051    face2->mVertices.push_back(Vector3(mMax.x,mMin.y,mMax.z)); 
     2052   
     2053        Polygon3 *face3 = new Polygon3();   
     2054        polys.push_back(face3); 
     2055 
     2056    face3->mVertices.push_back(Vector3(mMax.x,mMin.y,mMin.z)); 
     2057        face3->mVertices.push_back(Vector3(mMax.x,mMin.y,mMax.z)); 
     2058        face3->mVertices.push_back(Vector3(mMin.x,mMin.y,mMax.z)); 
     2059        face3->mVertices.push_back(Vector3(mMin.x,mMin.y,mMin.z)); 
     2060 
     2061        Polygon3 *face4 = new Polygon3();   
     2062        polys.push_back(face4); 
     2063 
     2064        face4->mVertices.push_back(Vector3(mMin.x,mMax.y,mMin.z)); 
     2065        face4->mVertices.push_back(Vector3(mMin.x,mMax.y,mMax.z)); 
     2066        face4->mVertices.push_back(Vector3(mMax.x,mMax.y,mMax.z)); 
     2067        face4->mVertices.push_back(Vector3(mMax.x,mMax.y,mMin.z)); 
     2068     
     2069        Polygon3 *face5 = new Polygon3();   
     2070        polys.push_back(face5); 
     2071 
     2072        face5->mVertices.push_back(Vector3(mMin.x,mMax.y,mMin.z)); 
     2073    face5->mVertices.push_back(Vector3(mMax.x,mMax.y,mMin.z)); 
     2074    face5->mVertices.push_back(Vector3(mMax.x,mMin.y,mMin.z)); 
     2075        face5->mVertices.push_back(Vector3(mMin.x,mMin.y,mMin.z)); 
     2076 
     2077        Polygon3 *face6 = new Polygon3();   
     2078        polys.push_back(face6);   
     2079   
     2080    face6->mVertices.push_back(Vector3(mMin.x,mMin.y,mMax.z)); 
     2081    face6->mVertices.push_back(Vector3(mMax.x,mMin.y,mMax.z)); 
     2082    face6->mVertices.push_back(Vector3(mMax.x,mMax.y,mMax.z)); 
     2083    face6->mVertices.push_back(Vector3(mMin.x,mMax.y,mMax.z)); 
     2084} 
  • trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h

    r538 r542  
    66#include "Vector3.h" 
    77#include "Plane3.h" 
     8#include "Containers.h" 
    89 
    910class Ray; 
    1011class Polygon3; 
    1112class Mesh; 
     13 
    1214// -------------------------------------------------------- 
    1315// CAABox class. 
     
    356358  void AddBoxToMesh(Mesh *mesh) const; 
    357359 
     360  void ExtractPolys(PolygonContainer &polys) const; 
     361 
    358362#define __EXTENT_HACK 
    359363  // get the extent of face 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Beam.cpp

    r540 r542  
    7171  } 
    7272  return result; 
     73} 
     74 
     75 
     76Beam::~Beam() 
     77{ 
     78        DEL_PTR(mMesh); 
    7379} 
    7480 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Beam.h

    r540 r542  
    8989                                                                 const AxisAlignedBox3 &sceneBBox) const; 
    9090 
    91   /* Computes parameters for glOrtho. 
     91  /** Computes parameters for glOrtho. 
    9292  */ 
    9393  void ComputeOrthoFrustum(float &left, float &right, 
     
    107107  } 
    108108 
     109  ~Beam(); 
     110 
     111  /** Creates beam mesh bounded at zfar. 
     112  */ 
    109113  void CreateMesh(const float zfar); 
    110114}; 
  • trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp

    r539 r542  
    18201820                "1000"); 
    18211821 
    1822         RegisterOption("VspBspTree.PostProcess.maxPvsSize",  
    1823                 optInt,  
    1824                 "vsp_bsp_term_post_process_max_pvs_size=",  
    1825                 "100"); 
    1826  
    18271822        RegisterOption("VspBspTree.PostProcess.useRaysForMerge",  
    18281823                optBool,  
  • trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp

    r541 r542  
    977977} 
    978978 
     979 
    979980void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays) 
    980981{ 
     
    10171018                        ObjectContainer::iterator oit = 
    10181019                                lower_bound(objects.begin(), objects.end(), &dummy, ilt); 
    1019                         obj = *oit; 
    1020                         if (!obj->Mailed()) 
     1020                         
     1021                         
     1022                        if (//(oit != oit.end()) &&  
     1023                                ((*oit)->GetId() == id) &&  
     1024                                !obj->Mailed()) 
    10211025                        { 
     1026                                obj = *oit; 
    10221027                                obj->Mail(); 
    10231028                                ++ pvsSize; 
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp

    r540 r542  
    2727mViewCellsFinished(false) 
    2828{ 
    29         mSceneBox.Initialize(); 
     29        mViewSpaceBox.Initialize(); 
    3030        ParseEnvironment(); 
    3131} 
     
    3939mViewCellsFinished(false) 
    4040{ 
    41         mSceneBox.Initialize(); 
     41        mViewSpaceBox.Initialize(); 
    4242        ParseEnvironment(); 
    4343} 
     
    7777int ViewCellsManager::Construct(VssRayContainer &rays) 
    7878{ 
    79         VssPreprocessor preprocessor; 
    80  
    81  
    82  
    83         return 0; 
     79/*      VssPreprocessor preprocessor; 
     80 
     81        VssRayContainer vssRays; 
     82        preprocessor->GenerateVssRays(mConstructionSamples, vssRays); 
     83        Construct(preprocessor->mObjects, vssRays); 
     84         
     85        // add rays to output rays 
     86        while (!vssRays.empty) 
     87        { 
     88                rays.push_back(vssRays.back()); 
     89                vssRays.pop_back(); 
     90        } 
     91 
     92        const int importanceRays = 1000000; 
     93        preprocessor->GenerateVssRays(max(importanceRays, mPostProcessSamples); 
     94 
     95        PostProcess(preprocesor->mObjects, importanceRays); 
     96        Visualize(preprocessor->mObjects, importanceRays); 
     97 
     98        // add rays to output rays 
     99        while (!importanceRays.empty) 
     100        { 
     101                rays.push_back(importanceRays.back()); 
     102                importanceRays.pop_back(); 
     103        } 
     104*/ 
     105        return (int)rays.size(); 
    84106} 
    85107 
     
    99121bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const 
    100122{ 
    101         viewPoint = mSceneBox.GetRandomPoint(); 
     123        viewPoint = mViewSpaceBox.GetRandomPoint(); 
    102124 
    103125        return true; 
     
    107129bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const 
    108130{ 
    109         return mSceneBox.IsInside(viewPoint); 
     131        return mViewSpaceBox.IsInside(viewPoint); 
    110132} 
    111133 
     
    333355void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box) 
    334356{ 
    335         mSceneBox = box; 
     357        mViewSpaceBox = box; 
    336358} 
    337359 
     
    339361AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const 
    340362{ 
    341         return mSceneBox; 
     363        return mViewSpaceBox; 
    342364} 
    343365 
     
    358380void ViewCellsManager::ComputeSampleContributions(VssRay &ray) 
    359381{ 
    360   ViewCellContainer viewcells; 
    361  
    362   ray.mPvsContribution = 0; 
    363   ray.mRelativePvsContribution = 0.0f; 
    364  
    365   // matt TODO: remove this!! 
    366   Ray hray(ray); 
    367   float tmin = 0, tmax = 1.0; 
    368  
    369   //hray.Init(ray.GetOrigin(), ray.GetDir(), Ray::LINE_SEGMENT); 
    370   if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax)) 
     382        ViewCellContainer viewcells; 
     383 
     384        ray.mPvsContribution = 0; 
     385        ray.mRelativePvsContribution = 0.0f; 
     386 
     387        // matt TODO: remove this!! 
     388        Ray hray(ray); 
     389        float tmin = 0, tmax = 1.0; 
     390 
     391        //hray.Init(ray.GetOrigin(), ray.GetDir(), Ray::LINE_SEGMENT); 
     392        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax)) 
    371393        return; 
    372394 
    373   Vector3 origin = hray.Extrap(tmin); 
    374   Vector3 termination = hray.Extrap(tmax); 
    375  
    376   CastLineSegment(origin, 
    377                                   termination, 
    378                                   viewcells); 
    379   //Debug << "constribution: " << (int)viewcells.size() << endl; 
    380   // copy viewcells memory efficiently 
    381   const bool storeViewcells = false; 
    382   if (storeViewcells) { 
    383         ray.mViewCells.reserve(viewcells.size()); 
    384         ray.mViewCells = viewcells; 
    385   } 
    386  
    387   ViewCellContainer::const_iterator it = viewcells.begin(); 
    388  
    389   bool addInPlace = false; 
    390  
    391   if (addInPlace) { 
    392         for (; it != viewcells.end(); ++it) { 
    393           ViewCell *viewcell = *it; 
    394  
    395           // if ray not outside of view space 
    396           float contribution; 
    397           bool added = 
    398                 viewcell->GetPvs().AddSample(ray.mTerminationObject, 
    399                                                                          contribution 
    400                                                                          ); 
    401           if (added) 
    402                 ray.mPvsContribution++; 
    403  
    404           ray.mRelativePvsContribution += contribution; 
    405         } 
    406   } else { 
    407     for (; it != viewcells.end(); ++it) { 
    408           ViewCell *viewcell = *it; 
    409           // if ray not outside of view space 
    410           float contribution; 
    411           if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject, 
    412                                                                                                    contribution 
    413                                                                                                    )) 
    414                 ray.mPvsContribution++; 
    415  
    416           ray.mRelativePvsContribution += contribution; 
    417         } 
    418  
    419         for (it = viewcells.begin(); it != viewcells.end(); ++it) { 
    420           ViewCell *viewcell = *it; 
    421           // if ray not outside of view space 
    422           viewcell->GetPvs().AddSample(ray.mTerminationObject); 
    423         } 
    424   } 
     395        Vector3 origin = hray.Extrap(tmin); 
     396        Vector3 termination = hray.Extrap(tmax); 
     397 
     398        CastLineSegment(origin, 
     399                                        termination, 
     400                                        viewcells); 
     401        //Debug << "constribution: " << (int)viewcells.size() << endl; 
     402        // copy viewcells memory efficiently 
     403        const bool storeViewcells = false; 
     404        if (storeViewcells) 
     405        { 
     406                ray.mViewCells.reserve(viewcells.size()); 
     407                ray.mViewCells = viewcells; 
     408        } 
     409 
     410        ViewCellContainer::const_iterator it = viewcells.begin(); 
     411 
     412        bool addInPlace = false; 
     413 
     414        if (addInPlace)  
     415        { 
     416                for (; it != viewcells.end(); ++it) { 
     417                        ViewCell *viewcell = *it; 
     418 
     419                        // if ray not outside of view space 
     420                        float contribution; 
     421                        bool added = 
     422                        viewcell->GetPvs().AddSample(ray.mTerminationObject, 
     423                                                                                        contribution 
     424                                                                                        ); 
     425                        if (added) 
     426                        ray.mPvsContribution++; 
     427 
     428                        ray.mRelativePvsContribution += contribution; 
     429                } 
     430        }  
     431        else  
     432        { 
     433                for (; it != viewcells.end(); ++it) { 
     434                        ViewCell *viewcell = *it; 
     435                        // if ray not outside of view space 
     436                        float contribution; 
     437                        if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject, 
     438                                                                                                                contribution 
     439                                                                                                                )) 
     440                        ray.mPvsContribution++; 
     441                        ray.mRelativePvsContribution += contribution; 
     442                } 
     443 
     444                for (it = viewcells.begin(); it != viewcells.end(); ++it) { 
     445                        ViewCell *viewcell = *it; 
     446                        // if ray not outside of view space 
     447                        viewcell->GetPvs().AddSample(ray.mTerminationObject); 
     448                } 
     449        } 
    425450} 
    426451 
     
    14561481                  << (int)constructionRays.size() << " samples" << endl; 
    14571482 
    1458         mVspKdTree->Construct(constructionRays, &mSceneBox); 
     1483        mVspKdTree->Construct(constructionRays, &mViewSpaceBox); 
    14591484        Debug << mVspKdTree->GetStatistics() << endl; 
    14601485 
     
    14681493        mVspKdTree->RefineViewCells(rays); 
    14691494 
    1470                 // collapse siblings belonging to the same view cell 
     1495        // collapse siblings belonging to the same view cell 
    14711496        mVspKdTree->CollapseTree(); 
    14721497 
     
    18271852        Debug << "saved rays: " << (int)savedRays.size() << endl; 
    18281853 
    1829         mVspBspTree->Construct(constructionRays, &mSceneBox); 
     1854        mVspBspTree->Construct(constructionRays, &mViewSpaceBox); 
    18301855 
    18311856        Debug << mVspBspTree->GetStatistics() << endl; 
     
    19822007        } 
    19832008 
    1984         EvaluateViewCellsStats(); 
    1985  
    1986         // view cells already finished post processing step 
     2009         
     2010        // view cells already finished before post processing step (i.e. because they were loaded) 
    19872011        if (mViewCellsFinished) 
     2012        { 
     2013                EvaluateViewCellsStats(); 
    19882014                return 0; 
     2015        } 
     2016         
     2017 
     2018        // check if new view cells turned invalid 
     2019        mVspBspTree->CheckValidy(); 
     2020        ResetViewCells(); 
     2021 
    19892022 
    19902023        VssRayContainer postProcessRays; 
     
    20382071        for (int i = 0; i < limit; ++ i) 
    20392072        { 
    2040                 viewPoint = mSceneBox.GetRandomPoint(); 
     2073                viewPoint = mViewSpaceBox.GetRandomPoint(); 
    20412074                if (mVspBspTree->ViewPointValid(viewPoint)) 
    20422075                { 
     
    20512084bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const 
    20522085{ 
    2053         return mSceneBox.IsInside(viewPoint) && 
     2086        return mViewSpaceBox.IsInside(viewPoint) && 
    20542087                   mVspBspTree->ViewPointValid(viewPoint); 
    20552088} 
     
    20722105                if (exporter) 
    20732106                { 
     2107                        if (1) 
     2108                        { 
     2109                                exporter->SetWireframe(); 
     2110                                exporter->ExportBox(mViewSpaceBox); 
     2111                                exporter->SetFilled(); 
     2112                        } 
     2113 
    20742114                        if (mExportGeometry) 
     2115                        { 
    20752116                                exporter->ExportGeometry(objects); 
     2117                        } 
    20762118 
    20772119                        // export rays 
     
    20992141        } 
    21002142 
    2101         // export single view cells 
     2143        //-- export single view cells 
    21022144        ExportBspPvs(objects, visRays); 
    21032145} 
     
    21672209                VssRayContainer vcRays; 
    21682210                Intersectable::NewMail(); 
    2169 #if 0 
     2211#if 0 // largest view cell pvs first 
    21702212                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]); 
    21712213#else 
     
    23012343                                                                                          ViewCell *vc) const 
    23022344{ 
    2303 #if 1 
    2304     if (vc->GetMesh()) 
     2345        if (vc->GetMesh()) 
    23052346        { 
    23062347                exporter->ExportMesh(vc->GetMesh()); 
     
    23122353                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom); 
    23132354        exporter->ExportPolygons(geom.mPolys); 
    2314 #else 
    2315  
    2316         Material m2; 
    2317         m2.mDiffuseColor.b = 0.3f + Random(0.7f); 
    2318         m2.mDiffuseColor.r = 0.0f;//0.3f + Random(0.7f); 
    2319         m2.mDiffuseColor.g = 0.3f + Random(0.7f); 
    2320         Material m; 
    2321         m.mDiffuseColor.b = 0.0f; 
    2322         m.mDiffuseColor.r = 1.0f; 
    2323         m.mDiffuseColor.g = 0.0f; 
    2324  
    2325         BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc); 
    2326         vector<BspLeaf *>::const_iterator it, it_end = bspVc->mLeaves.end(); 
    2327  
    2328         for (it = bspVc->mLeaves.begin(); it != it_end; ++ it) 
    2329         { 
    2330                 if ((*it)->Mailed()) 
    2331                         exporter->SetForcedMaterial(m); 
    2332                 else 
    2333                         exporter->SetForcedMaterial(m2); 
    2334                         //exporter->ResetForcedMaterial(); 
    2335                 BspNodeGeometry geom; 
    2336                 mVspBspTree->ConstructGeometry(*it, geom); 
    2337                 exporter->ExportPolygons(geom.mPolys); 
    2338         } 
    2339 #endif 
    23402355} 
    23412356 
  • trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h

    r532 r542  
    319319        ViewCellsStatistics mViewCellsStats; 
    320320        /// the scene bounding box 
    321         AxisAlignedBox3 mSceneBox; 
     321        AxisAlignedBox3 mViewSpaceBox; 
    322322        /// holds the view cell meshes 
    323323        MeshContainer mMeshContainer; 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp

    r538 r542  
    278278 
    279279        int numObj = 0; 
     280 
    280281        //-- extract polygons intersected by the rays 
    281282        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     
    313314        mMaxPvs = (int)(mMaxPvsRatio * (float)numObj); 
    314315         
    315         Debug << "maximal pvs (i.e., view cell considered as valid: " << mMaxPvs << endl; 
     316        Debug << "maximal pvs (i.e., pvs still considered as valid) : " << mMaxPvs << endl; 
    316317        //-- store rays 
    317318        for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 
     
    382383 
    383384        mStat.Start(); 
    384         cout << "Contructing vsp bsp tree ... "; 
    385  
    386         long startTime = GetTime(); 
    387          
    388         bool mOutOfMemory = false; 
     385        cout << "Contructing vsp bsp tree ... \n"; 
     386 
     387        long startTime = GetTime();      
     388        long interTime = GetTime();      
     389        mOutOfMemory = false; 
     390 
     391        int nleaves = 500; 
    389392 
    390393        while (!tStack.empty()) 
     
    404407                } 
    405408 
    406                 // subdivide leaf node 
     409                        // subdivide leaf node 
    407410                BspNode *r = Subdivide(tStack, tData); 
    408411 
    409412                if (r == mRoot) 
    410413                        Debug << "VSP BSP tree construction time spent at root: " 
    411                                   << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl << endl; 
    412         } 
    413  
    414         Debug << "Used Memory: " << GetMemUsage() << " MB" << endl; 
     414                                  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 
     415 
     416                if (mStat.Leaves() >= nleaves) 
     417                { 
     418                        nleaves += 500; 
     419                                 
     420                        cout << "leaves=" << mStat.Leaves() << endl; 
     421                        Debug << "needed " 
     422                          << TimeDiff(interTime, GetTime())*1e-3 << " secs to create 500 leaves" << endl; 
     423                        interTime = GetTime(); 
     424                } 
     425        } 
     426 
     427        Debug << "Used Memory: " << GetMemUsage() << " MB" << endl << endl; 
    415428        cout << "finished\n"; 
    416429 
     
    436449        BspNode *newNode = tData.mNode; 
    437450 
    438         if (!mOutOfMemory || !TerminationCriteriaMet(tData)) 
     451        if (!mOutOfMemory && !TerminationCriteriaMet(tData)) 
    439452        { 
    440453                PolygonContainer coincident; 
     
    508521 
    509522 
     523 
     524 
    510525BspNode *VspBspTree::SubdivideNode(VspBspTraversalData &tData, 
    511526                                                                   VspBspTraversalData &frontData, 
     
    517532        // select subdivision plane 
    518533        Plane3 splitPlane; 
     534         
    519535        int maxCostMisses = tData.mMaxCostMisses; 
    520         bool success = SelectPlane(splitPlane,  
    521                                                            leaf,  
    522                                                            tData, 
    523                                                            frontData, 
    524                                                            backData); 
     536 
     537        const bool success =  
     538                SelectPlane(splitPlane, leaf, tData, frontData, backData); 
     539 
    525540        if (!success) 
    526541        { 
     
    578593        if (mPvsUseArea) 
    579594        { 
    580                 // if not already computed 
     595                // if geometry was not already computed 
    581596                if (!frontData.mGeometry && !backData.mGeometry) 
    582597                { 
     
    820835                                                                                 BspNodeGeometry **backGeom, 
    821836                                                                                 float &frontArea, 
    822                                                                                  float &backArea) 
     837                                                                                 float &backArea, 
     838                                                                                 bool useKdSplit) 
    823839{ 
    824840        const bool useCostHeuristics = false; 
     
    838854        AxisAlignedBox3 box; 
    839855        box.Initialize(); 
    840          
     856        //TODO: for kd split geometry already is box 
    841857        if (1 && mPvsUseArea) 
    842858        { 
     
    868884                                Vector3 normal(0,0,0); normal[axis] = 1; 
    869885                                 
    870                                 nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]),  
    871                                                                                                   tData, *nFrontGeom[axis], *nBackGeom[axis], 
    872                                                                                                   nFrontArea[axis], nBackArea[axis]); 
     886                                if (useKdSplit) 
     887                                { 
     888                                        nCostRatio[axis] = EvalAxisAlignedSplitCost(tData, 
     889                                                                                                                                box, 
     890                                                                                                                                axis, 
     891                                                                                                                                nPosition[axis]); 
     892                                         
     893                                        Vector3 pos = box.Max(); pos[axis] = nPosition[axis]; 
     894                                        AxisAlignedBox3 frontBox(box.Min(), pos); 
     895                                        frontBox.ExtractPolys(nFrontGeom[axis]->mPolys); 
     896                                         
     897                                        pos = box.Min(); pos[axis] = nPosition[axis]; 
     898                                        AxisAlignedBox3 backBox(pos, box.Max()); 
     899                                        backBox.ExtractPolys(nBackGeom[axis]->mPolys); 
     900 
     901                                } 
     902                                else 
     903                                { 
     904                                        nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]),  
     905                                                                                                          tData, *nFrontGeom[axis], *nBackGeom[axis], 
     906                                                                                                          nFrontArea[axis], nBackArea[axis]); 
     907                                } 
    873908                        } 
    874909                        else 
     
    903938        *frontGeom = nFrontGeom[bestAxis]; 
    904939        *backGeom = nBackGeom[bestAxis]; 
     940 
    905941        // and delete other geometry 
    906942        delete nFrontGeom[(bestAxis + 1) % 3]; 
     
    913949        return nCostRatio[bestAxis]; 
    914950} 
     951 
     952 
     953float VspBspTree::EvalAxisAlignedSplitCost(const VspBspTraversalData &data, 
     954                                                                                   const AxisAlignedBox3 &box, 
     955                                                                                   const int axis, 
     956                                                                                   const float &position) const 
     957{ 
     958        int pvsFront = 0; 
     959        int pvsBack = 0; 
     960        int pvsTotal = 0; 
     961 
     962        // create unique ids for pvs heuristics 
     963        GenerateUniqueIdsForPvs(); 
     964 
     965        const int pvsSize = data.mPvs; 
     966 
     967        // this is the main ray classification loop! 
     968        for(RayInfoContainer::iterator ri = data.mRays->begin(); 
     969                ri != data.mRays->end(); ++ ri) 
     970        { 
     971                if (!(*ri).mRay->IsActive()) 
     972                        continue; 
     973 
     974                // determine the side of this ray with respect to the plane 
     975                float t; 
     976                int side = (*ri).ComputeRayIntersection(axis, position, t); 
     977         
     978                AddObjToPvs((*ri).mRay->mTerminationObject, side, pvsFront, pvsBack, pvsTotal); 
     979                AddObjToPvs((*ri).mRay->mOriginObject, side, pvsFront, pvsBack, pvsTotal); 
     980        } 
     981 
     982        //-- only one of these options should be one 
     983        //-- pvs + probability heuristics 
     984        float pBack, pFront, pOverall; 
     985 
     986        if (1) 
     987        { 
     988                // box length substitute for probability 
     989                const float minBox = box.Min(axis); 
     990                const float maxBox = box.Max(axis); 
     991 
     992                pBack = position - minBox; 
     993                pFront = maxBox - position; 
     994                pOverall = maxBox - minBox; 
     995        } 
     996        else //-- area substitute for probability 
     997        { 
     998                pOverall = box.SurfaceArea(); 
     999 
     1000                const bool useMidSplit = true; 
     1001                //const bool useMidSplit = false;        
     1002                                         
     1003                //-- simplified computation for mid split 
     1004                const int axis2 = (axis + 1) % 3; 
     1005                const int axis3 = (axis + 2) % 3; 
     1006 
     1007                const float faceArea =  
     1008                        (box.Max(axis2) - box.Min(axis2)) * 
     1009                        (box.Max(axis3) - box.Min(axis3)); 
     1010 
     1011                pBack = pFront = pOverall * 0.5f + faceArea; 
     1012        } 
     1013 
     1014        //Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl; 
     1015        //Debug << pFront << " " << pBack << " " << pOverall << endl; 
     1016 
     1017        // float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 
     1018        const float newCost = pvsBack * pBack + pvsFront * pFront; 
     1019        //  float oldCost = leaf->mRays.size(); 
     1020        const float oldCost = (float)pvsSize * pOverall; 
     1021 
     1022        return  (mCtDivCi + newCost) / oldCost; 
     1023} 
     1024 
    9151025 
    9161026 
     
    9841094        candidateCost = SelectAxisAlignedPlane(plane, data, axis, 
    9851095                                                                                   &fGeom, &bGeom,  
    986                                                                                    fArea, bArea);                                                 
     1096                                                                                   fArea, bArea, 
     1097                                                                                   onlyAxisAligned);      
    9871098 
    9881099        if (candidateCost < lowestCost) 
     
    9911102                lowestCost = candidateCost; 
    9921103 
    993                 //-- assign already computed values 
     1104                // assign already computed values 
     1105                // we can do this because we always save the 
     1106                // computed values from the axis aligned splits 
    9941107                frontData.mGeometry = fGeom; 
    9951108                backData.mGeometry = bGeom; 
     
    11231236        int totalPvs = 0; 
    11241237 
     1238        int limit; 
     1239        bool useRand; 
     1240 
     1241        // choose test rays randomly if too much 
     1242        if ((int)data.mRays->size() > mMaxTests) 
     1243        { 
     1244                useRand = true; 
     1245                limit = mMaxTests; 
     1246        } 
     1247        else 
     1248        { 
     1249                useRand = false; 
     1250                limit = (int)data.mRays->size(); 
     1251        } 
     1252         
     1253        for (int i = 0; i < limit; ++ i) 
     1254        { 
     1255                const int testIdx = useRand ?  
     1256                        (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
     1257                RayInfo rayInf = (*data.mRays)[testIdx]; 
     1258 
     1259                float t; 
     1260                VssRay *ray = rayInf.mRay; 
     1261                const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
     1262 
     1263        if (cf >= 0) 
     1264                        ++ raysFront; 
     1265                if (cf <= 0) 
     1266                        ++ raysBack; 
     1267 
     1268                if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     1269                { 
     1270                        sumBalancedRays += cf; 
     1271                } 
     1272 
     1273                if (mSplitPlaneStrategy & BALANCED_RAYS) 
     1274                { 
     1275                        if (cf == 0) 
     1276                                ++ sumRaySplits; 
     1277                } 
     1278 
     1279                if (mSplitPlaneStrategy & PVS) 
     1280                { 
     1281                        // find front and back pvs for origing and termination object 
     1282                        AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
     1283                        AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
     1284                } 
     1285        } 
     1286 
     1287        const float raysSize = (float)data.mRays->size() + Limits::Small; 
    11251288        if (mSplitPlaneStrategy & PVS) 
    11261289        { 
     
    11361299                                                                                  mBox, 
    11371300                                                                                  mEpsilon); 
    1138  
     1301#if 0 
     1302                        AxisAlignedBox3 fbox; 
     1303                        AxisAlignedBox3 bbox; 
     1304                        AxisAlignedBox3 box; 
     1305                        fbox.Initialize(); 
     1306                        bbox.Initialize(); 
     1307                        box.Initialize(); 
     1308 
     1309                        geomFront.IncludeInBox(fbox); 
     1310                        geomBack.IncludeInBox(bbox); 
     1311                        data.mGeometry->IncludeInBox(box); 
     1312 
     1313                        areaFront = fbox.GetVolume(); 
     1314                        areaBack = bbox.GetVolume(); 
     1315 
     1316                        pOverall = box.GetVolume(); 
     1317#else 
    11391318                        areaFront = geomFront.GetArea(); 
    11401319                        areaBack = geomBack.GetArea(); 
    11411320 
     1321                        pOverall = data.mArea; 
     1322#endif 
    11421323                        pBack = areaBack; 
    11431324                        pFront = areaFront; 
    1144                         pOverall = data.mArea; 
    11451325                } 
    11461326                else // use number of rays to approximate volume 
     
    11521332        } 
    11531333 
    1154         int limit; 
    1155         bool useRand; 
    1156  
    1157         // choose test rays randomly if too much 
    1158         if ((int)data.mRays->size() > mMaxTests) 
    1159         { 
    1160                 useRand = true; 
    1161                 limit = mMaxTests; 
    1162         } 
    1163         else 
    1164         { 
    1165                 useRand = false; 
    1166                 limit = (int)data.mRays->size(); 
    1167         } 
    1168          
    1169         for (int i = 0; i < limit; ++ i) 
    1170         { 
    1171                 const int testIdx = useRand ?  
    1172                         (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 
    1173                 RayInfo rayInf = (*data.mRays)[testIdx]; 
    1174  
    1175                 float t; 
    1176                 VssRay *ray = rayInf.mRay; 
    1177                 const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 
    1178  
    1179         if (cf >= 0) 
    1180                         ++ raysFront; 
    1181                 if (cf <= 0) 
    1182                         ++ raysBack; 
    1183  
    1184                 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
    1185                 { 
    1186                         sumBalancedRays += cf; 
    1187                 } 
    1188  
    1189                 if (mSplitPlaneStrategy & BALANCED_RAYS) 
    1190                 { 
    1191                         if (cf == 0) 
    1192                                 ++ sumRaySplits; 
    1193                 } 
    1194  
    1195                 if (mSplitPlaneStrategy & PVS) 
    1196                 { 
    1197                         // find front and back pvs for origing and termination object 
    1198                         AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 
    1199                         AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 
    1200                 } 
    1201         } 
    1202  
    1203         const float raysSize = (float)data.mRays->size() + Limits::Small; 
    12041334 
    12051335        if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 
     
    14731603} 
    14741604 
     1605 
     1606 
     1607void VspBspTree::CheckValidy() 
     1608{ 
     1609        stack<BspNode *> nodeStack; 
     1610 
     1611        if (!mRoot) 
     1612                return; 
     1613 
     1614        nodeStack.push(mRoot); 
     1615         
     1616        while (!nodeStack.empty())  
     1617        { 
     1618                BspNode *node = nodeStack.top(); 
     1619                nodeStack.pop(); 
     1620                 
     1621                if (node->IsLeaf()) 
     1622                { 
     1623                        BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 
     1624 
     1625                        if (node->TreeValid()) 
     1626                        { 
     1627                                BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell(); 
     1628                         
     1629                                if (viewCell->GetPvs().GetSize() > mMaxPvs) 
     1630                                { 
     1631                                        while (!viewCell->mLeaves.empty()) 
     1632                                        { 
     1633                                                BspLeaf *l = viewCell->mLeaves.back(); 
     1634                                                l->SetTreeValid(false); 
     1635                                                PropagateUpValidity(l); 
     1636 
     1637                                                l->SetViewCell(GetOrCreateOutOfBoundsCell()); 
     1638                                                viewCell->mLeaves.pop_back(); 
     1639                                        } 
     1640 
     1641                                        mOutOfBoundsCell->GetPvs().AddPvs(viewCell->GetPvs()); 
     1642 
     1643                                        DEL_PTR(viewCell); 
     1644                                } 
     1645                        } 
     1646                } 
     1647                else 
     1648                { 
     1649                        BspInterior *interior = dynamic_cast<BspInterior *>(node); 
     1650                 
     1651                        nodeStack.push(interior->GetFront()); 
     1652                        nodeStack.push(interior->GetBack()); 
     1653                } 
     1654        } 
     1655} 
    14751656 
    14761657void VspBspTree::CollectViewCells(BspNode *root,  
     
    24382619 
    24392620        //-- collect the leaves which haven't been found by ray casting 
    2440         vector<BspLeaf *> leaves; 
    2441         CollectLeaves(leaves, true, mMaxPvs); 
    2442         Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 
    2443         // TODO 
    2444         CollectMergeCandidates(leaves); 
     2621        if (0) 
     2622        { 
     2623                vector<BspLeaf *> leaves; 
     2624                CollectLeaves(leaves, true, mMaxPvs); 
     2625                Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 
     2626                CollectMergeCandidates(leaves); 
     2627        } 
    24452628 
    24462629        return numLeaves; 
     
    25192702                    mMergeMaxCostRatio * BspMergeCandidate::sOverallCost)) 
    25202703        { 
    2521                 //Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() << " rel mergecost: " 
    2522                 //        << mMergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost  
    2523                 //        << " max ratio: " << mMergeMaxCostRatio << endl; 
     2704                /*Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() << " rel mergecost: " 
     2705                          << mMergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost  
     2706                          << " max ratio: " << mMergeMaxCostRatio << endl;*/ 
    25242707                BspMergeCandidate mc = mMergeQueue.top(); 
    25252708                mMergeQueue.pop(); 
     
    25322715                { 
    25332716                        ViewCell::NewMail(); 
     2717         
    25342718                        MergeViewCells(mc.GetLeaf1(), mc.GetLeaf2()); 
    25352719                        -- nViewCells; 
     
    27092893 
    27102894        leaf->SetViewCell(vc2); // finally change view cell 
    2711          
    2712         //Debug << "new pvs: " << vc1->GetPvs().GetSize() + vc2->GetPvs().GetSize()  
    2713         //        << " (" << vc1->GetPvs().GetSize() << ", " << vc2->GetPvs().GetSize() << ")" << endl; 
    2714  
    27152895} 
    27162896 
     
    27412921        if (shuffledCost1 < shuffledCost2) 
    27422922        { 
    2743                 //Debug << "old cost: " << oldCost << ", new cost: " << shuffledCost1 << endl; 
    27442923                ShuffleLeaf(leaf1, vc1, vc2); 
    27452924                leaf1->Mail(); 
     
    27472926        else 
    27482927        { 
    2749                 //Debug << "old cost: " << oldCost << ", new cost: " << shuffledCost2 << endl; 
    27502928                ShuffleLeaf(leaf2, vc2, vc1); 
    27512929                leaf2->Mail(); 
     
    28793057 
    28803058        //-- compute ratio of old cost 
    2881         //-- (added size of left and right view cell times pvs size) 
    2882         //-- to new rendering cost (size of merged view cell times pvs size) 
     3059        //   (i.e., added size of left and right view cell times pvs size) 
     3060        //   to new rendering cost (i.e, size of merged view cell times pvs size) 
    28833061        const float oldCost = GetLeaf1Cost() + GetLeaf2Cost(); 
    28843062 
     
    28863064                (float)newPvs * (vc1->GetArea() + vc2->GetArea()); 
    28873065 
    2888         mMergeCost = newCost - oldCost; 
    28893066        if (newPvs > sMaxPvsSize) // strong penalty if pvs size too large 
    2890                 mMergeCost += 1.0; 
    2891 } 
     3067        { 
     3068                mMergeCost = 1e15f; 
     3069        } 
     3070        else 
     3071        { 
     3072                mMergeCost = newCost - oldCost; 
     3073        } 
     3074} 
     3075 
    28923076 
    28933077void BspMergeCandidate::SetLeaf1(BspLeaf *l) 
     
    28963080} 
    28973081 
     3082 
    28983083void BspMergeCandidate::SetLeaf2(BspLeaf *l) 
    28993084{ 
     
    29013086} 
    29023087 
     3088 
    29033089BspLeaf *BspMergeCandidate::GetLeaf1() 
    29043090{ 
     
    29063092} 
    29073093 
     3094 
    29083095BspLeaf *BspMergeCandidate::GetLeaf2() 
    29093096{ 
    29103097        return mLeaf2; 
    29113098} 
     3099 
    29123100 
    29133101bool BspMergeCandidate::Valid() const 
     
    29183106} 
    29193107 
     3108 
    29203109float BspMergeCandidate::GetMergeCost() const 
    29213110{ 
    29223111        return mMergeCost; 
    29233112} 
     3113 
    29243114 
    29253115void BspMergeCandidate::SetValid() 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h

    r532 r542  
    6060                /// how often this branch has missed the max-cost ratio 
    6161                int mMaxCostMisses; 
    62          
     62                /// bounding box of current view space. 
     63                ///AxisAlignedBox3 mBbox; 
     64                 
    6365                /** Returns average ray contribution. 
    6466                */ 
     
    7880                mGeometry(NULL), 
    7981                mMaxCostMisses(0) 
     82                //,mIsAxisAligned(false) 
    8083                {} 
    8184                 
     
    297300                                                  ViewCellContainer &viewCells, 
    298301                                                  bool onlyUnmailed = false) const; 
     302 
     303        /** returns maximal valid pvs. 
     304        */ 
     305        int GetMaxPvs() { return mMaxPvs;} 
     306 
     307        /** Checks validy of view cells. 
     308                if not valid, sets regions invalid and deletes view cell. 
     309        */ 
     310        void CheckValidy(); 
     311 
    299312protected: 
    300313 
     
    326339        }; 
    327340 
     341        float EvalAxisAlignedSplitCost(const VspBspTraversalData &data, 
     342                                                                   const AxisAlignedBox3 &box, 
     343                                                                   const int axis, 
     344                                                                   const float &position) const; 
     345 
    328346        /** Returns view cell corresponding to  
    329347                the invalid view space. If it does not exist, it is created. 
     
    447465                                                                 BspNodeGeometry **backGeom, 
    448466                                                                 float &frontArea, 
    449                                                                  float &backArea); 
     467                                                                 float &backArea, 
     468                                                                 bool useKdSplit); 
    450469 
    451470        /** Sorts split candidates for surface area heuristics for axis aligned splits. 
     
    779798        static float sOverallCost; 
    780799 
     800        /** Evaluates the merge costs of the leaves. 
     801        */ 
     802        void EvalMergeCost(); 
     803 
    781804protected: 
    782805 
     
    784807        */ 
    785808        float GetCost(ViewCell *vc) const; 
    786         /** Evaluates the merge costs of the leaves. 
    787         */ 
    788         void EvalMergeCost(); 
    789  
     809         
    790810        int mLeaf1Id; 
    791811        int mLeaf2Id; 
  • trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp

    r517 r542  
    832832        float pBack, pFront, pOverall; 
    833833 
    834         if (0) 
     834        if (1) 
    835835        { 
    836836                // box length substitute for probability 
     
    843843        } 
    844844 
    845         if (1) //-- area substitute for probability 
     845        if (0) //-- area substitute for probability 
    846846        { 
    847847                pOverall = box.SurfaceArea(); 
  • trunk/VUT/GtpVisibilityPreprocessor/src/common.cpp

    r372 r542  
    4646Real Limits::Threshold = 1e-6f; 
    4747Real Limits::Small = 0.01f; 
    48 Real Limits::Infinity = 1e20f; 
     48Real Limits::Infinity = 1e20; 
    4949 
    5050 
Note: See TracChangeset for help on using the changeset viewer.