Changeset 1006 for GTP/trunk/Lib/Vis
- Timestamp:
- 06/09/06 01:26:46 (19 years ago)
- Location:
- GTP/trunk/Lib/Vis
- Files:
-
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
r1004 r1006 158 158 </File> 159 159 <File 160 RelativePath="..\src\FromPointVisibilityTree.cpp">161 </File>162 <File163 RelativePath="..\src\FromPointVisibilityTree.h">164 </File>165 <File166 160 RelativePath="..\src\glInterface.h"> 167 161 </File> … … 176 170 Name="VCCustomBuildTool" 177 171 Description="Performing moc on $(InputName).h" 178 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
" 172 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp 173 " 179 174 Outputs="$(InputDir)moc_$(InputName).cpp"/> 180 175 </FileConfiguration> … … 307 302 Name="VCCustomBuildTool" 308 303 Description="Performing moc on $(InputName).h" 309 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
" 304 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp 305 " 310 306 Outputs="$(InputDir)moc_$(InputName).cpp"/> 311 307 </FileConfiguration> … … 321 317 Name="VCCustomBuildTool" 322 318 Description="Performing moc on $(InputName).h" 323 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
" 319 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp 320 " 324 321 Outputs="$(InputDir)moc_$(InputName).cpp"/> 325 322 </FileConfiguration> … … 461 458 </File> 462 459 <File 463 RelativePath="..\src\Vsp KdTree.cpp">464 </File> 465 <File 466 RelativePath="..\src\Vsp KdTree.h">460 RelativePath="..\src\VspOspTree.cpp"> 461 </File> 462 <File 463 RelativePath="..\src\VspOspTree.h"> 467 464 </File> 468 465 <File -
GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp
r863 r1006 2123 2123 } 2124 2124 2125 } 2125 void AxisAlignedBox3::Split(const int axis, 2126 const float value, 2127 AxisAlignedBox3 &left, 2128 AxisAlignedBox3 &right) 2129 { 2130 if ( (value >= mMin[axis]) && (value <= mMax[axis]) ) 2131 { 2132 left.mMin = mMin; left.mMax = mMax; 2133 right.mMin = mMin; right.mMax = mMax; 2134 2135 left.mMax[axis] = value; 2136 right.mMin[axis] = value; 2137 2138 } 2139 } 2140 } -
GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.h
r870 r1006 101 101 mMax[axis] = value; 102 102 } 103 103 104 105 104 106 // the size of the box along all the axes 105 107 Vector3 Size() const { return mMax - mMin; } … … 389 391 void ExtractPolys(PolygonContainer &polys) const; 390 392 393 /** Splits the box into two separate boxes according to the split plane 394 */ 395 void Split(const int axis, const float value, AxisAlignedBox3 &left, AxisAlignedBox3 &right); 396 391 397 #define __EXTENT_HACK 392 398 // get the extent of face -
GTP/trunk/Lib/Vis/Preprocessing/src/BoundingBoxConverter.h
r939 r1006 6 6 namespace GtpVisibilityPreprocessor { 7 7 8 /** helper struct used for identifyingobjects with similar bounding boxes.8 /** helper struct used to identify objects with similar bounding boxes. 9 9 */ 10 10 struct IndexedBoundingBox: public std::pair<int, AxisAlignedBox3> -
GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
r1004 r1006 1374 1374 "boxes.out"); 1375 1375 1376 RegisterOption("ViewCells.PostProcess.emptyViewCellsMerge",1377 optBool,1378 "view_cells_merge_empty=",1379 "true");1380 1381 1376 RegisterOption("ViewCells.evaluateViewCells", 1382 1377 optBool, … … 1739 1734 1740 1735 1741 /**************************************************************************************/1742 /* View space partition KD tree related options */1743 /**************************************************************************************/1744 1745 RegisterOption("VspKdTree.Construction.samples",1746 optInt,1747 "vsp_kd_construction_samples=",1748 "100000");1749 1750 RegisterOption("VspKdTree.Termination.maxDepth",1751 optInt,1752 "vsp_term_maxdepth=",1753 "30");1754 1755 RegisterOption("VspKdTree.Termination.minPvs",1756 optInt,1757 "vsp_minpvs=",1758 "1");1759 1760 RegisterOption("VspKdTree.Termination.minRays",1761 optInt,1762 "vsp_term_minrays=",1763 "10");1764 1765 RegisterOption("VspKdTree.Termination.minSize",1766 optFloat,1767 "vsp_term_minsize=",1768 "0.001");1769 1770 RegisterOption("VspKdTree.Termination.maxCostRatio",1771 optFloat,1772 "vsp_term_maxcost=",1773 "0.95");1774 1775 RegisterOption("VspKdTree.Termination.maxRayContribution",1776 optFloat,1777 "vsp_term_max_ray_contrib=",1778 "0.5");1779 1780 RegisterOption("VspKdTree.epsilon",1781 optFloat,1782 "kd_eps=",1783 "1e-6");1784 1785 RegisterOption("VspKdTree.ct_div_ci",1786 optFloat,1787 "vsp_ctdivci=", "1.0");1788 1789 RegisterOption("VspKdTree.splitType",1790 optString,1791 "split=",1792 "queries");1793 1794 RegisterOption("VspKdTree.splitAxis",1795 optString,1796 "split=",1797 "drivingAxis");1798 1799 RegisterOption("VspKdTree.splitUseOnlyDrivingAxis",1800 optBool,1801 "vsp_kd_splitdriving=",1802 "false");1803 1804 RegisterOption("VspKdTree.numberOfEndPointDomains",1805 optInt,1806 "endpoints=",1807 "10000");1808 1809 RegisterOption("VspKdTree.maxTotalMemory",1810 optFloat,1811 "vsp_max_total_mem=",1812 "60.0");1813 1814 RegisterOption("VspKdTree.maxStaticMemory",1815 optFloat,1816 "vsp_max_static_mem=",1817 "8.0");1818 1819 RegisterOption("VspKdTree.queryType",1820 optString,1821 "qtype=",1822 "static");1823 1824 RegisterOption("VspKdTree.queryPosWeight",1825 optFloat,1826 "vsp_kd_qposweight=",1827 "0.0");1828 1829 RegisterOption("VspKdTree.accessTimeThreshold",1830 optInt,1831 "vsp_kd_accesstime=",1832 "1000");1833 1834 RegisterOption("VspKdTree.minCollapseDepth",1835 optInt,1836 "vsp_kd_min_colldepth=",1837 "4");1838 1839 RegisterOption("VspKdTree.PostProcess.maxCostRatio",1840 optFloat,1841 "vsp_kd_post_process_max_cost_ratio=",1842 "0.9");1843 1844 RegisterOption("VspKdTree.PostProcess.minViewCells",1845 optInt,1846 "vsp_kd_term_post_process_min_view_cells=",1847 "1000");1848 1849 RegisterOption("VspKdTree.Termination.maxViewCells",1850 optInt,1851 "vsp_kd_term_post_process_min_view_cells=",1852 "300");1853 1854 RegisterOption("VspKdTree.PostProcess.maxPvsSize",1855 optInt,1856 "vsp_kd_term_post_process_max_pvs_size=",1857 "100");1858 1859 RegisterOption("VspKdTree.Termination.missTolerance",1860 optInt,1861 "vsp_kd_term_miss_tolerance=",1862 "4");1863 1864 1736 /************************************************************************************/ 1865 1737 /* VSS Preprocessor cells related options */ -
GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.h
r863 r1006 16 16 class KdTree; 17 17 class BspTree; 18 class VspKdTree;19 18 class SceneGraphNode; 20 19 class Ray; … … 64 63 const Vector3 direction 65 64 ) = 0; 66 67 virtual bool68 ExportVspKdTree(const VspKdTree &tree, const int maxPvs = 0) = 0;69 65 70 66 virtual bool -
GTP/trunk/Lib/Vis/Preprocessing/src/FromPointVisibilityTree.cpp
r1004 r1006 124 124 Environment::GetSingleton()->GetIntValue("FromPointVisibilityTree.nodePriorityQueueType", mNodePriorityQueueType); 125 125 126 Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.emptyViewCellsMerge", mEmptyViewCellsMergeAllowed);127 126 128 127 char subdivisionStatsLog[100]; … … 160 159 Debug << "use random axis: " << mUseRandomAxis << endl; 161 160 Debug << "priority queue type: " << mNodePriorityQueueType << endl; 162 Debug << "empty view cells merge: " << mEmptyViewCellsMergeAllowed << endl;161 163 162 Debug << "octree: " << mCirculatingAxis << endl; 164 163 Debug << "minband: " << mMinBand << endl; … … 3707 3706 MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell()); 3708 3707 3709 // dont't merge view cells if they are empty and not front and back leaf of the same parent 3710 // in the tree? 3711 if (mEmptyViewCellsMergeAllowed || 3712 !leaf->GetViewCell()->GetPvs().Empty() || 3708 if (!leaf->GetViewCell()->GetPvs().Empty() || 3713 3709 !(*nit)->GetViewCell()->GetPvs().Empty() || 3714 3710 leaf->IsSibling(*nit)) -
GTP/trunk/Lib/Vis/Preprocessing/src/FromPointVisibilityTree.h
r1002 r1006 827 827 int mNodePriorityQueueType; 828 828 829 bool mEmptyViewCellsMergeAllowed;830 831 829 // priority queue strategy 832 830 enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED}; 831 832 833 833 private: 834 834 -
GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h
r1004 r1006 281 281 signals: 282 282 283 SetViewCellGranularity(int);284 SetSceneCut(int);285 SetTopDistance(int);286 SetVisibilityFilterSize(int);287 SetSpatialFilterSize(int);288 289 SetRenderFilter(bool);290 SetUseFilter(bool);291 SetUseSpatialFilter(bool);292 SetRenderErrors(bool);293 SetShowViewCells(bool);294 SetShowRenderCost(bool);295 SetShowPvsSizes(bool);296 SetTopView(bool);297 SetCutViewCells(bool);298 SetCutScene(bool);283 void SetViewCellGranularity(int); 284 void SetSceneCut(int); 285 void SetTopDistance(int); 286 void SetVisibilityFilterSize(int); 287 void SetSpatialFilterSize(int); 288 289 void SetRenderFilter(bool); 290 void SetUseFilter(bool); 291 void SetUseSpatialFilter(bool); 292 void SetRenderErrors(bool); 293 void SetShowViewCells(bool); 294 void SetShowRenderCost(bool); 295 void SetShowPvsSizes(bool); 296 void SetTopView(bool); 297 void SetCutViewCells(bool); 298 void SetCutScene(bool); 299 299 300 300 -
GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
r1004 r1006 9 9 #include "ViewCellBsp.h" 10 10 #include "VspBspTree.h" 11 #include "VspKdTree.h"12 11 #include "RenderSimulator.h" 13 12 #include "GlRenderer.h" … … 113 112 mKdTree(NULL), 114 113 mBspTree(NULL), 115 mVspKdTree(NULL),116 114 mVspBspTree(NULL), 117 115 mViewCellsManager(NULL), … … 158 156 DEL_PTR(mKdTree); 159 157 cout << "done.\n"; 160 161 cout << "Deleting vspkd tree...\n"; 162 DEL_PTR(mVspKdTree); 158 159 #if 0 160 cout << "Deleting vsp osp tree...\n"; 161 DEL_PTR(mVspOspTree); 163 162 cout << "done.\n"; 163 #endif 164 164 165 165 cout << "Deleting vspbsp tree...\n"; … … 424 424 mViewCellsManager = new VspBspViewCellsManager(mVspBspTree); 425 425 } 426 else if (strcmp(name, "vspKdTree") == 0) 427 { 428 mVspKdTree = new VspKdTree(); 429 430 mViewCellsManager = new VspKdViewCellsManager(mVspKdTree); 431 } 426 #if 0 427 else if (strcmp(name, "vspOspTree") == 0) 428 { 429 mVspOspTree = new VspOspTree(); 430 mViewCellsManager = new VspOspViewCellsManager(mVspOspTree); 431 } 432 #endif 432 433 else if (strcmp(name, "sceneDependent") == 0) 433 434 { -
GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
r904 r1006 17 17 class ViewCellsManager; 18 18 class BspTree; 19 class Vsp KdTree;19 class VspOspTree; 20 20 class VspBspTree; 21 21 class RenderSimulator; … … 151 151 ViewCellsManager *mViewCellsManager; 152 152 153 /** Kd tree inducing a coarse partition of view space that are the building 154 blocks for view cells. 155 */ 156 VspKdTree *mVspKdTree; 153 /// greedy optimized hierarchy for both objects and view cells 154 VspOspTree *mVspOspTree; 157 155 158 156 bool mUseGlRenderer; … … 183 181 /// samples used for construction of the BSP view cells tree. 184 182 int mBspConstructionSamples; 185 /// samples used for construction of the VSP KDtree.186 int mVsp KdConstructionSamples;183 /// samples used for construction of the VSP OSP tree. 184 int mVspOspConstructionSamples; 187 185 /** Simulates rendering of the scene. 188 186 */ -
GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.cpp
r863 r1006 4 4 #include "ViewCell.h" 5 5 #include "VspBspTree.h" 6 #include "VspKdTree.h"7 6 #include "ViewCellsManager.h" 8 7 -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
r1004 r1006 17 17 class BspPvs; 18 18 class BspLeaf; 19 class VspKdTree;20 19 class VspKdLeaf; 21 20 class KdLeaf; -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h
r882 r1006 323 323 }; 324 324 325 325 326 /** BSP interior node implementation 326 327 */ … … 366 367 BspNode *mFront; 367 368 }; 369 368 370 369 371 /** BSP leaf node implementation. -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
r1004 r1006 8 8 #include "ViewCellBsp.h" 9 9 #include "KdTree.h" 10 #include "VspKdTree.h"10 //#include "VspOspTree.h" 11 11 #include "Exporter.h" 12 12 #include "VspBspTree.h" … … 1828 1828 Vector3 termination = hray.Extrap(tmax); 1829 1829 1830 // traverse the view space subdivision 1830 1831 CastLineSegment(origin, termination, viewcells); 1831 1832 1832 // copy viewcells memory efficiently1833 1833 //const bool storeViewcells = !addRays; 1834 1834 //return 0; 1835 1835 if (storeViewCells) 1836 1836 { 1837 // copy viewcells memory efficiently 1837 1838 ray.mViewCells.reserve(viewcells.size()); 1838 1839 ray.mViewCells = viewcells; … … 2090 2091 } 2091 2092 2092 2093 2093 return true; 2094 2094 } … … 2173 2173 2174 2174 2175 void ViewCellsManager::SetScalarPvsSize(ViewCell *vc, const int pvsSize) const 2175 void ViewCellsManager::SetScalarPvsSize(ViewCell *vc, 2176 const int pvsSize) const 2176 2177 { 2177 2178 vc->mPvsSize = pvsSize; … … 3346 3347 } 3347 3348 3348 3349 /**********************************************************************/3350 /* VspKdViewCellsManager implementation */3351 /**********************************************************************/3352 3353 3354 VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):3355 ViewCellsManager(), mVspKdTree(vspKdTree)3356 {3357 Environment::GetSingleton()->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);3358 mVspKdTree->SetViewCellsManager(this);3359 }3360 3361 float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)3362 {3363 // compute view cell area / volume as subsititute for probability3364 if (0)3365 return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();3366 else3367 return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();3368 }3369 3370 3371 3372 3373 void VspKdViewCellsManager::CollectViewCells()3374 {3375 mVspKdTree->CollectViewCells(mViewCells);3376 }3377 3378 3379 int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,3380 const VssRayContainer &rays)3381 {3382 // if view cells already constructed3383 if (ViewCellsConstructed())3384 return 0;3385 3386 VssRayContainer constructionRays;3387 VssRayContainer savedRays;3388 3389 GetRaySets(rays,3390 mInitialSamples,3391 constructionRays,3392 &savedRays);3393 3394 Debug << "constructing vsp kd tree using "3395 << (int)constructionRays.size() << " samples" << endl;3396 3397 mVspKdTree->Construct(constructionRays, &mViewSpaceBox);3398 Debug << mVspKdTree->GetStatistics() << endl;3399 3400 // export leaf building blocks3401 ExportLeaves(objects, rays);3402 3403 // finally merge kd leaf building blocks to view cells3404 const int merged = mVspKdTree->MergeViewCells(rays);3405 3406 // collapse siblings belonging to the same view cell3407 mVspKdTree->RefineViewCells(rays);3408 3409 // collapse siblings belonging to the same view cell3410 mVspKdTree->CollapseTree();3411 3412 // evaluale view cell stats3413 ResetViewCells();3414 3415 Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;3416 3417 long startTime = GetTime();3418 3419 // recast rest of rays3420 ComputeSampleContributions(savedRays, true, false);3421 3422 Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-33423 << " secs" << endl;3424 3425 return merged;3426 }3427 3428 bool VspKdViewCellsManager::ViewCellsConstructed() const3429 {3430 return mVspKdTree->GetRoot() != NULL;3431 }3432 3433 3434 ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const3435 {3436 return new VspKdViewCell(mesh);3437 }3438 3439 int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,3440 const VssRayContainer &rays)3441 {3442 if (!ViewCellsConstructed())3443 return 0;3444 3445 // recalculate stats3446 EvaluateViewCellsStats();3447 3448 return 0;3449 }3450 3451 3452 void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,3453 const VssRayContainer &sampleRays)3454 {3455 if (!ViewCellsConstructed())3456 return;3457 3458 //-- export leaf building blocks3459 Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");3460 if (!exporter)3461 return;3462 3463 if (mExportGeometry)3464 exporter->ExportGeometry(objects);3465 3466 //exporter->SetWireframe();3467 //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);3468 exporter->ExportVspKdTree(*mVspKdTree);3469 3470 if (mExportRays)3471 {3472 const float prob = (float)mVisualizationSamples3473 / ((float)sampleRays.size() + Limits::Small);3474 3475 exporter->SetWireframe();3476 3477 //-- collect uniformly distributed rays3478 VssRayContainer rays;3479 3480 for (int i = 0; i < sampleRays.size(); ++ i)3481 {3482 if (RandomValue(0,1) < prob)3483 rays.push_back(sampleRays[i]);3484 }3485 exporter->ExportRays(rays, RgbColor(1, 0, 0));3486 }3487 3488 delete exporter;3489 }3490 3491 3492 void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,3493 const VssRayContainer &sampleRays)3494 {3495 if (!ViewCellsConstructed())3496 return;3497 3498 //-- export single view cells3499 for (int i = 0; i < 10; ++ i)3500 {3501 char s[64];3502 sprintf(s, "vsp_viewcell%04d.x3d", i);3503 Exporter *exporter = Exporter::GetExporter(s);3504 const int idx =3505 (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));3506 3507 VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);3508 3509 //-- export geometry3510 Material m;3511 m.mDiffuseColor = RgbColor(0, 1, 1);3512 3513 exporter->SetForcedMaterial(m);3514 exporter->SetWireframe();3515 3516 ExportViewCellGeometry(exporter, vc);3517 3518 //-- export stored rays3519 3520 if (mExportRays)3521 {3522 ViewCellContainer leaves;3523 mViewCellsTree->CollectLeaves(vc, leaves);3524 3525 ViewCellContainer::const_iterator it,3526 it_end = leaves.end();3527 3528 for (it = leaves.begin(); it != it_end; ++ it)3529 {3530 VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);3531 VspKdLeaf *leaf = vspKdVc->mLeaf;3532 AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);3533 3534 VssRayContainer vssRays;3535 3536 VssRayContainer castRays;3537 VssRayContainer initRays;3538 3539 leaf->GetRays(vssRays);3540 3541 VssRayContainer::const_iterator it, it_end = vssRays.end();3542 const float prop = 200.0f / (float)vssRays.size();3543 3544 for (it = vssRays.begin(); it != it_end; ++ it)3545 {3546 if (Random(1) < prop)3547 if ((*it)->mTerminationObject == NULL)3548 castRays.push_back(*it);3549 else3550 initRays.push_back(*it);3551 }3552 3553 exporter->ExportRays(castRays, RgbColor(1, 0, 0));3554 exporter->ExportRays(initRays, RgbColor(0, 1, 0));3555 }3556 }3557 3558 //-- output PVS of view cell3559 m.mDiffuseColor = RgbColor(1, 0, 0);3560 exporter->SetForcedMaterial(m);3561 3562 Intersectable::NewMail();3563 3564 ObjectPvsMap::const_iterator it,3565 it_end = vc->GetPvs().mEntries.end();3566 3567 exporter->SetFilled();3568 3569 for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)3570 {3571 Intersectable *intersect = (*it).first;3572 3573 if (!intersect->Mailed())3574 {3575 Material m = RandomMaterial();3576 exporter->SetForcedMaterial(m);3577 3578 exporter->ExportIntersectable(intersect);3579 intersect->Mail();3580 }3581 }3582 3583 delete exporter;3584 }3585 3586 //-- export final view cells3587 Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");3588 3589 3590 ExportViewCellsForViz(exporter);3591 3592 if (mExportGeometry)3593 {3594 exporter->SetFilled();3595 exporter->ExportGeometry(objects);3596 }3597 3598 if (mExportRays)3599 {3600 const float prob = (float)mVisualizationSamples3601 / ((float)sampleRays.size() + Limits::Small);3602 3603 exporter->SetWireframe();3604 3605 VssRayContainer rays;3606 3607 for (int i = 0; i < sampleRays.size(); ++ i)3608 {3609 if (RandomValue(0,1) < prob)3610 rays.push_back(sampleRays[i]);3611 }3612 exporter->ExportRays(rays, RgbColor(1, 0, 0));3613 }3614 3615 delete exporter;3616 }3617 3618 int VspKdViewCellsManager::GetType() const3619 {3620 return VSP_KD;3621 }3622 3623 3624 int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,3625 const Vector3 &termination,3626 ViewCellContainer &viewcells)3627 {3628 return mVspKdTree->CastLineSegment(origin, termination, viewcells);3629 }3630 3631 3632 void VspKdViewCellsManager::ExportColor(Exporter *exporter,3633 ViewCell *vc) const3634 {3635 if (mColorCode == 0) // Random color3636 return;3637 3638 float importance = 0;3639 3640 switch (mColorCode)3641 {3642 case 1: // pvs3643 {3644 importance = (float)mViewCellsTree->GetPvsSize(vc) /3645 (float)mCurrentViewCellsStats.maxPvs;3646 }3647 break;3648 case 2: // merged leaves3649 {3650 const int lSize = mViewCellsTree->GetNumInitialViewCells(vc);3651 importance = (float)lSize /3652 (float)mCurrentViewCellsStats.maxLeaves;3653 }3654 break;3655 case 3: // merged tree depth difference3656 {3657 //importance = (float)GetMaxTreeDiff(vc) /3658 // (float)(mVspBspTree->GetStatistics().maxDepth * 2);3659 }3660 break;3661 default:3662 break;3663 }3664 3665 Material m;3666 m.mDiffuseColor.b = 1.0f;3667 m.mDiffuseColor.r = importance;3668 m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;3669 //Debug << "importance: " << importance << endl;3670 exporter->SetForcedMaterial(m);3671 }3672 3673 3674 void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,3675 ViewCell *vc,3676 const Plane3 *clipPlane) const3677 {3678 VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);3679 3680 Mesh m;3681 3682 ViewCellContainer leaves;3683 mViewCellsTree->CollectLeaves(vc, leaves);3684 3685 ViewCellContainer::const_iterator it, it_end = leaves.end();3686 3687 for (it = leaves.begin(); it != it_end; ++ it)3688 {3689 VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;3690 IncludeBoxInMesh(mVspKdTree->GetBBox(l), m);3691 }3692 3693 exporter->ExportMesh(&m);3694 }3695 3696 3697 void VspKdViewCellsManager::CreateMesh(ViewCell *vc)3698 {3699 //TODO3700 }3701 3702 3703 void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,3704 vector<MergeCandidate> &candidates)3705 {3706 // TODO3707 }3708 3709 3710 3349 /**************************************************************************/ 3711 3350 /* VspBspViewCellsManager implementation */ … … 4343 3982 4344 3983 //exporter->SetFilled(); 4345 bool b = mUseClipPlaneForViz; 3984 // HACK: export without clip plane 3985 const bool b = mUseClipPlaneForViz; 4346 3986 mUseClipPlaneForViz = false; 4347 3987 ExportViewCellsForViz(exporter); -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
r1004 r1006 19 19 class BspTree; 20 20 class KdTree; 21 class Vsp KdTree;21 class VspOspTree; 22 22 class VspBspTree; 23 23 class KdNode; 24 24 class KdLeaf; 25 class VspKdTree;26 25 class AxisAlignedBox3; 27 26 class BspLeaf; … … 813 812 814 813 /** 815 Manages different higher order operations on the view cells816 for vsp kd tree view cells.817 */818 class VspKdViewCellsManager: public ViewCellsManager819 {820 821 public:822 823 VspKdViewCellsManager(VspKdTree *vspKdTree);824 825 int ConstructSubdivision(const ObjectContainer &objects,826 const VssRayContainer &rays);827 828 829 int PostProcess(const ObjectContainer &objects,830 const VssRayContainer &rays);831 832 void Visualize(const ObjectContainer &objects,833 const VssRayContainer &sampleRays);834 835 int GetType() const;836 837 bool ViewCellsConstructed() const;838 839 //virtual void PrintStatistics(ostream &s) const;840 841 ViewCell *GenerateViewCell(Mesh *mesh) const;842 843 844 int CastLineSegment(const Vector3 &origin,845 const Vector3 &termination,846 ViewCellContainer &viewcells);847 848 ViewCell *GetViewCell(const Vector3 &point, const bool active = false) const { return NULL; }849 850 float GetProbability(ViewCell *viewCell);851 852 853 void CreateMesh(ViewCell *vc);854 855 void ExportViewCellGeometry(Exporter *exporter,856 ViewCell *vc,857 const Plane3 *clipPlane = NULL) const;858 859 void CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);860 861 virtual void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs) {};862 863 864 protected:865 866 void ExportLeaves(const ObjectContainer &objects,867 const VssRayContainer &sampleRays);868 869 void CollectViewCells();870 871 void ExportColor(Exporter *exporter, ViewCell *vc) const;872 873 874 875 /// the BSP tree.876 VspKdTree *mVspKdTree;877 };878 879 880 881 /**882 814 Manages different higher order operations on the view cells. 883 815 */ -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp
r1004 r1006 28 28 #include "VspBspTree.h" 29 29 #include "ViewCellBsp.h" 30 #include "VspKdTree.h"31 30 #include "ViewCellsManager.h" 32 31 #include "GzFileInputSource.h" … … 621 620 622 621 mViewCellsManager = new BspViewCellsManager(mBspTree); 623 }624 625 else if (strcmp(name, "vspKdTree") == 0)626 {627 // TODO628 Debug << "view cell type: VspKd" << endl;629 mVspKdTree = new VspKdTree();630 mViewCellsManager = new VspKdViewCellsManager(mVspKdTree);631 622 } 632 623 else // vspBspTree -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParserXerces.h
r1004 r1006 18 18 19 19 class VspBspTree; 20 class VspKdTree;21 20 class BspTree; 22 21 class ViewCellsManager; … … 70 69 71 70 VspBspTree *mVspBspTree; 72 VspKdTree *mVspKdTree;73 71 BspTree *mBspTree; 74 72 ViewCellsTree *mViewCellsTree; -
GTP/trunk/Lib/Vis/Preprocessing/src/VrmlExporter.cpp
r1004 r1006 9 9 #include "Polygon3.h" 10 10 #include "VssRay.h" 11 #include "VspKdTree.h"12 11 #include "VssTree.h" 13 12 #include "VspBspTree.h" … … 590 589 } 591 590 592 593 bool VrmlExporter::ExportVsp KdTree(const VspKdTree &tree,591 #if 0 592 bool VrmlExporter::ExportVspOspTree(const VspOspTree &tree, 594 593 const int maxPvs) 595 594 { … … 662 661 return true; 663 662 } 664 663 #endif 665 664 666 665 bool VrmlExporter::ExportKdTree(const KdTree &tree) -
GTP/trunk/Lib/Vis/Preprocessing/src/VrmlExporter.h
r1001 r1006 59 59 const Vector3 direction 60 60 ); 61 61 #if 0 62 62 bool 63 ExportVsp KdTree(const VspKdTree &tree, const int maxPvs);64 63 ExportVspOspTree(const VspKdTree &tree, const int maxPvs); 64 #endif 65 65 bool ExportBspTree(const BspTree &tree); 66 66 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
r1004 r1006 124 124 Environment::GetSingleton()->GetIntValue("VspBspTree.nodePriorityQueueType", mNodePriorityQueueType); 125 125 126 Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.emptyViewCellsMerge", mEmptyViewCellsMergeAllowed);127 126 128 127 char subdivisionStatsLog[100]; … … 132 131 Environment::GetSingleton()->GetFloatValue("VspBspTree.Construction.minBand", mMinBand); 133 132 Environment::GetSingleton()->GetFloatValue("VspBspTree.Construction.maxBand", mMaxBand); 134 Environment::GetSingleton()->GetBoolValue("VspBspTree.Construction.useDrivingAxisForMaxCost", mUseDrivingAxis ForMaxCost);133 Environment::GetSingleton()->GetBoolValue("VspBspTree.Construction.useDrivingAxisForMaxCost", mUseDrivingAxisIfMaxCostViolated); 135 134 136 135 //-- debug output … … 161 160 Debug << "use random axis: " << mUseRandomAxis << endl; 162 161 Debug << "priority queue type: " << mNodePriorityQueueType << endl; 163 Debug << "empty view cells merge: " << mEmptyViewCellsMergeAllowed << endl;164 162 Debug << "circulating axis: " << mCirculatingAxis << endl; 165 163 Debug << "minband: " << mMinBand << endl; 166 164 Debug << "maxband: " << mMaxBand << endl; 167 Debug << "use driving axis for max cost: " << mUseDrivingAxis ForMaxCost<< endl;165 Debug << "use driving axis for max cost: " << mUseDrivingAxisIfMaxCostViolated << endl; 168 166 169 167 Debug << "Split plane strategy: "; … … 1194 1192 } 1195 1193 1196 if (ray->mOriginObject) 1194 // only count termination objects? 1195 if (1 && ray->mOriginObject) 1197 1196 { 1198 1197 if (vc->AddPvsSample(ray->mOriginObject, ray->mPdf, contribution)) … … 1482 1481 const float maxCostRatioForArbitraryAxis = 0.9f; 1483 1482 1484 if (mUseDrivingAxis ForMaxCost)1483 if (mUseDrivingAxisIfMaxCostViolated) 1485 1484 bestAxis = box.Size().DrivingAxis(); 1486 1485 else … … 1523 1522 nPosition[axis]); 1524 1523 } 1525 1526 //-- split plane position is spatial median 1527 1528 1529 // also use median split if cost ratio very low as 1530 // there are not enough visibility cues 1531 //if (!mUseCostHeuristics || (nCostRatio[axis] > maxCostRatioForHeur)) 1532 else 1524 else //-- split plane position is spatial median 1533 1525 { 1534 1526 … … 1578 1570 1579 1571 1580 if (mUseDrivingAxis ForMaxCost)1572 if (mUseDrivingAxisIfMaxCostViolated) 1581 1573 { 1582 1574 // we take longest axis split if cost ratio exceeds threshold … … 1710 1702 } 1711 1703 1704 1712 1705 //-- evaluate axis aligned splits 1706 1713 1707 int axis; 1714 1708 BspNodeGeometry *fGeom, *bGeom; … … 1717 1711 candidateCost = 99999999.0f; 1718 1712 1719 // option: axis aligned split only if no polygon available 1713 // as a variant, we take axis aligned split only if there is 1714 // more polygon available to guide the split 1720 1715 if (!mUsePolygonSplitIfAvailable || data.mPolygons->empty()) 1721 1716 { … … 1932 1927 1933 1928 #if 1 1934 // take render cost of node into account 1929 // take render cost of node into account to avoid being stuck in a local minimum 1935 1930 const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume(); 1931 1936 1932 //Debug << "rendercostdecr: " << 0.99f * renderCostDecrease << " old render cost: " << 0.01f * normalizedOldRenderCost << endl; 1937 //return 0.5f * renderCostDecrease + 0.5f * normalizedOldRenderCost;1938 1933 return 0.99f * renderCostDecrease + 0.01f * normalizedOldRenderCost; 1939 1934 #else … … 1956 1951 float pvsBack = 0; 1957 1952 1953 // overall probability is used as normalizer 1954 float pOverall = 0; 1955 1958 1956 // probability that view point lies in back / front node 1959 float pOverall = 0;1960 1957 pFront = 0; 1961 1958 pBack = 0; … … 3532 3529 3533 3530 3534 typedef pair<BspNode *, BspNodeGeometry *> bspNodePair;3535 3536 3537 3531 int VspBspTree::CastBeam(Beam &beam) 3538 3532 { … … 3656 3650 MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell()); 3657 3651 3658 // dont't merge view cells if they are empty and not front and back leaf of the same parent 3659 // in the tree? 3660 if (mEmptyViewCellsMergeAllowed || 3661 !leaf->GetViewCell()->GetPvs().Empty() || 3652 if (!leaf->GetViewCell()->GetPvs().Empty() || 3662 3653 !(*nit)->GetViewCell()->GetPvs().Empty() || 3663 3654 leaf->IsSibling(*nit)) -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
r1004 r1006 158 158 struct VspBspSplitCandidate 159 159 { 160 /// the current node160 /// the current split plane 161 161 Plane3 mSplitPlane; 162 162 /// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned) … … 467 467 @param plane returns the split plane 468 468 @param leaf the leaf to be split 469 @param polys the polygon list on which the split decition is based 470 @param rays ray container on which selection may be based 469 @param data the traversal data holding the polygons and rays which the split decision is based 470 @param frontData the front node traversal data (which may be updated to avoid repcomputations 471 @param backData the front node traversal data (which may be updated to avoid repcomputations 472 @param splitAxis 0 - 2 if axis aligned split, 3 if polygon-aligned split 473 471 474 @note the polygons can be reordered in the process 475 472 476 @returns true if the cost of the split is under maxCostRatio 473 477 … … 567 571 float &position); 568 572 569 /** Selects an axis aligned split plane.570 @Returns true if split is valied571 */572 bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;573 574 573 /** Subdivides the rays into front and back rays according to the split plane. 575 574 … … 649 648 int &contributingSamples); 650 649 651 652 653 654 655 650 656 651 /** Take 3 ray endpoints, where two are minimum and one a maximum … … 701 696 /** Returns estimated memory usage of tree. 702 697 */ 698 float GetMemUsage() const; 703 699 //float GetMemUsage(const VspBspTraversalQueue &tstack) const; 704 float GetMemUsage() const; 705 706 707 700 701 702 703 /////////////////////////////////////////////////////////// 704 protected: 705 708 706 /// Pointer to the root of the tree 709 707 BspNode *mRoot; 710 708 709 /// the pointer to the view cells manager 710 ViewCellsManager *mViewCellsManager; 711 712 /// View cell corresponding to the space outside the valid view space 713 BspViewCell *mOutOfBoundsCell; 714 715 /// the bsp tree statistics 711 716 BspTreeStatistics mBspStats; 712 717 713 /// Strategies for choosing next split plane. 714 enum {NO_STRATEGY = 0, 715 RANDOM_POLYGON = 1, 716 AXIS_ALIGNED = 2, 717 LEAST_RAY_SPLITS = 256, 718 BALANCED_RAYS = 512, 719 PVS = 1024 720 }; 718 /// sorted split candidates used for sweep-heuristics 719 vector<SortableEntry> *mSplitCandidates; 721 720 722 721 /// box around the whole view domain 723 722 AxisAlignedBox3 mBox; 724 723 725 bool mUseCostHeuristics; 724 725 //-- termination critera 726 726 727 727 /// minimal number of rays before subdivision termination … … 737 737 /// minimal accumulated ray length 738 738 float mTermMinAccRayLength; 739 740 //HACK 741 int mTermMinPolygons; 739 /// maximal acceptable cost ratio 740 float mTermMaxCostRatio; 741 /// tolerance value indicating how often the max cost ratio can be failed 742 int mTermMissTolerance; 743 744 745 //-- termination criteria for 746 //-- hybrid stategy where only axis aligned split are used until 747 //-- a certain point and then also polygon aligned split are taken 748 749 /// minimal number of rays where axis aligned split is taken 750 int mTermMinRaysForAxisAligned; 751 /// max ray contribution 752 float mTermMaxRayContriForAxisAligned; 753 /// weight for heuristics evaluation 754 float mAxisAlignedCtDivCi; 755 /// spezifies the split border of the axis aligned split 756 float mAxisAlignedSplitBorder; 757 758 759 //-- global terminatino criteria 742 760 743 761 float mTermMinGlobalCostRatio; 744 762 int mTermGlobalCostMissTolerance; 745 746 763 int mGlobalCostMisses; 747 764 748 bool mUseSplitCostQueue; 749 //-- termination criteria for axis aligned split 750 751 /// minimal number of rays for axis aligned split 752 int mTermMinRaysForAxisAligned; 753 // max ray contribution 754 float mTermMaxRayContriForAxisAligned; 755 756 /// strategy to get the best split plane 757 int mSplitPlaneStrategy; 765 /// maximal number of view cells 766 int mMaxViewCells; 767 /// maximal tree memory 768 float mMaxMemory; 769 /// the tree is out of memory 770 bool mOutOfMemory; 771 772 758 773 /// number of candidates evaluated for the next split plane 759 774 int mMaxPolyCandidates; 760 775 /// number of candidates for split planes evaluated using the rays 761 776 int mMaxRayCandidates; 777 778 779 780 //-- axis aligned split criteria 781 782 /// if only driving axis should be used for choosing the axis-aligned split 783 bool mOnlyDrivingAxis; 784 /// if heuristics should be used to place the split plane of an axis-aligned split 785 bool mUseCostHeuristics; 786 /// if driving axis should taken if max cost is exceeded for 787 /// all evaluated axis aligned split plane candidates 788 bool mUseDrivingAxisIfMaxCostViolated; 789 /// minimal relative position where the split axis can be placed 790 float mMinBand; 791 /// maximal relative position where the split axis can be placed 792 float mMaxBand; 762 793 /// balancing factor for PVS criterium 763 794 float mCtDivCi; 764 765 bool mUseDrivingAxisForMaxCost; 766 //-- axis aligned split criteria 767 float mAxisAlignedCtDivCi; 768 /// spezifies the split border of the axis aligned split 769 float mAxisAlignedSplitBorder; 770 771 /// maximal acceptable cost ratio 772 float mTermMaxCostRatio; 773 /// tolerance value indicating how often the max cost ratio can be failed 774 int mTermMissTolerance; 795 /// if random split axis should be used 796 bool mUseRandomAxis; 797 /// if vsp bsp tree should simulate octree 798 bool mCirculatingAxis; 799 800 801 802 /// priority queue strategy 803 enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED}; 804 /// if we should use breath first priority for the splits 805 int mNodePriorityQueueType; 806 /// if split cost queue should be used to compute next best split 807 bool mUseSplitCostQueue; 808 809 810 811 /// Strategies for choosing next split plane. 812 enum {NO_STRATEGY = 0, 813 RANDOM_POLYGON = 1, 814 AXIS_ALIGNED = 2, 815 LEAST_RAY_SPLITS = 256, 816 BALANCED_RAYS = 512, 817 PVS = 1024 818 }; 819 820 /// strategy to get the best split plane 821 int mSplitPlaneStrategy; 775 822 776 823 //-- factors guiding the split plane heuristics 824 777 825 float mLeastRaySplitsFactor; 778 826 float mBalancedRaysFactor; 779 827 float mPvsFactor; 828 780 829 781 830 /// if area or volume should be used for PVS heuristics … … 787 836 /// normalizes different bsp split plane criteria 788 837 float mCostNormalizer; 789 /// maximal number of view cells790 int mMaxViewCells;791 792 ofstream mSubdivisionStats;793 794 838 // if rays should be stored in leaves 795 839 bool mStoreRays; 796 797 /// if only driving axis should be used for split 798 bool mOnlyDrivingAxis; 799 800 ViewCellsManager *mViewCellsManager; 801 802 vector<SortableEntry> *mSplitCandidates; 803 804 840 /// render cost weight between expected value and variance 805 841 float mRenderCostWeight; 806 /// View cell corresponding to the space outside the valid view space 807 BspViewCell *mOutOfBoundsCell; 808 809 /// maximal tree memory 810 float mMaxMemory; 811 /// the tree is out of memory 812 bool mOutOfMemory; 813 842 843 844 //-- subdivision statistics 845 846 /// subdivision stats output file 847 ofstream mSubdivisionStats; 814 848 float mTotalCost; 815 849 int mTotalPvsSize; 816 850 817 float mMinBand; 818 float mMaxBand; 819 820 //int mSplits; 821 /// subdivision stats output file 822 ofstream mSubdivsionStats; 823 /// if random split axis should be used 824 bool mUseRandomAxis; 851 825 852 /// use polygon split whenever there are polys left 826 853 bool mUsePolygonSplitIfAvailable; … … 829 856 /// number of currenly generated view cells 830 857 int mCreatedViewCells; 831 /// if vsp bsp tree should simulate octree 832 bool mCirculatingAxis; 833 834 /// if we should use breath first priority for the splits 835 int mNodePriorityQueueType; 836 837 bool mEmptyViewCellsMergeAllowed; 838 839 // priority queue strategy 840 enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED}; 858 859 841 860 private: 842 861 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.cpp
r1004 r1006 73 73 74 74 /**************************************************************/ 75 /* class VspKdNode implementation */75 /* class VspKdNode implementation */ 76 76 /**************************************************************/ 77 77 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
r1002 r1006 4 4 5 5 #include "Plane3.h" 6 #include "Vsp BspTree.h"6 #include "VspOspTree.h" 7 7 #include "Mesh.h" 8 8 #include "common.h" … … 25 25 //-- static members 26 26 27 28 int VspBspTree::sFrontId = 0; 29 int VspBspTree::sBackId = 0; 30 int VspBspTree::sFrontAndBackId = 0; 31 32 typedef pair<BspNode *, BspNodeGeometry *> bspNodePair; 27 int VspOspTree::sFrontId = 0; 28 int VspOspTree::sBackId = 0; 29 int VspOspTree::sFrontAndBackId = 0; 30 33 31 34 32 … … 51 49 52 50 /******************************************************************************/ 53 /* class Vsp BspTree implementation */51 /* class VspOspTree implementation */ 54 52 /******************************************************************************/ 55 53 56 54 57 Vsp BspTree::VspBspTree(Environment *env):55 VspOspTree::VspOspTree(): 58 56 mRoot(NULL), 59 mUseAreaForPvs(false),60 mCostNormalizer(Limits::Small),61 mViewCellsManager(NULL),62 57 mOutOfBoundsCell(NULL), 63 58 mStoreRays(false), 64 mRenderCostWeight(0.5),65 59 mUseRandomAxis(false), 66 60 mTimeStamp(1) 67 61 { 68 62 bool randomize = false; 69 env->GetBoolValue("VspBspTree.Construction.randomize", randomize);63 Environment::GetSingleton()->GetBoolValue("VspOspTree.Construction.randomize", randomize); 70 64 if (randomize) 71 65 Randomize(); // initialise random generator for heuristics 72 66 73 67 //-- termination criteria for autopartition 74 env->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth); 75 env->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs); 76 env->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays); 77 env->GetFloatValue("VspBspTree.Termination.minProbability", mTermMinProbability); 78 env->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution); 79 env->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength); 80 env->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio); 81 env->GetIntValue("VspBspTree.Termination.missTolerance", mTermMissTolerance); 82 env->GetIntValue("VspBspTree.Termination.maxViewCells", mMaxViewCells); 68 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.maxDepth", mTermMaxDepth); 69 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.minPvs", mTermMinPvs); 70 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.minRays", mTermMinRays); 71 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.minProbability", mTermMinProbability); 72 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxRayContribution", mTermMaxRayContribution); 73 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxCostRatio", mTermMaxCostRatio); 74 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.missTolerance", mTermMissTolerance); 75 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.maxViewCells", mMaxViewCells); 83 76 84 77 //-- max cost ratio for early tree termination 85 env->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);86 87 env->GetFloatValue("VspBspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);88 env->GetIntValue("VspBspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);78 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.maxCostRatio", mTermMaxCostRatio); 79 80 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio); 81 Environment::GetSingleton()->GetIntValue("VspOspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance); 89 82 90 83 // HACK//mTermMinPolygons = 25; 91 84 92 85 //-- factors for bsp tree split plane heuristics 93 env->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor); 94 env->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi); 95 86 Environment::GetSingleton()->GetFloatValue("VspOspTree.Termination.ct_div_ci", mCtDivCi); 96 87 97 88 //-- partition criteria 98 env->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates); 99 env->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates); 100 env->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy); 101 102 env->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon); 103 env->GetIntValue("VspBspTree.maxTests", mMaxTests); 89 Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.epsilon", mEpsilon); 104 90 105 91 // if only the driving axis is used for axis aligned split 106 env->GetBoolValue("VspBspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 107 108 //-- termination criteria for axis aligned split 109 env->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution", 110 mTermMaxRayContriForAxisAligned); 111 env->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 112 mTermMinRaysForAxisAligned); 113 114 //env->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory); 115 env->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory); 116 117 env->GetFloatValue("VspBspTree.Construction.renderCostWeight", mRenderCostWeight); 118 env->GetBoolValue("VspBspTree.usePolygonSplitIfAvailable", mUsePolygonSplitIfAvailable); 119 120 env->GetBoolValue("VspBspTree.useCostHeuristics", mUseCostHeuristics); 121 env->GetBoolValue("VspBspTree.useSplitCostQueue", mUseSplitCostQueue); 122 env->GetBoolValue("VspBspTree.simulateOctree", mCirculatingAxis); 123 env->GetBoolValue("VspBspTree.useRandomAxis", mUseRandomAxis); 124 env->GetIntValue("VspBspTree.nodePriorityQueueType", mNodePriorityQueueType); 125 126 env->GetBoolValue("ViewCells.PostProcess.emptyViewCellsMerge", mEmptyViewCellsMergeAllowed); 92 Environment::GetSingleton()->GetBoolValue("VspOspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 93 94 //Environment::GetSingleton()->GetFloatValue("VspOspTree.maxTotalMemory", mMaxTotalMemory); 95 Environment::GetSingleton()->GetFloatValue("VspOspTree.maxStaticMemory", mMaxMemory); 96 97 Environment::GetSingleton()->GetBoolValue("VspOspTree.useCostHeuristics", mUseCostHeuristics); 98 Environment::GetSingleton()->GetBoolValue("VspOspTree.simulateOctree", mCirculatingAxis); 99 Environment::GetSingleton()->GetBoolValue("VspOspTree.useRandomAxis", mUseRandomAxis); 100 Environment::GetSingleton()->GetIntValue("VspOspTree.nodePriorityQueueType", mNodePriorityQueueType); 127 101 128 102 char subdivisionStatsLog[100]; 129 env->GetStringValue("VspBspTree.subdivisionStats", subdivisionStatsLog);103 Environment::GetSingleton()->GetStringValue("VspOspTree.subdivisionStats", subdivisionStatsLog); 130 104 mSubdivisionStats.open(subdivisionStatsLog); 131 105 132 env->GetFloatValue("VspBspTree.Construction.minBand", mMinBand);133 env->GetFloatValue("VspBspTree.Construction.maxBand", mMaxBand);134 env->GetBoolValue("VspBspTree.Construction.useDrivingAxisForMaxCost", mUseDrivingAxisForMaxCost);106 Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.minBand", mMinBand); 107 Environment::GetSingleton()->GetFloatValue("VspOspTree.Construction.maxBand", mMaxBand); 108 135 109 136 110 //-- debug output … … 145 119 Debug << "miss tolerance: " << mTermMissTolerance << endl; 146 120 Debug << "max view cells: " << mMaxViewCells << endl; 147 Debug << "max polygon candidates: " << mMaxPolyCandidates << endl;148 //Debug << "max plane candidates: " << mMaxRayCandidates << endl;149 121 Debug << "randomize: " << randomize << endl; 150 122 151 Debug << "using area for pvs: " << mUseAreaForPvs << endl;152 Debug << "render cost weight: " << mRenderCostWeight << endl;153 123 Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl; 154 124 Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl; 155 125 Debug << "only driving axis: " << mOnlyDrivingAxis << endl; 156 126 Debug << "max memory: " << mMaxMemory << endl; 157 Debug << "use poly split if available: " << mUsePolygonSplitIfAvailable << endl;158 127 Debug << "use cost heuristics: " << mUseCostHeuristics << endl; 159 Debug << "use split cost queue: " << mUseSplitCostQueue << endl;160 128 Debug << "subdivision stats log: " << subdivisionStatsLog << endl; 161 129 Debug << "use random axis: " << mUseRandomAxis << endl; 162 130 Debug << "priority queue type: " << mNodePriorityQueueType << endl; 163 Debug << "empty view cells merge: " << mEmptyViewCellsMergeAllowed << endl;164 131 Debug << "circulating axis: " << mCirculatingAxis << endl; 165 132 Debug << "minband: " << mMinBand << endl; 166 133 Debug << "maxband: " << mMaxBand << endl; 167 Debug << "use driving axis for max cost: " << mUseDrivingAxisForMaxCost << endl; 168 169 Debug << "Split plane strategy: "; 170 171 if (mSplitPlaneStrategy & RANDOM_POLYGON) 172 { 173 Debug << "random polygon "; 174 } 175 if (mSplitPlaneStrategy & AXIS_ALIGNED) 176 { 177 Debug << "axis aligned "; 178 } 179 if (mSplitPlaneStrategy & LEAST_RAY_SPLITS) 180 { 181 mCostNormalizer += mLeastRaySplitsFactor; 182 Debug << "least ray splits "; 183 } 184 if (mSplitPlaneStrategy & BALANCED_RAYS) 185 { 186 mCostNormalizer += mBalancedRaysFactor; 187 Debug << "balanced rays "; 188 } 189 if (mSplitPlaneStrategy & PVS) 190 { 191 mCostNormalizer += mPvsFactor; 192 Debug << "pvs"; 193 } 194 134 195 135 196 136 mSplitCandidates = new vector<SortableEntry>; … … 199 139 } 200 140 201 VspBspTree::VspBspTree(): 202 mRoot(NULL), 203 mUseAreaForPvs(false), 204 mCostNormalizer(Limits::Small), 205 mViewCellsManager(NULL), 206 mOutOfBoundsCell(NULL), 207 mStoreRays(false), 208 mRenderCostWeight(0.5), 209 mUseRandomAxis(false), 210 mTimeStamp(1), 211 mEpsilon(1e-6f) 212 { 213 } 214 215 BspViewCell *VspBspTree::GetOutOfBoundsCell() 141 142 BspViewCell *VspOspTree::GetOutOfBoundsCell() 216 143 { 217 144 return mOutOfBoundsCell; … … 219 146 220 147 221 BspViewCell *Vsp BspTree::GetOrCreateOutOfBoundsCell()148 BspViewCell *VspOspTree::GetOrCreateOutOfBoundsCell() 222 149 { 223 150 if (!mOutOfBoundsCell) … … 232 159 233 160 234 const BspTreeStatistics &Vsp BspTree::GetStatistics() const161 const BspTreeStatistics &VspOspTree::GetStatistics() const 235 162 { 236 163 return mBspStats; … … 238 165 239 166 240 Vsp BspTree::~VspBspTree()167 VspOspTree::~VspOspTree() 241 168 { 242 169 DEL_PTR(mRoot); … … 244 171 } 245 172 246 247 int VspBspTree::AddMeshToPolygons(Mesh *mesh, 248 PolygonContainer &polys, 249 MeshInstance *parent) 250 { 251 FaceContainer::const_iterator fi; 252 253 // copy the face data to polygons 254 for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi) 255 { 256 Polygon3 *poly = new Polygon3((*fi), mesh); 257 258 if (poly->Valid(mEpsilon)) 259 { 260 poly->mParent = parent; // set parent intersectable 261 polys.push_back(poly); 262 } 263 else 264 DEL_PTR(poly); 265 } 266 return (int)mesh->mFaces.size(); 267 } 268 269 270 int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 271 PolygonContainer &polys, 272 int maxObjects) 273 { 274 int limit = (maxObjects > 0) ? 275 Min((int)viewCells.size(), maxObjects) : (int)viewCells.size(); 276 277 int polysSize = 0; 278 279 for (int i = 0; i < limit; ++ i) 280 { 281 if (viewCells[i]->GetMesh()) // copy the mesh data to polygons 282 { 283 mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb 284 polysSize += 285 AddMeshToPolygons(viewCells[i]->GetMesh(), 286 polys, 287 viewCells[i]); 288 } 289 } 290 291 return polysSize; 292 } 293 294 295 int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, 296 PolygonContainer &polys, 297 int maxObjects) 298 { 299 int limit = (maxObjects > 0) ? 300 Min((int)objects.size(), maxObjects) : (int)objects.size(); 301 302 for (int i = 0; i < limit; ++i) 303 { 304 Intersectable *object = objects[i];//*it; 305 Mesh *mesh = NULL; 306 307 switch (object->Type()) // extract the meshes 308 { 309 case Intersectable::MESH_INSTANCE: 310 mesh = dynamic_cast<MeshInstance *>(object)->GetMesh(); 311 break; 312 case Intersectable::VIEW_CELL: 313 mesh = dynamic_cast<ViewCell *>(object)->GetMesh(); 314 break; 315 case Intersectable::TRANSFORMED_MESH_INSTANCE: 316 { 317 TransformedMeshInstance *mi = dynamic_cast<TransformedMeshInstance *>(object); 318 319 if (!mi->GetMesh()) 320 break; 321 322 mesh = new Mesh(*mi->GetMesh()); 323 324 Matrix4x4 m; 325 mi->GetWorldTransform(m); 326 327 mesh->ApplyTransformation(m); 328 329 break; 330 } 331 default: 332 Debug << "intersectable type not supported" << endl; 333 break; 334 } 335 336 if (mesh) // copy the mesh data to polygons 337 { 338 mBox.Include(object->GetBox()); // add to BSP tree aabb 339 AddMeshToPolygons(mesh, polys, NULL); 340 341 // cleanup 342 if (object->Type() == Intersectable::TRANSFORMED_MESH_INSTANCE) 343 DEL_PTR(mesh); 344 } 345 } 346 347 return (int)polys.size(); 348 } 349 350 351 void VspBspTree::Construct(const VssRayContainer &sampleRays, 173 void VspOspTree::Construct(const VssRayContainer &sampleRays, 352 174 AxisAlignedBox3 *forcedBoundingBox) 353 175 { … … 371 193 int numObj = 0; 372 194 373 //-- extract polygons intersected by the rays374 for (rit = sampleRays.begin(); rit != rit_end; ++ rit)375 {376 VssRay *ray = *rit;377 378 if ((mBox.IsInside(ray->mTermination) || !forcedBoundingBox) &&379 ray->mTerminationObject &&380 !ray->mTerminationObject->Mailed())381 {382 ray->mTerminationObject->Mail();383 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject);384 AddMeshToPolygons(obj->GetMesh(), polys, obj);385 ++ numObj;386 387 //-- compute bounding box388 if (!forcedBoundingBox)389 mBox.Include(ray->mTermination);390 }391 392 if ((mBox.IsInside(ray->mOrigin) || !forcedBoundingBox) &&393 ray->mOriginObject &&394 !ray->mOriginObject->Mailed())395 {396 ray->mOriginObject->Mail();397 MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject);398 AddMeshToPolygons(obj->GetMesh(), polys, obj);399 ++ numObj;400 401 //-- compute bounding box402 if (!forcedBoundingBox)403 mBox.Include(ray->mOrigin);404 }405 }406 407 Debug << "maximal pvs (i.e., pvs still considered as valid) : "408 << mViewCellsManager->GetMaxPvsSize() << endl;409 410 195 //-- store rays 411 196 for (rit = sampleRays.begin(); rit != rit_end; ++ rit) … … 430 215 } 431 216 432 // normalize 433 if (mUseAreaForPvs) 434 mTermMinProbability *= mBox.SurfaceArea(); 435 else 436 mTermMinProbability *= mBox.GetVolume(); 437 438 // throw out unnecessary polygons 439 PreprocessPolygons(polys); 440 441 mBspStats.polys = (int)polys.size(); 217 mTermMinProbability *= mBox.GetVolume(); 218 442 219 mGlobalCostMisses = 0; 443 220 444 221 cout << "finished" << endl; 445 222 446 Debug << "\nPolygon extraction: " << (int)polys.size() << " polys extracted from "447 << (int)sampleRays.size() << " rays in "448 << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl << endl;449 450 223 // use split cost priority queue 451 if (mUseSplitCostQueue) 452 { 453 ConstructWithSplitQueue(polys, rays); 454 } 455 else 456 { 457 Construct(polys, rays); 458 } 459 460 // clean up polygons 461 CLEAR_CONTAINER(polys); 224 Construct(rays); 462 225 } 463 226 464 227 465 228 // TODO: return memory usage in MB 466 float Vsp BspTree::GetMemUsage() const229 float VspOspTree::GetMemUsage() const 467 230 { 468 231 return (float) 469 (sizeof(Vsp BspTree) +232 (sizeof(VspOspTree) + 470 233 mBspStats.Leaves() * sizeof(BspLeaf) + 471 234 mCreatedViewCells * sizeof(BspViewCell) + … … 476 239 477 240 478 479 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 480 { 481 VspBspTraversalQueue tQueue; 241 void VspOspTree::Construct(RayInfoContainer *rays) 242 { 243 VspOspSplitQueue tQueue; 482 244 483 245 mRoot = new BspLeaf(); 484 246 485 // constrruct root node geometry 486 BspNodeGeometry *geom = new BspNodeGeometry(); 487 ConstructGeometry(mRoot, *geom); 488 489 const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(); 490 491 VspBspTraversalData tData(mRoot, 492 new PolygonContainer(polys), 247 const float prop = mBox.GetVolume(); 248 249 VspOspTraversalData tData(mRoot, 493 250 0, 494 251 rays, 495 252 ComputePvsSize(*rays), 496 253 prop, 497 geom); 498 499 EvalPriority(tData); 500 501 502 // first node is kd node, i.e. an axis aligned box 503 if (1) 504 tData.mIsKdNode = true; 505 else 506 tData.mIsKdNode = false; 507 508 tQueue.push(tData); 509 510 511 mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume(); 512 mTotalPvsSize = tData.mPvs; 513 514 mSubdivisionStats 515 << "#ViewCells\n1" << endl 516 << "#RenderCostDecrease\n0" << endl 517 << "#TotalRenderCost\n" << mTotalCost << endl 518 << "#AvgRenderCost\n" << mTotalPvsSize << endl; 519 520 Debug << "total cost: " << mTotalCost << endl; 521 522 523 mBspStats.Start(); 524 cout << "Constructing vsp bsp tree ... \n"; 525 526 long startTime = GetTime(); 527 int nLeaves = 500; 528 int nViewCells = 500; 529 530 // used for intermediate time measurements and progress 531 long interTime = GetTime(); 532 533 mOutOfMemory = false; 534 535 mCreatedViewCells = 0; 536 537 while (!tQueue.empty()) 538 { 539 tData = tQueue.top(); 540 tQueue.pop(); 541 542 if (0 && !mOutOfMemory) 543 { 544 float mem = GetMemUsage(); 545 546 if (mem > mMaxMemory) 547 { 548 mOutOfMemory = true; 549 Debug << "memory limit reached: " << mem << endl; 550 } 551 } 552 553 // subdivide leaf node 554 BspNode *r = Subdivide(tQueue, tData); 555 556 if (r == mRoot) 557 Debug << "VSP BSP tree construction time spent at root: " 558 << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; 559 560 if (mBspStats.Leaves() >= nLeaves) 561 { 562 nLeaves += 500; 563 564 cout << "leaves=" << mBspStats.Leaves() << endl; 565 Debug << "needed " 566 << TimeDiff(interTime, GetTime())*1e-3 567 << " secs to create 500 view cells" << endl; 568 interTime = GetTime(); 569 } 570 571 if (mCreatedViewCells >= nViewCells) 572 { 573 nViewCells += 500; 574 575 cout << "generated " << mCreatedViewCells << " viewcells" << endl; 576 } 577 } 578 579 Debug << "Used Memory: " << GetMemUsage() << " MB" << endl << endl; 580 cout << "finished\n"; 581 582 mBspStats.Stop(); 583 } 584 585 586 587 void VspBspTree::ConstructWithSplitQueue(const PolygonContainer &polys, 588 RayInfoContainer *rays) 589 { 590 VspBspSplitQueue tQueue; 591 592 mRoot = new BspLeaf(); 593 594 // constrruct root node geometry 595 BspNodeGeometry *geom = new BspNodeGeometry(); 596 ConstructGeometry(mRoot, *geom); 597 598 const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(); 599 600 VspBspTraversalData tData(mRoot, 601 new PolygonContainer(polys), 602 0, 603 rays, 604 ComputePvsSize(*rays), 605 prop, 606 geom); 254 mBox); 607 255 608 256 609 257 // compute first split candidate 610 Vsp BspSplitCandidate splitCandidate;258 VspOspSplitCandidate splitCandidate; 611 259 EvalSplitCandidate(tData, splitCandidate); 612 260 … … 697 345 698 346 699 bool Vsp BspTree::LocalTerminationCriteriaMet(const VspBspTraversalData &data) const347 bool VspOspTree::LocalTerminationCriteriaMet(const VspOspTraversalData &data) const 700 348 { 701 349 return … … 708 356 709 357 710 bool Vsp BspTree::GlobalTerminationCriteriaMet(const VspBspTraversalData &data) const358 bool VspOspTree::GlobalTerminationCriteriaMet(const VspOspTraversalData &data) const 711 359 { 712 360 return … … 718 366 719 367 720 721 BspNode *VspBspTree::Subdivide(VspBspTraversalQueue &tQueue,722 VspBspTraversalData &tData)723 {724 BspNode *newNode = tData.mNode;725 726 if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData))727 {728 PolygonContainer coincident;729 730 VspBspTraversalData tFrontData;731 VspBspTraversalData tBackData;732 733 // create new interior node and two leaf nodes734 // or return leaf as it is (if maxCostRatio missed)735 int splitAxis;736 bool splitFurther = true;737 int maxCostMisses = tData.mMaxCostMisses;738 739 Plane3 splitPlane;740 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);741 742 // choose next split plane743 if (!SelectPlane(splitPlane, leaf, tData, tFrontData, tBackData, splitAxis))744 {745 ++ maxCostMisses;746 747 if (maxCostMisses > mTermMissTolerance)748 {749 // terminate branch because of max cost750 ++ mBspStats.maxCostNodes;751 splitFurther = false;752 }753 }754 755 // if this a valid split => subdivide this node further756 if (splitFurther) //-- continue subdivision757 {758 newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData, coincident);759 760 if (splitAxis < 3)761 ++ mBspStats.splits[splitAxis];762 else763 ++ mBspStats.polySplits;764 765 // if it was a kd node (i.e., a box) and the split axis is axis aligned, it is still a kd node766 tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && (splitAxis < 3));767 tFrontData.mAxis = tBackData.mAxis = splitAxis;768 769 // how often was max cost ratio missed in this branch?770 tFrontData.mMaxCostMisses = maxCostMisses;771 tBackData.mMaxCostMisses = maxCostMisses;772 773 EvalPriority(tFrontData);774 EvalPriority(tBackData);775 776 // evaluate subdivision stats777 if (1)778 {779 float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;780 float cBack = (float)tBackData.mPvs * tBackData.mProbability;781 float cData = (float)tData.mPvs * tData.mProbability;;782 783 float costDecr = (cFront + cBack - cData) / mBox.GetVolume();784 785 mTotalCost += costDecr;786 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;787 788 mSubdivisionStats789 << "#ViewCells\n" << mBspStats.Leaves() << endl790 << "#RenderCostDecrease\n" << -costDecr << endl791 << "#TotalRenderCost\n" << mTotalCost << endl792 << "#AvgRenderCost\n" << (float)mTotalPvsSize / (float)mBspStats.Leaves() << endl;793 }794 795 // push the children on the stack796 tQueue.push(tFrontData);797 tQueue.push(tBackData);798 799 // delete old leaf node800 DEL_PTR(tData.mNode);801 }802 }803 804 //-- terminate traversal and create new view cell805 if (newNode->IsLeaf())806 {807 BspLeaf *leaf = dynamic_cast<BspLeaf *>(newNode);808 BspViewCell *viewCell = new BspViewCell();809 810 leaf->SetViewCell(viewCell);811 812 //-- update pvs813 int conSamp = 0;814 float sampCon = 0.0f;815 AddToPvs(leaf, *tData.mRays, sampCon, conSamp);816 817 // update scalar pvs size lookup818 mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().GetSize());819 820 821 mBspStats.contributingSamples += conSamp;822 mBspStats.sampleContributions +=(int) sampCon;823 824 //-- store additional info825 if (mStoreRays)826 {827 RayInfoContainer::const_iterator it, it_end = tData.mRays->end();828 for (it = tData.mRays->begin(); it != it_end; ++ it)829 {830 (*it).mRay->Ref();831 leaf->mVssRays.push_back((*it).mRay);832 }833 }834 835 // should I check here?836 if (0 && !mViewCellsManager->CheckValidity(viewCell, 0, mViewCellsManager->GetMaxPvsSize()))837 {838 viewCell->SetValid(false);839 leaf->SetTreeValid(false);840 PropagateUpValidity(leaf);841 842 ++ mBspStats.invalidLeaves;843 }844 845 viewCell->mLeaf = leaf;846 847 if (mUseAreaForPvs)848 viewCell->SetArea(tData.mProbability);849 else850 viewCell->SetVolume(tData.mProbability);851 852 leaf->mProbability = tData.mProbability;853 854 EvaluateLeafStats(tData);855 }856 857 //-- cleanup858 tData.Clear();859 860 return newNode;861 }862 863 368 // subdivide using a split plane queue 864 BspNode *Vsp BspTree::Subdivide(VspBspSplitQueue &tQueue,865 Vsp BspSplitCandidate &splitCandidate)866 { 867 Vsp BspTraversalData &tData = splitCandidate.mParentData;369 BspNode *VspOspTree::Subdivide(VspOspSplitQueue &tQueue, 370 VspOspSplitCandidate &splitCandidate) 371 { 372 VspOspTraversalData &tData = splitCandidate.mParentData; 868 373 869 374 BspNode *newNode = tData.mNode; … … 871 376 if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData)) 872 377 { 873 PolygonContainer coincident; 874 875 VspBspTraversalData tFrontData; 876 VspBspTraversalData tBackData; 378 VspOspTraversalData tFrontData; 379 VspOspTraversalData tBackData; 877 380 878 381 //-- continue subdivision 879 382 880 383 // create new interior node and two leaf node 881 const Plane3 splitPlane = splitCandidate.mSplitPlane; 384 //TODO 385 const Plane3 splitPlane;// = splitCandidate.mSplitPlane; 882 386 883 newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData, coincident); 884 885 const int splitAxis = splitCandidate.mSplitAxis; 387 newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData); 388 886 389 const int maxCostMisses = splitCandidate.mMaxCostMisses; 887 390 888 if (splitAxis < 3)889 ++ mBspStats.splits[splitAxis];890 else891 ++ mBspStats.polySplits;892 893 tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && (splitAxis < 3));894 tFrontData.mAxis = tBackData.mAxis = splitAxis;895 391 896 392 // how often was max cost ratio missed in this branch? … … 922 418 923 419 //-- push the new split candidates on the stack 924 Vsp BspSplitCandidate frontCandidate;925 Vsp BspSplitCandidate backCandidate;420 VspOspSplitCandidate frontCandidate; 421 VspOspSplitCandidate backCandidate; 926 422 927 423 EvalSplitCandidate(tFrontData, frontCandidate); … … 969 465 viewCell->mLeaf = leaf; 970 466 971 if (mUseAreaForPvs) 972 viewCell->SetArea(tData.mProbability); 973 else 974 viewCell->SetVolume(tData.mProbability); 975 467 viewCell->SetVolume(tData.mProbability); 976 468 leaf->mProbability = tData.mProbability; 977 469 … … 986 478 987 479 988 void VspBspTree::EvalPriority(VspBspTraversalData &tData) const 989 { 990 switch (mNodePriorityQueueType) 991 { 992 case BREATH_FIRST: 993 tData.mPriority = (float)-tData.mDepth; 994 break; 995 case DEPTH_FIRST: 996 tData.mPriority = (float)tData.mDepth; 997 break; 998 default: 999 tData.mPriority = tData.mPvs * tData.mProbability; 1000 //Debug << "priority: " << tData.mPriority << endl; 1001 break; 1002 } 1003 } 1004 1005 1006 void VspBspTree::EvalSplitCandidate(VspBspTraversalData &tData, 1007 VspBspSplitCandidate &splitData) 1008 { 1009 VspBspTraversalData frontData; 1010 VspBspTraversalData backData; 480 void VspOspTree::EvalSplitCandidate(VspOspTraversalData &tData, 481 VspOspSplitCandidate &splitData) 482 { 483 VspOspTraversalData frontData; 484 VspOspTraversalData backData; 1011 485 1012 486 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); 1013 487 1014 488 // compute locally best split plane 1015 bool success = SelectPlane(splitData.mSplitPlane, leaf, tData, 1016 frontData, backData, splitData.mSplitAxis); 1017 1018 // TODO: reuse 1019 DEL_PTR(frontData.mGeometry); 1020 DEL_PTR(backData.mGeometry); 1021 489 // TODO 490 const bool success =0;/// SelectPlane(splitData.mSplitPlane, tData, 491 // frontData, backData); 492 //TODO 1022 493 // compute global decrease in render cost 1023 splitData.mRenderCost = EvalRenderCostDecrease(splitData.mSplitPlane, tData);494 splitData.mRenderCost = 0;//EvalRenderCostDecrease(splitData.mSplitPlane, tData); 1024 495 splitData.mParentData = tData; 1025 496 splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1; … … 1027 498 1028 499 1029 BspInterior *VspBspTree::SubdivideNode(const Plane3 &splitPlane, 1030 VspBspTraversalData &tData, 1031 VspBspTraversalData &frontData, 1032 VspBspTraversalData &backData, 1033 PolygonContainer &coincident) 500 BspInterior *VspOspTree::SubdivideNode(const Plane3 &splitPlane, 501 VspOspTraversalData &tData, 502 VspOspTraversalData &frontData, 503 VspOspTraversalData &backData) 1034 504 { 1035 505 BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode); … … 1037 507 //-- the front and back traversal data is filled with the new values 1038 508 frontData.mDepth = tData.mDepth + 1; 1039 frontData.mPolygons = new PolygonContainer();1040 509 frontData.mRays = new RayInfoContainer(); 1041 510 1042 511 backData.mDepth = tData.mDepth + 1; 1043 backData.mPolygons = new PolygonContainer();1044 512 backData.mRays = new RayInfoContainer(); 1045 513 … … 1059 527 1060 528 // if geometry was not already computed 1061 if (!frontData.mGeometry && !backData.mGeometry) 1062 { 1063 frontData.mGeometry = new BspNodeGeometry(); 1064 backData.mGeometry = new BspNodeGeometry(); 1065 1066 tData.mGeometry->SplitGeometry(*frontData.mGeometry, 1067 *backData.mGeometry, 1068 splitPlane, 1069 mBox, 1070 //0.0f); 1071 mEpsilon); 1072 1073 if (mUseAreaForPvs) 1074 { 1075 frontData.mProbability = frontData.mGeometry->GetArea(); 1076 backData.mProbability = backData.mGeometry->GetArea(); 1077 } 1078 else 1079 { 1080 frontData.mProbability = frontData.mGeometry->GetVolume(); 1081 backData.mProbability = tData.mProbability - frontData.mProbability; 1082 1083 // should never come here: wrong volume !!! 1084 if (0) 1085 { 1086 if (frontData.mProbability < -0.00001) 1087 Debug << "fatal error f: " << frontData.mProbability << endl; 1088 if (backData.mProbability < -0.00001) 1089 Debug << "fatal error b: " << backData.mProbability << endl; 1090 1091 // clamp because of precision issues 1092 if (frontData.mProbability < 0) frontData.mProbability = 0; 1093 if (backData.mProbability < 0) backData.mProbability = 0; 1094 } 1095 } 1096 } 1097 1098 1099 // subdivide polygons 1100 SplitPolygons(splitPlane, 1101 *tData.mPolygons, 1102 *frontData.mPolygons, 1103 *backData.mPolygons, 1104 coincident); 1105 1106 1107 1108 /////////////////////////////////////// 529 // TODO 530 531 #if TODO 532 tData.mBoundingBox.Split(splitPlane.mAxis, splitPlane.mPosition, 533 frontData.mBoundingBox, backData.mBoundingBox); 534 535 #endif 536 537 frontData.mProbability = frontData.mBoundingBox.GetVolume(); 538 backData.mProbability = tData.mProbability - frontData.mProbability; 539 540 541 /////////////////////////////////////////// 1109 542 // subdivide further 1110 543 … … 1149 582 interior->mTimeStamp = mTimeStamp ++; 1150 583 1151 1152 //DEL_PTR(leaf);1153 584 return interior; 1154 585 } 1155 586 1156 587 1157 void Vsp BspTree::AddToPvs(BspLeaf *leaf,588 void VspOspTree::AddToPvs(BspLeaf *leaf, 1158 589 const RayInfoContainer &rays, 1159 590 float &sampleContributions, … … 1200 631 1201 632 1202 void Vsp BspTree::SortSplitCandidates(const RayInfoContainer &rays,633 void VspOspTree::SortSplitCandidates(const RayInfoContainer &rays, 1203 634 const int axis, 1204 635 float minBand, … … 1251 682 1252 683 1253 float Vsp BspTree::BestCostRatioHeuristics(const RayInfoContainer &rays,684 float VspOspTree::BestCostRatioHeuristics(const RayInfoContainer &rays, 1254 685 const AxisAlignedBox3 &box, 1255 686 const int pvsSize, … … 1413 844 if (splitPlaneFound) 1414 845 { 1415 ratio = mPvsFactor *newRenderCost / (oldRenderCost + Limits::Small);846 ratio = newRenderCost / (oldRenderCost + Limits::Small); 1416 847 } 1417 848 //if (axis != 1) … … 1423 854 1424 855 1425 float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 1426 const VspBspTraversalData &tData, 1427 int &axis, 1428 BspNodeGeometry **frontGeom, 1429 BspNodeGeometry **backGeom, 1430 float &pFront, 1431 float &pBack, 1432 const bool isKdNode) 856 float VspOspTree::SelectPlane(const VspOspTraversalData &tData, 857 AxisAlignedPlane &plane, 858 float &pFront, 859 float &pBack) 1433 860 { 1434 861 float nPosition[3]; … … 1437 864 float nProbBack[3]; 1438 865 1439 BspNodeGeometry *nFrontGeom[3];1440 BspNodeGeometry *nBackGeom[3];1441 1442 // set to NULL, so I can find out which gemetry was stored1443 for (int i = 0; i < 3; ++ i)1444 {1445 nFrontGeom[i] = NULL;1446 nBackGeom[i] = NULL;1447 }1448 1449 866 // create bounding box of node geometry 1450 AxisAlignedBox3 box; 1451 1452 //TODO: for kd split geometry already is box => only take minmax vertices 1453 if (1) 1454 { 1455 // get bounding box from geometry 1456 tData.mGeometry->GetBoundingBox(box); 1457 } 1458 else 1459 { 1460 box.Initialize(); 1461 RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end(); 1462 1463 for(ri = tData.mRays->begin(); ri < ri_end; ++ ri) 1464 box.Include((*ri).ExtrapTermination()); 1465 } 1466 867 AxisAlignedBox3 box = tData.mBoundingBox; 868 1467 869 int sAxis = 0; 1468 int bestAxis; 1469 1470 // if max cost ratio is exceeded, take split along longest axis instead 1471 const float maxCostRatioForArbitraryAxis = 0.9f; 1472 1473 if (mUseDrivingAxisForMaxCost) 1474 bestAxis = box.Size().DrivingAxis(); 1475 else 1476 bestAxis = -1; 870 int bestAxis = -1; 1477 871 1478 872 #if 0 … … 1493 887 sAxis = box.Size().DrivingAxis(); 1494 888 1495 1496 //Debug << "use special axis: " << useSpecialAxis << endl; 1497 //Debug << "axis: " << sAxis << " drivingaxis: " << box.Size().DrivingAxis(); 1498 1499 for (axis = 0; axis < 3 ; ++ axis) 889 890 for (int axis = 0; axis < 3 ; ++ axis) 1500 891 { 1501 892 if (!useSpecialAxis || (axis == sAxis)) … … 1512 903 nPosition[axis]); 1513 904 } 1514 1515 //-- split plane position is spatial median 1516 1517 1518 // also use median split if cost ratio very low as 1519 // there are not enough visibility cues 1520 //if (!mUseCostHeuristics || (nCostRatio[axis] > maxCostRatioForHeur)) 1521 else 1522 { 1523 905 else //-- split plane position is spatial median 906 { 1524 907 nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 1525 Vector3 normal(0,0,0); normal[axis] = 1.0f; 1526 1527 // allows faster split because we have axis aligned kd tree boxes 1528 if (isKdNode) 1529 { 1530 nCostRatio[axis] = EvalAxisAlignedSplitCost(tData, 1531 box, 1532 axis, 1533 nPosition[axis], 1534 nProbFront[axis], 1535 nProbBack[axis]); 1536 1537 Vector3 pos; 1538 1539 // create back geometry from box 1540 // NOTE: the geometry is saved when possible 1541 pos = box.Max(); pos[axis] = nPosition[axis]; 1542 AxisAlignedBox3 bBox(box.Min(), pos); 1543 PolygonContainer fPolys; 1544 bBox.ExtractPolys(fPolys); 1545 1546 nBackGeom[axis] = new BspNodeGeometry(fPolys); 1547 1548 //-- create front geometry from box 1549 pos = box.Min(); pos[axis] = nPosition[axis]; 1550 AxisAlignedBox3 fBox(pos, box.Max()); 1551 1552 PolygonContainer bPolys; 1553 fBox.ExtractPolys(bPolys); 1554 nFrontGeom[axis] = new BspNodeGeometry(bPolys); 1555 } 1556 else 1557 { 1558 nFrontGeom[axis] = new BspNodeGeometry(); 1559 nBackGeom[axis] = new BspNodeGeometry(); 1560 1561 nCostRatio[axis] = 1562 EvalSplitPlaneCost(Plane3(normal, nPosition[axis]), 1563 tData, *nFrontGeom[axis], *nBackGeom[axis], 1564 nProbFront[axis], nProbBack[axis]); 1565 } 908 909 nCostRatio[axis] = EvalSplitCost(tData, 910 box, 911 axis, 912 nPosition[axis], 913 nProbFront[axis], 914 nProbBack[axis]); 1566 915 } 1567 916 1568 1569 if (mUseDrivingAxisForMaxCost) 1570 { 1571 // we take longest axis split if cost ratio exceeds threshold 1572 if (nCostRatio[axis] < min(maxCostRatioForArbitraryAxis, nCostRatio[bestAxis])) 1573 { 1574 bestAxis = axis; 1575 } 1576 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 1577 Debug << "taking split along longest axis (" << bestAxis << ") instead of (" << axis << ")" << endl; 1578 1579 } 1580 else 1581 { 1582 if (bestAxis == -1) 1583 { 1584 bestAxis = axis; 1585 } 1586 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 1587 { 1588 bestAxis = axis; 1589 } 917 if (bestAxis == -1) 918 { 919 bestAxis = axis; 920 } 921 else if (nCostRatio[axis] < nCostRatio[bestAxis]) 922 { 923 bestAxis = axis; 1590 924 } 1591 925 } … … 1593 927 1594 928 //-- assign values 1595 axis = bestAxis;929 plane.mAxis = bestAxis; 1596 930 pFront = nProbFront[bestAxis]; 1597 931 pBack = nProbBack[bestAxis]; 1598 932 1599 // assign best split nodes geometry 1600 *frontGeom = nFrontGeom[bestAxis]; 1601 *backGeom = nBackGeom[bestAxis]; 1602 1603 // and delete other geometry 1604 DEL_PTR(nFrontGeom[(bestAxis + 1) % 3]); 1605 DEL_PTR(nBackGeom[(bestAxis + 2) % 3]); 1606 1607 //-- split plane 1608 Vector3 normal(0,0,0); normal[bestAxis] = 1; 1609 plane = Plane3(normal, nPosition[bestAxis]); 1610 1611 //Debug << "best axis: " << bestAxis << " pos " << nPosition[bestAxis] << endl; 1612 //Debug << "!!!!!!!!!!!!!!" << endl; 933 //-- split plane position 934 plane.mPosition = nPosition[bestAxis]; 935 1613 936 return nCostRatio[bestAxis]; 1614 937 } 1615 938 1616 939 1617 bool VspBspTree::SelectPlane(Plane3 &bestPlane, 1618 BspLeaf *leaf, 1619 VspBspTraversalData &data, 1620 VspBspTraversalData &frontData, 1621 VspBspTraversalData &backData, 1622 int &splitAxis) 1623 { 1624 // HACK matt: subdivide regularily to certain depth 1625 if (data.mDepth < 0) 1626 { 1627 cout << "d: " << data.mDepth << endl; 1628 // return axis aligned split 1629 AxisAlignedBox3 box; 1630 box.Initialize(); 1631 1632 // create bounding box of region 1633 data.mGeometry->GetBoundingBox(box); 1634 1635 const int axis = box.Size().DrivingAxis(); 1636 const Vector3 position = (box.Min()[axis] + box.Max()[axis]) * 0.5f; 1637 1638 Vector3 norm(0,0,0); norm[axis] = 1.0f; 1639 bestPlane = Plane3(norm, position); 1640 splitAxis = axis; 1641 return true; 1642 } 1643 1644 // simplest strategy: just take next polygon 1645 if (mSplitPlaneStrategy & RANDOM_POLYGON) 1646 { 1647 if (!data.mPolygons->empty()) 1648 { 1649 const int randIdx = 1650 (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1)); 1651 Polygon3 *nextPoly = (*data.mPolygons)[randIdx]; 1652 1653 bestPlane = nextPoly->GetSupportingPlane(); 1654 return true; 1655 } 1656 } 1657 1658 //-- use heuristics to find appropriate plane 1659 1660 // intermediate plane 1661 Plane3 plane; 1662 float lowestCost = MAX_FLOAT; 1663 1664 // decides if the first few splits should be only axisAligned 1665 const bool onlyAxisAligned = 1666 (mSplitPlaneStrategy & AXIS_ALIGNED) && 1667 ((int)data.mRays->size() > mTermMinRaysForAxisAligned) && 1668 ((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned); 1669 1670 const int limit = onlyAxisAligned ? 0 : 1671 Min((int)data.mPolygons->size(), mMaxPolyCandidates); 1672 1673 float candidateCost; 1674 1675 int maxIdx = (int)data.mPolygons->size(); 1676 1677 for (int i = 0; i < limit; ++ i) 1678 { 1679 // the already taken candidates are stored behind maxIdx 1680 // => assure that no index is taken twice 1681 const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx)); 1682 Polygon3 *poly = (*data.mPolygons)[candidateIdx]; 1683 1684 // swap candidate to the end to avoid testing same plane 1685 std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]); 1686 //Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)]; 1687 1688 // evaluate current candidate 1689 BspNodeGeometry fGeom, bGeom; 1690 float fArea, bArea; 1691 plane = poly->GetSupportingPlane(); 1692 candidateCost = EvalSplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea); 1693 1694 if (candidateCost < lowestCost) 1695 { 1696 bestPlane = plane; 1697 lowestCost = candidateCost; 1698 } 1699 } 1700 1701 //-- evaluate axis aligned splits 1702 int axis; 1703 BspNodeGeometry *fGeom, *bGeom; 1704 float pFront, pBack; 1705 1706 candidateCost = 99999999.0f; 1707 1708 // option: axis aligned split only if no polygon available 1709 if (!mUsePolygonSplitIfAvailable || data.mPolygons->empty()) 1710 { 1711 candidateCost = SelectAxisAlignedPlane(plane, 1712 data, 1713 axis, 1714 &fGeom, 1715 &bGeom, 1716 pFront, 1717 pBack, 1718 data.mIsKdNode); 1719 } 1720 1721 splitAxis = 3; 1722 1723 if (candidateCost < lowestCost) 1724 { 1725 bestPlane = plane; 1726 lowestCost = candidateCost; 1727 splitAxis = axis; 1728 1729 // assign already computed values 1730 // we can do this because we always save the 1731 // computed values from the axis aligned splits 1732 1733 if (fGeom && bGeom) 1734 { 1735 frontData.mGeometry = fGeom; 1736 backData.mGeometry = bGeom; 1737 1738 frontData.mProbability = pFront; 1739 backData.mProbability = pBack; 1740 } 1741 } 1742 else 1743 { 1744 DEL_PTR(fGeom); 1745 DEL_PTR(bGeom); 1746 } 1747 1748 #ifdef _DEBUG 1749 Debug << "plane lowest cost: " << lowestCost << endl; 1750 #endif 1751 1752 // exeeded relative max cost ratio 1753 if (lowestCost > mTermMaxCostRatio) 1754 { 1755 return false; 1756 } 1757 1758 return true; 1759 } 1760 1761 1762 Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const 1763 { 1764 const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 1765 1766 const Vector3 minPt = rays[candidateIdx].ExtrapOrigin(); 1767 const Vector3 maxPt = rays[candidateIdx].ExtrapTermination(); 1768 1769 const Vector3 pt = (maxPt + minPt) * 0.5; 1770 const Vector3 normal = Normalize(rays[candidateIdx].mRay->GetDir()); 1771 1772 return Plane3(normal, pt); 1773 } 1774 1775 1776 Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const 1777 { 1778 Vector3 pt[3]; 1779 1780 int idx[3]; 1781 int cmaxT = 0; 1782 int cminT = 0; 1783 bool chooseMin = false; 1784 1785 for (int j = 0; j < 3; ++ j) 1786 { 1787 idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1)); 1788 1789 if (idx[j] >= (int)rays.size()) 1790 { 1791 idx[j] -= (int)rays.size(); 1792 1793 chooseMin = (cminT < 2); 1794 } 1795 else 1796 chooseMin = (cmaxT < 2); 1797 1798 RayInfo rayInf = rays[idx[j]]; 1799 pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination(); 1800 } 1801 1802 return Plane3(pt[0], pt[1], pt[2]); 1803 } 1804 1805 1806 Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const 1807 { 1808 Vector3 pt[3]; 1809 1810 int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 1811 int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1)); 1812 1813 // check if rays different 1814 if (idx1 == idx2) 1815 idx2 = (idx2 + 1) % (int)rays.size(); 1816 1817 const RayInfo ray1 = rays[idx1]; 1818 const RayInfo ray2 = rays[idx2]; 1819 1820 // normal vector of the plane parallel to both lines 1821 const Vector3 norm = Normalize(CrossProd(ray1.mRay->GetDir(), ray2.mRay->GetDir())); 1822 1823 // vector from line 1 to line 2 1824 const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin(); 1825 1826 // project vector on normal to get distance 1827 const float dist = DotProd(vd, norm); 1828 1829 // point on plane lies halfway between the two planes 1830 const Vector3 planePt = ray1.ExtrapOrigin() + norm * dist * 0.5; 1831 1832 return Plane3(norm, planePt); 1833 } 1834 1835 1836 inline void VspBspTree::GenerateUniqueIdsForPvs() 940 inline void VspOspTree::GenerateUniqueIdsForPvs() 1837 941 { 1838 942 Intersectable::NewMail(); sBackId = Intersectable::sMailId; … … 1842 946 1843 947 1844 float Vsp BspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane,1845 const Vsp BspTraversalData &data) const948 float VspOspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane, 949 const VspOspTraversalData &data) const 1846 950 { 1847 951 float pvsFront = 0; … … 1874 978 BspNodeGeometry geomFront; 1875 979 BspNodeGeometry geomBack; 1876 1877 // construct child geometry with regard to the candidate split plane 1878 data.mGeometry->SplitGeometry(geomFront, 1879 geomBack, 1880 candidatePlane, 1881 mBox, 1882 //0.0f); 1883 mEpsilon); 1884 1885 if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 1886 { 1887 pFront = geomFront.GetVolume(); 1888 pBack = pOverall - pFront; 1889 1890 // something is wrong with the volume 1891 if ((pFront < 0.0) || (pBack < 0.0)) 1892 { 1893 Debug << "ERROR in volume:\n" 1894 << "volume f :" << pFront << " b: " << pBack << " p: " << pOverall 1895 << ", real volume f: " << pFront << " b: " << geomBack.GetVolume() 1896 << ", #polygons f: " << geomFront.Size() << " b: " << geomBack.Size() << " p: " << data.mGeometry->Size() << endl; 1897 } 1898 } 1899 else 1900 { 1901 pFront = geomFront.GetArea(); 1902 pBack = geomBack.GetArea(); 1903 } 1904 980 981 pFront = geomFront.GetVolume(); 982 pBack = pOverall - pFront; 983 984 1905 985 1906 986 // -- pvs rendering heuristics … … 1921 1001 1922 1002 #if 1 1923 // take render cost of node into account 1003 // take render cost of node into account to avoid being stuck in a local minimum 1924 1004 const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume(); 1925 //Debug << "rendercostdecr: " << 0.99f * renderCostDecrease << " old render cost: " << 0.01f * normalizedOldRenderCost << endl;1926 //return 0.5f * renderCostDecrease + 0.5f * normalizedOldRenderCost;1927 1005 return 0.99f * renderCostDecrease + 0.01f * normalizedOldRenderCost; 1928 1006 #else … … 1932 1010 1933 1011 1934 float VspBspTree::EvalSplitPlaneCost(const Plane3 &candidatePlane, 1935 const VspBspTraversalData &data, 1936 BspNodeGeometry &geomFront, 1937 BspNodeGeometry &geomBack, 1938 float &pFront, 1939 float &pBack) const 1940 { 1941 float cost = 0; 1942 1943 float totalPvs = 0; 1944 float pvsFront = 0; 1945 float pvsBack = 0; 1946 1947 // probability that view point lies in back / front node 1948 float pOverall = 0; 1949 pFront = 0; 1950 pBack = 0; 1951 1952 1953 int limit; 1954 bool useRand; 1955 1956 // create unique ids for pvs heuristics 1957 GenerateUniqueIdsForPvs(); 1958 1959 // choose test rays randomly if too much 1960 if ((int)data.mRays->size() > mMaxTests) 1961 { 1962 useRand = true; 1963 limit = mMaxTests; 1964 } 1965 else 1966 { 1967 useRand = false; 1968 limit = (int)data.mRays->size(); 1969 } 1970 1971 for (int i = 0; i < limit; ++ i) 1972 { 1973 const int testIdx = useRand ? 1974 (int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i; 1975 RayInfo rayInf = (*data.mRays)[testIdx]; 1976 1977 float t; 1978 VssRay *ray = rayInf.mRay; 1979 const int cf = rayInf.ComputeRayIntersection(candidatePlane, t); 1980 1981 // find front and back pvs for origing and termination object 1982 AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs); 1983 AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs); 1984 } 1985 1986 // construct child geometry with regard to the candidate split plane 1987 bool splitSuccessFull = data.mGeometry->SplitGeometry(geomFront, 1988 geomBack, 1989 candidatePlane, 1990 mBox, 1991 //0.0f); 1992 mEpsilon); 1993 1994 pOverall = data.mProbability; 1995 1996 if (!mUseAreaForPvs) // use front and back cell areas to approximate volume 1997 { 1998 pFront = geomFront.GetVolume(); 1999 pBack = pOverall - pFront; 2000 2001 // HACK: precision issues possible for unbalanced split => don't take this split! 2002 if (1 && 2003 (!splitSuccessFull || (pFront <= 0) || (pBack <= 0) || 2004 !geomFront.Valid() || !geomBack.Valid())) 2005 { 2006 //Debug << "error f: " << pFront << " b: " << pBack << endl; 2007 // high penalty for this split 2008 return 99999.9f; 2009 } 2010 } 2011 else 2012 { 2013 pFront = geomFront.GetArea(); 2014 pBack = geomBack.GetArea(); 2015 } 2016 2017 2018 // -- pvs rendering heuristics 2019 const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize(); 2020 const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize(); 2021 2022 // only render cost heuristics or combined with standard deviation 2023 const float penaltyOld = EvalPvsPenalty((int)totalPvs, lowerPvsLimit, upperPvsLimit); 2024 const float penaltyFront = EvalPvsPenalty((int)pvsFront, lowerPvsLimit, upperPvsLimit); 2025 const float penaltyBack = EvalPvsPenalty((int)pvsBack, lowerPvsLimit, upperPvsLimit); 2026 2027 const float oldRenderCost = pOverall * penaltyOld; 2028 const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack; 2029 2030 float oldCost, newCost; 2031 2032 // only render cost 2033 if (1) 2034 { 2035 oldCost = oldRenderCost; 2036 newCost = newRenderCost; 2037 } 2038 else // also considering standard deviation 2039 { 2040 // standard deviation is difference of back and front pvs 2041 const float expectedCost = 0.5f * (penaltyFront + penaltyBack); 2042 2043 const float newDeviation = 0.5f * 2044 fabs(penaltyFront - expectedCost) + fabs(penaltyBack - expectedCost); 2045 2046 const float oldDeviation = penaltyOld; 2047 2048 newCost = mRenderCostWeight * newRenderCost + (1.0f - mRenderCostWeight) * newDeviation; 2049 oldCost = mRenderCostWeight * oldRenderCost + (1.0f - mRenderCostWeight) * oldDeviation; 2050 } 2051 2052 cost += mPvsFactor * newCost / (oldCost + Limits::Small); 2053 2054 2055 #ifdef _DEBUG 2056 Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall 2057 << " frontpvs: " << pvsFront << " pFront: " << pFront 2058 << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl; 2059 Debug << "cost: " << cost << endl; 2060 #endif 2061 2062 return cost; 2063 } 2064 2065 2066 int VspBspTree::ComputeBoxIntersections(const AxisAlignedBox3 &box, 2067 ViewCellContainer &viewCells) const 2068 { 2069 stack<bspNodePair> nodeStack; 2070 BspNodeGeometry *rgeom = new BspNodeGeometry(); 2071 2072 ConstructGeometry(mRoot, *rgeom); 2073 2074 nodeStack.push(bspNodePair(mRoot, rgeom)); 2075 2076 ViewCell::NewMail(); 2077 2078 while (!nodeStack.empty()) 2079 { 2080 BspNode *node = nodeStack.top().first; 2081 BspNodeGeometry *geom = nodeStack.top().second; 2082 nodeStack.pop(); 2083 2084 const int side = geom->ComputeIntersection(box); 2085 2086 switch (side) 2087 { 2088 case -1: 2089 // node geometry is contained in box 2090 CollectViewCells(node, true, viewCells, true); 2091 break; 2092 2093 case 0: 2094 if (node->IsLeaf()) 2095 { 2096 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 2097 2098 if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid()) 2099 { 2100 leaf->GetViewCell()->Mail(); 2101 viewCells.push_back(leaf->GetViewCell()); 2102 } 2103 } 2104 else 2105 { 2106 BspInterior *interior = dynamic_cast<BspInterior *>(node); 2107 2108 BspNode *first = interior->GetFront(); 2109 BspNode *second = interior->GetBack(); 2110 2111 BspNodeGeometry *firstGeom = new BspNodeGeometry(); 2112 BspNodeGeometry *secondGeom = new BspNodeGeometry(); 2113 2114 geom->SplitGeometry(*firstGeom, 2115 *secondGeom, 2116 interior->GetPlane(), 2117 mBox, 2118 //0.0000001f); 2119 mEpsilon); 2120 2121 nodeStack.push(bspNodePair(first, firstGeom)); 2122 nodeStack.push(bspNodePair(second, secondGeom)); 2123 } 2124 2125 break; 2126 default: 2127 // default: cull 2128 break; 2129 } 2130 2131 DEL_PTR(geom); 2132 2133 } 2134 2135 return (int)viewCells.size(); 2136 } 2137 2138 2139 float VspBspTree::EvalAxisAlignedSplitCost(const VspBspTraversalData &data, 2140 const AxisAlignedBox3 &box, 2141 const int axis, 2142 const float &position, 2143 float &pFront, 2144 float &pBack) const 1012 1013 float VspOspTree::EvalSplitCost(const VspOspTraversalData &data, 1014 const AxisAlignedBox3 &box, 1015 const int axis, 1016 const float &position, 1017 float &pFront, 1018 float &pBack) const 2145 1019 { 2146 1020 float pvsTotal = 0; … … 2158 1032 for(rit = data.mRays->begin(); rit != rit_end; ++ rit) 2159 1033 { 2160 //if (!(*rit).mRay->IsActive()) continue;2161 2162 1034 // determine the side of this ray with respect to the plane 2163 1035 float t; … … 2175 1047 2176 1048 pOverall = data.mProbability; 2177 2178 if (!mUseAreaForPvs) 2179 { // volume 2180 pBack = pFront = pOverall * 0.5f; 2181 2182 #if 0 2183 // box length substitute for probability 2184 const float minBox = box.Min(axis); 2185 const float maxBox = box.Max(axis); 2186 2187 pBack = position - minBox; 2188 pFront = maxBox - position; 2189 pOverall = maxBox - minBox; 2190 #endif 2191 } 2192 else //-- area substitute for probability 2193 { 2194 const int axis2 = (axis + 1) % 3; 2195 const int axis3 = (axis + 2) % 3; 2196 2197 const float faceArea = 2198 (box.Max(axis2) - box.Min(axis2)) * 2199 (box.Max(axis3) - box.Min(axis3)); 2200 2201 pBack = pFront = pOverall * 0.5f + faceArea; 2202 } 2203 1049 pBack = pFront = pOverall * 0.5f; 1050 1051 2204 1052 #ifdef _DEBUG 2205 1053 Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl; … … 2215 1063 2216 1064 2217 void Vsp BspTree::AddObjToPvs(Intersectable *obj,1065 void VspOspTree::AddObjToPvs(Intersectable *obj, 2218 1066 const int cf, 2219 1067 float &frontPvs, … … 2268 1116 2269 1117 2270 void Vsp BspTree::CollectLeaves(vector<BspLeaf *> &leaves,1118 void VspOspTree::CollectLeaves(vector<BspLeaf *> &leaves, 2271 1119 const bool onlyUnmailed, 2272 1120 const int maxPvsSize) const … … 2302 1150 2303 1151 2304 AxisAlignedBox3 Vsp BspTree::GetBoundingBox() const1152 AxisAlignedBox3 VspOspTree::GetBoundingBox() const 2305 1153 { 2306 1154 return mBox; … … 2308 1156 2309 1157 2310 BspNode *Vsp BspTree::GetRoot() const1158 BspNode *VspOspTree::GetRoot() const 2311 1159 { 2312 1160 return mRoot; … … 2314 1162 2315 1163 2316 void Vsp BspTree::EvaluateLeafStats(const VspBspTraversalData &data)1164 void VspOspTree::EvaluateLeafStats(const VspOspTraversalData &data) 2317 1165 { 2318 1166 // the node became a leaf -> evaluate stats for leafs … … 2370 1218 2371 1219 2372 int Vsp BspTree::CastRay(Ray &ray)1220 int VspOspTree::CastRay(Ray &ray) 2373 1221 { 2374 1222 int hits = 0; … … 2439 1287 if (!leaf->GetViewCell()->Mailed()) 2440 1288 { 2441 //ray.bspIntersections.push_back(Ray::Vsp BspIntersection(maxt, leaf));1289 //ray.bspIntersections.push_back(Ray::VspOspIntersection(maxt, leaf)); 2442 1290 leaf->GetViewCell()->Mail(); 2443 1291 ++ hits; … … 2468 1316 2469 1317 2470 void Vsp BspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const1318 void VspOspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const 2471 1319 { 2472 1320 ViewCell::NewMail(); … … 2476 1324 2477 1325 2478 void Vsp BspTree::CollapseViewCells()1326 void VspOspTree::CollapseViewCells() 2479 1327 { 2480 1328 // TODO … … 2531 1379 2532 1380 2533 void Vsp BspTree::CollectRays(VssRayContainer &rays)1381 void VspOspTree::CollectRays(VssRayContainer &rays) 2534 1382 { 2535 1383 vector<BspLeaf *> leaves; … … 2548 1396 2549 1397 2550 void Vsp BspTree::ValidateTree()1398 void VspOspTree::ValidateTree() 2551 1399 { 2552 1400 stack<BspNode *> nodeStack; … … 2591 1439 2592 1440 2593 void Vsp BspTree::CollectViewCells(BspNode *root,1441 void VspOspTree::CollectViewCells(BspNode *root, 2594 1442 bool onlyValid, 2595 1443 ViewCellContainer &viewCells, … … 2635 1483 2636 1484 2637 void VspBspTree::PreprocessPolygons(PolygonContainer &polys) 2638 { 2639 // preprocess: throw out polygons coincident to the view space box (not needed) 2640 PolygonContainer boxPolys; 2641 mBox.ExtractPolys(boxPolys); 2642 vector<Plane3> boxPlanes; 2643 2644 PolygonContainer::iterator pit, pit_end = boxPolys.end(); 2645 2646 // extract planes of box 2647 // TODO: can be done more elegantly than first extracting polygons 2648 // and take their planes 2649 for (pit = boxPolys.begin(); pit != pit_end; ++ pit) 2650 { 2651 boxPlanes.push_back((*pit)->GetSupportingPlane()); 2652 } 2653 2654 pit_end = polys.end(); 2655 2656 for (pit = polys.begin(); pit != pit_end; ++ pit) 2657 { 2658 vector<Plane3>::const_iterator bit, bit_end = boxPlanes.end(); 2659 2660 for (bit = boxPlanes.begin(); (bit != bit_end) && (*pit); ++ bit) 2661 { 2662 const int cf = (*pit)->ClassifyPlane(*bit, mEpsilon); 2663 2664 if (cf == Polygon3::COINCIDENT) 2665 { 2666 DEL_PTR(*pit); 2667 //Debug << "coincident!!" << endl; 2668 } 2669 } 2670 } 2671 2672 // remove deleted entries 2673 for (int i = 0; i < (int)polys.size(); ++ i) 2674 { 2675 while (!polys[i] && (i < (int)polys.size())) 2676 { 2677 swap(polys[i], polys.back()); 2678 polys.pop_back(); 2679 } 2680 } 2681 } 2682 2683 2684 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const 2685 { 2686 float len = 0; 2687 2688 RayInfoContainer::const_iterator it, it_end = rays.end(); 2689 2690 for (it = rays.begin(); it != it_end; ++ it) 2691 len += (*it).SegmentLength(); 2692 2693 return len; 2694 } 2695 2696 2697 int VspBspTree::SplitRays(const Plane3 &plane, 1485 int VspOspTree::SplitRays(const Plane3 &plane, 2698 1486 RayInfoContainer &rays, 2699 1487 RayInfoContainer &frontRays, … … 2725 1513 { 2726 1514 //-- split ray 2727 // 1515 //-- test if start point behind or in front of plane 2728 1516 const int side = plane.Side(bRay.ExtrapOrigin()); 2729 1517 … … 2750 1538 2751 1539 2752 void VspBspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const 2753 { 2754 BspNode *lastNode; 2755 2756 do 2757 { 2758 lastNode = n; 2759 2760 // want to get planes defining geometry of this node => don't take 2761 // split plane of node itself 2762 n = n->GetParent(); 2763 2764 if (n) 2765 { 2766 BspInterior *interior = dynamic_cast<BspInterior *>(n); 2767 Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane(); 2768 2769 if (interior->GetBack() != lastNode) 2770 halfSpace.ReverseOrientation(); 2771 2772 halfSpaces.push_back(halfSpace); 2773 } 2774 } 2775 while (n); 2776 } 2777 2778 2779 void VspBspTree::ConstructGeometry(BspNode *n, 2780 BspNodeGeometry &geom) const 2781 { 2782 vector<Plane3> halfSpaces; 2783 ExtractHalfSpaces(n, halfSpaces); 2784 2785 PolygonContainer candidatePolys; 2786 vector<Plane3> candidatePlanes; 2787 2788 vector<Plane3>::const_iterator pit, pit_end = halfSpaces.end(); 2789 2790 // bounded planes are added to the polygons 2791 for (pit = halfSpaces.begin(); pit != pit_end; ++ pit) 2792 { 2793 Polygon3 *p = GetBoundingBox().CrossSection(*pit); 2794 2795 if (p->Valid(mEpsilon)) 2796 { 2797 candidatePolys.push_back(p); 2798 candidatePlanes.push_back(*pit); 2799 } 2800 } 2801 2802 // add faces of bounding box (also could be faces of the cell) 2803 for (int i = 0; i < 6; ++ i) 2804 { 2805 VertexContainer vertices; 2806 2807 for (int j = 0; j < 4; ++ j) 2808 vertices.push_back(mBox.GetFace(i).mVertices[j]); 2809 2810 Polygon3 *poly = new Polygon3(vertices); 2811 2812 candidatePolys.push_back(poly); 2813 candidatePlanes.push_back(poly->GetSupportingPlane()); 2814 } 2815 2816 for (int i = 0; i < (int)candidatePolys.size(); ++ i) 2817 { 2818 // polygon is split by all other planes 2819 for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j) 2820 { 2821 if (i == j) // polygon and plane are coincident 2822 continue; 2823 2824 VertexContainer splitPts; 2825 Polygon3 *frontPoly, *backPoly; 2826 2827 const int cf = 2828 candidatePolys[i]->ClassifyPlane(halfSpaces[j], 2829 mEpsilon); 2830 2831 switch (cf) 2832 { 2833 case Polygon3::SPLIT: 2834 frontPoly = new Polygon3(); 2835 backPoly = new Polygon3(); 2836 2837 candidatePolys[i]->Split(halfSpaces[j], 2838 *frontPoly, 2839 *backPoly, 2840 mEpsilon); 2841 2842 DEL_PTR(candidatePolys[i]); 2843 2844 if (backPoly->Valid(mEpsilon)) 2845 candidatePolys[i] = backPoly; 2846 else 2847 DEL_PTR(backPoly); 2848 2849 // outside, don't need this 2850 DEL_PTR(frontPoly); 2851 break; 2852 // polygon outside of halfspace 2853 case Polygon3::FRONT_SIDE: 2854 DEL_PTR(candidatePolys[i]); 2855 break; 2856 // just take polygon as it is 2857 case Polygon3::BACK_SIDE: 2858 case Polygon3::COINCIDENT: 2859 default: 2860 break; 2861 } 2862 } 2863 2864 if (candidatePolys[i]) 2865 { 2866 geom.Add(candidatePolys[i], candidatePlanes[i]); 2867 // geom.mPolys.push_back(candidates[i]); 2868 } 2869 } 2870 } 2871 2872 2873 void VspBspTree::ConstructGeometry(ViewCell *vc, 2874 BspNodeGeometry &vcGeom) const 2875 { 2876 ViewCellContainer leaves; 2877 2878 mViewCellsTree->CollectLeaves(vc, leaves); 2879 2880 ViewCellContainer::const_iterator it, it_end = leaves.end(); 2881 2882 for (it = leaves.begin(); it != it_end; ++ it) 2883 { 2884 BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf; 2885 2886 ConstructGeometry(l, vcGeom); 2887 } 2888 } 2889 2890 2891 int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 1540 int VspOspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 2892 1541 const bool onlyUnmailed) const 2893 1542 { 2894 stack<bspNodePair> nodeStack; 2895 2896 BspNodeGeometry nodeGeom; 2897 ConstructGeometry(n, nodeGeom); 2898 // const float eps = 0.5f; 2899 const float eps = 0.01f; 2900 // split planes from the root to this node 2901 // needed to verify that we found neighbor leaf 2902 // TODO: really needed? 2903 vector<Plane3> halfSpaces; 2904 ExtractHalfSpaces(n, halfSpaces); 2905 2906 2907 BspNodeGeometry *rgeom = new BspNodeGeometry(); 2908 ConstructGeometry(mRoot, *rgeom); 2909 2910 nodeStack.push(bspNodePair(mRoot, rgeom)); 2911 2912 while (!nodeStack.empty()) 2913 { 2914 BspNode *node = nodeStack.top().first; 2915 BspNodeGeometry *geom = nodeStack.top().second; 2916 2917 nodeStack.pop(); 2918 2919 if (node->IsLeaf()) 2920 { 2921 // test if this leaf is in valid view space 2922 if (node->TreeValid() && 2923 (node != n) && 2924 (!onlyUnmailed || !node->Mailed())) 2925 { 2926 bool isAdjacent = true; 2927 2928 if (1) 2929 { 2930 // test all planes of current node if still adjacent 2931 for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i) 2932 { 2933 const int cf = 2934 Polygon3::ClassifyPlane(geom->GetPolys(), 2935 halfSpaces[i], 2936 eps); 2937 2938 if (cf == Polygon3::FRONT_SIDE) 2939 { 2940 isAdjacent = false; 2941 } 2942 } 2943 } 2944 else 2945 { 2946 // TODO: why is this wrong?? 2947 // test all planes of current node if still adjacent 2948 for (int i = 0; (i < nodeGeom.Size()) && isAdjacent; ++ i) 2949 { 2950 Polygon3 *poly = nodeGeom.GetPolys()[i]; 2951 2952 const int cf = 2953 Polygon3::ClassifyPlane(geom->GetPolys(), 2954 poly->GetSupportingPlane(), 2955 eps); 2956 2957 if (cf == Polygon3::FRONT_SIDE) 2958 { 2959 isAdjacent = false; 2960 } 2961 } 2962 } 2963 // neighbor was found 2964 if (isAdjacent) 2965 { 2966 neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 2967 } 2968 } 2969 } 2970 else 2971 { 2972 BspInterior *interior = dynamic_cast<BspInterior *>(node); 2973 2974 const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(), 2975 interior->GetPlane(), 2976 eps); 2977 2978 BspNode *front = interior->GetFront(); 2979 BspNode *back = interior->GetBack(); 2980 2981 BspNodeGeometry *fGeom = new BspNodeGeometry(); 2982 BspNodeGeometry *bGeom = new BspNodeGeometry(); 2983 2984 geom->SplitGeometry(*fGeom, 2985 *bGeom, 2986 interior->GetPlane(), 2987 mBox, 2988 //0.0000001f); 2989 eps); 2990 2991 if (cf == Polygon3::BACK_SIDE) 2992 { 2993 nodeStack.push(bspNodePair(interior->GetBack(), bGeom)); 2994 DEL_PTR(fGeom); 2995 } 2996 else 2997 { 2998 if (cf == Polygon3::FRONT_SIDE) 2999 { 3000 nodeStack.push(bspNodePair(interior->GetFront(), fGeom)); 3001 DEL_PTR(bGeom); 3002 } 3003 else 3004 { // random decision 3005 nodeStack.push(bspNodePair(front, fGeom)); 3006 nodeStack.push(bspNodePair(back, bGeom)); 3007 } 3008 } 3009 } 3010 3011 DEL_PTR(geom); 3012 } 3013 3014 return (int)neighbors.size(); 3015 } 3016 3017 3018 3019 int VspBspTree::FindApproximateNeighbors(BspNode *n, 3020 vector<BspLeaf *> &neighbors, 3021 const bool onlyUnmailed) const 3022 { 3023 stack<bspNodePair> nodeStack; 3024 3025 BspNodeGeometry nodeGeom; 3026 ConstructGeometry(n, nodeGeom); 3027 3028 float eps = 0.01f; 3029 // split planes from the root to this node 3030 // needed to verify that we found neighbor leaf 3031 // TODO: really needed? 3032 vector<Plane3> halfSpaces; 3033 ExtractHalfSpaces(n, halfSpaces); 3034 3035 3036 BspNodeGeometry *rgeom = new BspNodeGeometry(); 3037 ConstructGeometry(mRoot, *rgeom); 3038 3039 nodeStack.push(bspNodePair(mRoot, rgeom)); 3040 3041 while (!nodeStack.empty()) 3042 { 3043 BspNode *node = nodeStack.top().first; 3044 BspNodeGeometry *geom = nodeStack.top().second; 3045 3046 nodeStack.pop(); 3047 3048 if (node->IsLeaf()) 3049 { 3050 // test if this leaf is in valid view space 3051 if (node->TreeValid() && 3052 (node != n) && 3053 (!onlyUnmailed || !node->Mailed())) 3054 { 3055 bool isAdjacent = true; 3056 3057 // neighbor was found 3058 if (isAdjacent) 3059 { 3060 neighbors.push_back(dynamic_cast<BspLeaf *>(node)); 3061 } 3062 } 3063 } 3064 else 3065 { 3066 BspInterior *interior = dynamic_cast<BspInterior *>(node); 3067 3068 const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(), 3069 interior->GetPlane(), 3070 eps); 3071 3072 BspNode *front = interior->GetFront(); 3073 BspNode *back = interior->GetBack(); 3074 3075 BspNodeGeometry *fGeom = new BspNodeGeometry(); 3076 BspNodeGeometry *bGeom = new BspNodeGeometry(); 3077 3078 geom->SplitGeometry(*fGeom, 3079 *bGeom, 3080 interior->GetPlane(), 3081 mBox, 3082 //0.0000001f); 3083 eps); 3084 3085 if (cf == Polygon3::BACK_SIDE) 3086 { 3087 nodeStack.push(bspNodePair(interior->GetBack(), bGeom)); 3088 DEL_PTR(fGeom); 3089 } 3090 else 3091 { 3092 if (cf == Polygon3::FRONT_SIDE) 3093 { 3094 nodeStack.push(bspNodePair(interior->GetFront(), fGeom)); 3095 DEL_PTR(bGeom); 3096 } 3097 else 3098 { // random decision 3099 nodeStack.push(bspNodePair(front, fGeom)); 3100 nodeStack.push(bspNodePair(back, bGeom)); 3101 } 3102 } 3103 } 3104 3105 DEL_PTR(geom); 3106 } 3107 3108 return (int)neighbors.size(); 3109 } 3110 3111 3112 3113 BspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace) 3114 { 1543 // TODO 1544 return 0; 1545 } 1546 1547 1548 BspLeaf *VspOspTree::GetRandomLeaf(const Plane3 &halfspace) 1549 { 1550 #if TODO 3115 1551 stack<BspNode *> nodeStack; 3116 1552 nodeStack.push(mRoot); … … 3157 1593 } 3158 1594 } 3159 1595 #endif 3160 1596 return NULL; 3161 1597 } 3162 1598 3163 1599 3164 BspLeaf *Vsp BspTree::GetRandomLeaf(const bool onlyUnmailed)1600 BspLeaf *VspOspTree::GetRandomLeaf(const bool onlyUnmailed) 3165 1601 { 3166 1602 stack<BspNode *> nodeStack; … … 3198 1634 3199 1635 3200 int Vsp BspTree::ComputePvsSize(const RayInfoContainer &rays) const1636 int VspOspTree::ComputePvsSize(const RayInfoContainer &rays) const 3201 1637 { 3202 1638 int pvsSize = 0; … … 3232 1668 3233 1669 3234 float Vsp BspTree::GetEpsilon() const1670 float VspOspTree::GetEpsilon() const 3235 1671 { 3236 1672 return mEpsilon; … … 3238 1674 3239 1675 3240 int VspBspTree::SplitPolygons(const Plane3 &plane, 3241 PolygonContainer &polys, 3242 PolygonContainer &frontPolys, 3243 PolygonContainer &backPolys, 3244 PolygonContainer &coincident) const 3245 { 3246 int splits = 0; 3247 3248 PolygonContainer::const_iterator it, it_end = polys.end(); 3249 3250 for (it = polys.begin(); it != polys.end(); ++ it) 3251 { 3252 Polygon3 *poly = *it; 3253 3254 // classify polygon 3255 const int cf = poly->ClassifyPlane(plane, mEpsilon); 3256 3257 switch (cf) 3258 { 3259 case Polygon3::COINCIDENT: 3260 coincident.push_back(poly); 3261 break; 3262 case Polygon3::FRONT_SIDE: 3263 frontPolys.push_back(poly); 3264 break; 3265 case Polygon3::BACK_SIDE: 3266 backPolys.push_back(poly); 3267 break; 3268 case Polygon3::SPLIT: 3269 backPolys.push_back(poly); 3270 frontPolys.push_back(poly); 3271 ++ splits; 3272 break; 3273 default: 3274 Debug << "SHOULD NEVER COME HERE\n"; 3275 break; 3276 } 3277 } 3278 3279 return splits; 3280 } 3281 3282 3283 int VspBspTree::CastLineSegment(const Vector3 &origin, 1676 1677 int VspOspTree::CastLineSegment(const Vector3 &origin, 3284 1678 const Vector3 &termination, 3285 1679 ViewCellContainer &viewcells) … … 3387 1781 3388 1782 3389 3390 int VspBspTree::TreeDistance(BspNode *n1, BspNode *n2) const 3391 { 3392 std::deque<BspNode *> path1; 3393 BspNode *p1 = n1; 3394 3395 // create path from node 1 to root 3396 while (p1) 3397 { 3398 if (p1 == n2) // second node on path 3399 return (int)path1.size(); 3400 3401 path1.push_front(p1); 3402 p1 = p1->GetParent(); 3403 } 3404 3405 int depth = n2->GetDepth(); 3406 int d = depth; 3407 3408 BspNode *p2 = n2; 3409 3410 // compare with same depth 3411 while (1) 3412 { 3413 if ((d < (int)path1.size()) && (p2 == path1[d])) 3414 return (depth - d) + ((int)path1.size() - 1 - d); 3415 3416 -- d; 3417 p2 = p2->GetParent(); 3418 } 3419 3420 return 0; // never come here 3421 } 3422 3423 3424 BspNode *VspBspTree::CollapseTree(BspNode *node, int &collapsed) 1783 BspNode *VspOspTree::CollapseTree(BspNode *node, int &collapsed) 3425 1784 { 3426 1785 // TODO … … 3464 1823 3465 1824 3466 int Vsp BspTree::CollapseTree()1825 int VspOspTree::CollapseTree() 3467 1826 { 3468 1827 int collapsed = 0; … … 3478 1837 3479 1838 3480 void Vsp BspTree::RepairViewCellsLeafLists()1839 void VspOspTree::RepairViewCellsLeafLists() 3481 1840 { 3482 1841 // TODO … … 3521 1880 3522 1881 3523 typedef pair<BspNode *, BspNodeGeometry *> bspNodePair; 3524 3525 3526 int VspBspTree::CastBeam(Beam &beam) 3527 { 3528 stack<bspNodePair> nodeStack; 3529 BspNodeGeometry *rgeom = new BspNodeGeometry(); 3530 ConstructGeometry(mRoot, *rgeom); 3531 3532 nodeStack.push(bspNodePair(mRoot, rgeom)); 3533 3534 ViewCell::NewMail(); 3535 3536 while (!nodeStack.empty()) 3537 { 3538 BspNode *node = nodeStack.top().first; 3539 BspNodeGeometry *geom = nodeStack.top().second; 3540 nodeStack.pop(); 3541 3542 AxisAlignedBox3 box; 3543 geom->GetBoundingBox(box); 3544 3545 const int side = beam.ComputeIntersection(box); 3546 3547 switch (side) 3548 { 3549 case -1: 3550 CollectViewCells(node, true, beam.mViewCells, true); 3551 break; 3552 case 0: 3553 3554 if (node->IsLeaf()) 3555 { 3556 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 3557 3558 if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid()) 3559 { 3560 leaf->GetViewCell()->Mail(); 3561 beam.mViewCells.push_back(leaf->GetViewCell()); 3562 } 3563 } 3564 else 3565 { 3566 BspInterior *interior = dynamic_cast<BspInterior *>(node); 3567 3568 BspNode *first = interior->GetFront(); 3569 BspNode *second = interior->GetBack(); 3570 3571 BspNodeGeometry *firstGeom = new BspNodeGeometry(); 3572 BspNodeGeometry *secondGeom = new BspNodeGeometry(); 3573 3574 geom->SplitGeometry(*firstGeom, 3575 *secondGeom, 3576 interior->GetPlane(), 3577 mBox, 3578 //0.0000001f); 3579 mEpsilon); 3580 3581 // decide on the order of the nodes 3582 if (DotProd(beam.mPlanes[0].mNormal, 3583 interior->GetPlane().mNormal) > 0) 3584 { 3585 swap(first, second); 3586 swap(firstGeom, secondGeom); 3587 } 3588 3589 nodeStack.push(bspNodePair(first, firstGeom)); 3590 nodeStack.push(bspNodePair(second, secondGeom)); 3591 } 3592 3593 break; 3594 default: 3595 // default: cull 3596 break; 3597 } 3598 3599 DEL_PTR(geom); 3600 3601 } 3602 3603 return (int)beam.mViewCells.size(); 3604 } 3605 3606 3607 void VspBspTree::SetViewCellsManager(ViewCellsManager *vcm) 3608 { 3609 mViewCellsManager = vcm; 3610 } 3611 3612 3613 int VspBspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves, 3614 vector<MergeCandidate> &candidates) 3615 { 3616 BspLeaf::NewMail(); 3617 3618 vector<BspLeaf *>::const_iterator it, it_end = leaves.end(); 3619 3620 int numCandidates = 0; 3621 3622 // find merge candidates and push them into queue 3623 for (it = leaves.begin(); it != it_end; ++ it) 3624 { 3625 BspLeaf *leaf = *it; 3626 3627 // the same leaves must not be part of two merge candidates 3628 leaf->Mail(); 3629 3630 vector<BspLeaf *> neighbors; 3631 3632 // appoximate neighbor search has slightl relaxed constraints 3633 if (1) 3634 FindNeighbors(leaf, neighbors, true); 3635 else 3636 FindApproximateNeighbors(leaf, neighbors, true); 3637 3638 vector<BspLeaf *>::const_iterator nit, nit_end = neighbors.end(); 3639 3640 // TODO: test if at least one ray goes from one leaf to the other 3641 for (nit = neighbors.begin(); nit != nit_end; ++ nit) 3642 { 3643 if ((*nit)->GetViewCell() != leaf->GetViewCell()) 3644 { 3645 MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell()); 3646 3647 // dont't merge view cells if they are empty and not front and back leaf of the same parent 3648 // in the tree? 3649 if (mEmptyViewCellsMergeAllowed || 3650 !leaf->GetViewCell()->GetPvs().Empty() || 3651 !(*nit)->GetViewCell()->GetPvs().Empty() || 3652 leaf->IsSibling(*nit)) 3653 { 3654 candidates.push_back(mc); 3655 } 3656 3657 ++ numCandidates; 3658 if ((numCandidates % 1000) == 0) 3659 { 3660 cout << "collected " << numCandidates << " merge candidates" << endl; 3661 } 3662 } 3663 } 3664 } 3665 3666 Debug << "merge queue: " << (int)candidates.size() << endl; 3667 Debug << "leaves in queue: " << numCandidates << endl; 3668 3669 3670 return (int)leaves.size(); 3671 } 3672 3673 3674 int VspBspTree::CollectMergeCandidates(const VssRayContainer &rays, 3675 vector<MergeCandidate> &candidates) 3676 { 3677 ViewCell::NewMail(); 3678 long startTime = GetTime(); 3679 3680 map<BspLeaf *, vector<BspLeaf*> > neighborMap; 3681 ViewCellContainer::const_iterator iit; 3682 3683 int numLeaves = 0; 3684 3685 BspLeaf::NewMail(); 3686 3687 for (int i = 0; i < (int)rays.size(); ++ i) 3688 { 3689 VssRay *ray = rays[i]; 3690 3691 // traverse leaves stored in the rays and compare and 3692 // merge consecutive leaves (i.e., the neighbors in the tree) 3693 if (ray->mViewCells.size() < 2) 3694 continue; 3695 //TODO viewcellhierarchy 3696 iit = ray->mViewCells.begin(); 3697 BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*(iit ++)); 3698 BspLeaf *leaf = bspVc->mLeaf; 3699 3700 // traverse intersections 3701 // consecutive leaves are neighbors => add them to queue 3702 for (; iit != ray->mViewCells.end(); ++ iit) 3703 { 3704 // next pair 3705 BspLeaf *prevLeaf = leaf; 3706 bspVc = dynamic_cast<BspViewCell *>(*iit); 3707 leaf = bspVc->mLeaf; 3708 3709 // view space not valid or same view cell 3710 if (!leaf->TreeValid() || !prevLeaf->TreeValid() || 3711 (leaf->GetViewCell() == prevLeaf->GetViewCell())) 3712 continue; 3713 3714 vector<BspLeaf *> &neighbors = neighborMap[leaf]; 3715 3716 bool found = false; 3717 3718 // both leaves inserted in queue already => 3719 // look if double pair already exists 3720 if (leaf->Mailed() && prevLeaf->Mailed()) 3721 { 3722 vector<BspLeaf *>::const_iterator it, it_end = neighbors.end(); 3723 3724 for (it = neighbors.begin(); !found && (it != it_end); ++ it) 3725 if (*it == prevLeaf) 3726 found = true; // already in queue 3727 } 3728 3729 if (!found) 3730 { 3731 // this pair is not in map yet 3732 // => insert into the neighbor map and the queue 3733 neighbors.push_back(prevLeaf); 3734 neighborMap[prevLeaf].push_back(leaf); 3735 3736 leaf->Mail(); 3737 prevLeaf->Mail(); 3738 3739 MergeCandidate mc(leaf->GetViewCell(), prevLeaf->GetViewCell()); 3740 3741 candidates.push_back(mc); 3742 3743 if (((int)candidates.size() % 1000) == 0) 3744 { 3745 cout << "collected " << (int)candidates.size() << " merge candidates" << endl; 3746 } 3747 } 3748 } 3749 } 3750 3751 Debug << "neighbormap size: " << (int)neighborMap.size() << endl; 3752 Debug << "merge queue: " << (int)candidates.size() << endl; 3753 Debug << "leaves in queue: " << numLeaves << endl; 3754 3755 3756 //-- collect the leaves which haven't been found by ray casting 3757 if (0) 3758 { 3759 cout << "finding additional merge candidates using geometry" << endl; 3760 vector<BspLeaf *> leaves; 3761 CollectLeaves(leaves, true); 3762 Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl; 3763 CollectMergeCandidates(leaves, candidates); 3764 } 3765 3766 return numLeaves; 3767 } 3768 3769 3770 3771 3772 ViewCell *VspBspTree::GetViewCell(const Vector3 &point, const bool active) 1882 1883 ViewCell *VspOspTree::GetViewCell(const Vector3 &point, const bool active) 3773 1884 { 3774 1885 if (mRoot == NULL) … … 3809 1920 3810 1921 3811 bool Vsp BspTree::ViewPointValid(const Vector3 &viewPoint) const1922 bool VspOspTree::ViewPointValid(const Vector3 &viewPoint) const 3812 1923 { 3813 1924 BspNode *node = mRoot; … … 3839 1950 3840 1951 3841 void Vsp BspTree::PropagateUpValidity(BspNode *node)1952 void VspOspTree::PropagateUpValidity(BspNode *node) 3842 1953 { 3843 1954 const bool isValid = node->TreeValid(); … … 3868 1979 3869 1980 #if ZIPPED_VIEWCELLS 3870 bool Vsp BspTree::Export(ogzstream &stream)1981 bool VspOspTree::Export(ogzstream &stream) 3871 1982 #else 3872 bool Vsp BspTree::Export(ofstream &stream)1983 bool VspOspTree::Export(ofstream &stream) 3873 1984 #endif 3874 1985 { … … 3878 1989 } 3879 1990 1991 3880 1992 #if ZIPPED_VIEWCELLS 3881 void Vsp BspTree::ExportNode(BspNode *node, ogzstream &stream)1993 void VspOspTree::ExportNode(BspNode *node, ogzstream &stream) 3882 1994 #else 3883 void Vsp BspTree::ExportNode(BspNode *node, ofstream &stream)1995 void VspOspTree::ExportNode(BspNode *node, ofstream &stream) 3884 1996 #endif 3885 1997 { -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
r1002 r1006 1 #ifndef _Vsp BspTree_H__2 #define _Vsp BspTree_H__1 #ifndef _VspOspTree_H__ 2 #define _VspOspTree_H__ 3 3 4 4 #include "Mesh.h" … … 31 31 32 32 /** 33 This is a view space partitioning specialised BSPtree. 34 There are no polygon splits, but we split the sample rays. 35 The candidates for the next split plane are evaluated only 36 by checking the sampled visibility information. 37 The polygons are employed merely as candidates for the next split planes. 33 This class implements a structure holding two different hierarchies, 34 one for object space partitioning and one for view space partitioning. 35 36 The object space and the view space are subdivided using a cost heuristics. 37 If an object space split or a view space split is chosen is also evaluated 38 based on the heuristics. 39 40 The view space heuristics is evaluated by weighting and adding the pvss of the back and 41 front node of each specific split. unlike for the standalone method vspbsp tree, 42 the pvs of an object would not be the pvs of single object but that of all objects 43 which are contained in the same leaf of the object subdivision. This could be done 44 by storing the pointer to the object space partition parent, which would allow access to all children. 45 Another possibility is to include traced kd-cells in the ray casing process. 46 47 Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object. 48 the contribution to an object to the pvs is the number of view cells it can be seen from. 49 50 51 There is a potential efficiency problem involved in a sense that once a certain type 52 of split is chosen for view space / object space, the candidates for the next split of 53 object space / view space must be reevaluated. 54 38 55 */ 39 class Vsp BspTree56 class VspOspTree 40 57 { 41 58 friend class ViewCellsParseHandlers; 42 59 friend class VspBspViewCellsManager; 60 43 61 public: 44 62 63 /** A definition for an axis aligned plane. 64 */ 65 struct AxisAlignedPlane 66 { 67 public: 68 int mAxis; 69 float mPosition; 70 }; 71 45 72 /** Additional data which is passed down the BSP tree during traversal. 46 73 */ 47 class Vsp BspTraversalData74 class VspOspTraversalData 48 75 { 49 76 public: 50 77 /// the current node 51 78 BspNode *mNode; 52 /// polygonal data for splitting53 PolygonContainer *mPolygons;54 79 /// current depth 55 80 int mDepth; … … 58 83 /// the probability that this node contains view point 59 84 float mProbability; 60 /// geometry of node as induced by planes61 BspNodeGeometry *mGeometry;85 /// the bounding box of the node 86 AxisAlignedBox3 mBoundingBox; 62 87 /// pvs size 63 88 int mPvs; 64 89 /// how often this branch has missed the max-cost ratio 65 90 int mMaxCostMisses; 66 /// if this node is a kd-node (i.e., boundaries are axis aligned67 bool mIsKdNode;68 91 // current axis 69 92 int mAxis; … … 80 103 81 104 82 Vsp BspTraversalData():105 VspOspTraversalData(): 83 106 mNode(NULL), 84 mPolygons(NULL),85 107 mDepth(0), 86 108 mRays(NULL), 87 109 mPvs(0), 88 110 mProbability(0.0), 89 mGeometry(NULL),90 111 mMaxCostMisses(0), 91 mIsKdNode(false),92 112 mPriority(0), 93 113 mAxis(0) 94 114 {} 95 115 96 VspBspTraversalData(BspNode *node, 97 PolygonContainer *polys, 116 VspOspTraversalData(BspNode *node, 98 117 const int depth, 99 118 RayInfoContainer *rays, 100 119 const int pvs, 101 120 const float p, 102 BspNodeGeometry *geom):121 const AxisAlignedBox3 &box): 103 122 mNode(node), 104 mPolygons(polys),105 123 mDepth(depth), 106 124 mRays(rays), 107 125 mPvs(pvs), 108 126 mProbability(p), 109 m Geometry(geom),127 mBoundingBox(box), 110 128 mMaxCostMisses(0), 111 mIsKdNode(false),112 129 mPriority(0), 113 130 mAxis(0) 114 131 {} 115 132 116 Vsp BspTraversalData(PolygonContainer *polys,133 VspOspTraversalData(PolygonContainer *polys, 117 134 const int depth, 118 135 RayInfoContainer *rays, 119 BspNodeGeometry *geom):136 const AxisAlignedBox3 &box): 120 137 mNode(NULL), 121 mPolygons(polys),122 138 mDepth(depth), 123 139 mRays(rays), 124 140 mPvs(0), 125 141 mProbability(0), 126 mGeometry(geom),127 142 mMaxCostMisses(0), 128 m IsKdNode(false),129 m Axis(0)143 mAxis(0), 144 mBoundingBox(box) 130 145 {} 131 146 … … 141 156 void Clear() 142 157 { 143 DEL_PTR(mPolygons);144 158 DEL_PTR(mRays); 145 DEL_PTR(mGeometry); 146 } 147 148 friend bool operator<(const VspBspTraversalData &a, const VspBspTraversalData &b) 159 } 160 161 friend bool operator<(const VspOspTraversalData &a, const VspOspTraversalData &b) 149 162 { 150 163 return a.GetCost() < b.GetCost(); … … 153 166 154 167 155 typedef std::priority_queue<Vsp BspTraversalData> VspBspTraversalQueue;156 157 158 struct Vsp BspSplitCandidate168 typedef std::priority_queue<VspOspTraversalData> VspOspTraversalQueue; 169 170 171 struct VspOspSplitCandidate 159 172 { 160 /// the current node 161 Plane3 mSplitPlane; 162 /// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned) 163 int mSplitAxis; 173 /// the current plane 174 AxisAlignedPlane mSplitPlane; 164 175 /// the number of misses of max cost ratio until this split 165 176 int mMaxCostMisses; 166 167 // parent data 168 VspBspTraversalData mParentData; 169 // cost of applying this split 177 /// parent data 178 VspOspTraversalData mParentData; 179 /// cost of applying this split 170 180 float mRenderCost; 171 181 172 Vsp BspSplitCandidate(): mRenderCost(0)182 VspOspSplitCandidate(): mRenderCost(0) 173 183 {}; 174 184 175 Vsp BspSplitCandidate(const Plane3 &plane, const VspBspTraversalData &tData):185 VspOspSplitCandidate(const AxisAlignedPlane &plane, const VspOspTraversalData &tData): 176 186 mSplitPlane(plane), mParentData(tData), mRenderCost(0) 177 187 {} … … 189 199 } 190 200 191 friend bool operator<(const Vsp BspSplitCandidate &a, const VspBspSplitCandidate &b)201 friend bool operator<(const VspOspSplitCandidate &a, const VspOspSplitCandidate &b) 192 202 { 193 203 return a.GetCost() < b.GetCost(); … … 195 205 }; 196 206 197 typedef std::priority_queue<Vsp BspSplitCandidate> VspBspSplitQueue;207 typedef std::priority_queue<VspOspSplitCandidate> VspOspSplitQueue; 198 208 199 209 /** Default constructor creating an empty tree. 200 210 */ 201 VspBspTree(); 202 203 204 /** Constructor creating an empty tree. Loads parameters 205 from an environment file. 206 */ 207 VspBspTree(Environment *env); 211 VspOspTree(); 208 212 209 213 /** Default destructor. 210 214 */ 211 ~Vsp BspTree();215 ~VspOspTree(); 212 216 213 217 /** Returns BSP Tree statistics. … … 252 256 int CastRay(Ray &ray); 253 257 254 /// bsp tree construction types255 enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};256 258 257 259 /** finds neighbouring leaves of this tree node. … … 260 262 vector<BspLeaf *> &neighbors, 261 263 const bool onlyUnmailed) const; 262 263 /** Constructs geometry associated with the half space intersections264 leading to this node.265 */266 void ConstructGeometry(BspNode *n, BspNodeGeometry &geom) const;267 268 /** Construct geometry of view cell.269 */270 void ConstructGeometry(ViewCell *vc, BspNodeGeometry &geom) const;271 264 272 265 /** Returns random leaf of BSP tree. … … 400 393 /** faster evaluation of split plane cost for kd axis aligned cells. 401 394 */ 402 float Eval AxisAlignedSplitCost(const VspBspTraversalData &data,403 404 405 406 407 395 float EvalSplitCost(const VspOspTraversalData &data, 396 const AxisAlignedBox3 &box, 397 const int axis, 398 const float &position, 399 float &pFront, 400 float &pBack) const; 408 401 409 402 /** Evaluates candidate for splitting. 410 403 */ 411 void EvalSplitCandidate(Vsp BspTraversalData &tData, VspBspSplitCandidate &splitData);404 void EvalSplitCandidate(VspOspTraversalData &tData, VspOspSplitCandidate &splitData); 412 405 413 406 /** Computes priority of the traversal data and stores it in tData. 414 407 */ 415 void EvalPriority(Vsp BspTraversalData &tData) const;408 void EvalPriority(VspOspTraversalData &tData) const; 416 409 417 410 /** Evaluates render cost decrease of next split. 418 411 */ 419 412 float EvalRenderCostDecrease(const Plane3 &candidatePlane, 420 const Vsp BspTraversalData &data) const;413 const VspOspTraversalData &data) const; 421 414 422 415 /** Constructs tree using the split priority queue. 423 416 */ 424 void Construct WithSplitQueue(const PolygonContainer &polys,RayInfoContainer *rays);417 void Construct(RayInfoContainer *rays); 425 418 426 419 /** Collects view cells in the subtree under root. … … 451 444 /** Evaluates tree stats in the BSP tree leafs. 452 445 */ 453 void EvaluateLeafStats(const Vsp BspTraversalData &data);446 void EvaluateLeafStats(const VspOspTraversalData &data); 454 447 455 448 /** Subdivides node with respect to the traversal data. … … 458 451 @returns new root of the subtree 459 452 */ 460 BspNode *Subdivide(VspBspTraversalQueue &tStack, 461 VspBspTraversalData &tData); 462 463 BspNode *Subdivide(VspBspSplitQueue &tQueue, 464 VspBspSplitCandidate &splitCandidate); 465 466 /** Constructs the tree from the given traversal data. 467 @param polys stores set of polygons on which subdivision may be based 468 @param rays storesset of rays on which subdivision may be based 469 */ 470 void Construct(const PolygonContainer &polys, RayInfoContainer *rays); 471 472 /** Selects the best possible splitting plane. 473 @param plane returns the split plane 474 @param leaf the leaf to be split 475 @param polys the polygon list on which the split decition is based 476 @param rays ray container on which selection may be based 477 @note the polygons can be reordered in the process 478 @returns true if the cost of the split is under maxCostRatio 479 480 */ 481 bool SelectPlane(Plane3 &plane, 482 BspLeaf *leaf, 483 VspBspTraversalData &data, 484 VspBspTraversalData &frontData, 485 VspBspTraversalData &backData, 486 int &splitAxis); 487 488 /** Strategies where the effect of the split plane is tested 489 on all input rays. 490 491 @returns the cost of the candidate split plane 492 */ 493 float EvalSplitPlaneCost(const Plane3 &candidatePlane, 494 const VspBspTraversalData &data, 495 BspNodeGeometry &geomFront, 496 BspNodeGeometry &geomBack, 497 float &pFront, 498 float &pBack) const; 499 453 BspNode *Subdivide(VspOspSplitQueue &tQueue, 454 VspOspSplitCandidate &splitCandidate); 455 456 500 457 /** Subdivides leaf. 501 458 @param leaf the leaf to be subdivided … … 513 470 514 471 BspInterior *SubdivideNode(const Plane3 &splitPlane, 515 VspBspTraversalData &tData, 516 VspBspTraversalData &frontData, 517 VspBspTraversalData &backData, 518 PolygonContainer &coincident); 519 520 /** Extracts the meshes of the objects and adds them to polygons. 521 Adds object aabb to the aabb of the tree. 522 @param maxPolys the maximal number of objects to be stored as polygons 523 @returns the number of polygons 524 */ 525 int AddToPolygonSoup(const ObjectContainer &objects, 526 PolygonContainer &polys, 527 int maxObjects = 0); 528 529 /** Extracts the meshes of the view cells and and adds them to polygons. 530 Adds view cell aabb to the aabb of the tree. 531 @param maxPolys the maximal number of objects to be stored as polygons 532 @returns the number of polygons 533 */ 534 int AddToPolygonSoup(const ViewCellContainer &viewCells, 535 PolygonContainer &polys, 536 int maxObjects = 0); 537 538 /** Extract polygons of this mesh and add to polygon container. 539 @param mesh the mesh that drives the polygon construction 540 @param parent the parent intersectable this polygon is constructed from 541 @returns number of polygons 542 */ 543 int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent); 472 VspOspTraversalData &tData, 473 VspOspTraversalData &frontData, 474 VspOspTraversalData &backData); 544 475 545 476 /** Selects an axis aligned for the next split. 546 477 @returns cost for this split 547 478 */ 548 float SelectAxisAlignedPlane(Plane3 &plane, 549 const VspBspTraversalData &tData, 550 int &axis, 551 BspNodeGeometry **frontGeom, 552 BspNodeGeometry **backGeom, 553 float &pFront, 554 float &pBack, 555 const bool useKdSplit); 479 float SelectPlane(const VspOspTraversalData &tData, 480 AxisAlignedPlane &plane, 481 float &pFront, 482 float &pBack); 556 483 557 484 /** Sorts split candidates for surface area heuristics for axis aligned splits. … … 573 500 float &position); 574 501 575 /** Selects an axis aligned split plane.576 @Returns true if split is valied577 */578 bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;579 580 502 /** Subdivides the rays into front and back rays according to the split plane. 581 503 … … 593 515 RayInfoContainer &backRays) const; 594 516 595 596 /** Extracts the split planes representing the space bounded by node n.597 */598 void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;599 600 517 /** Adds the object to the pvs of the front and back leaf with a given classification. 601 518 … … 618 535 /** Returns true if tree can be terminated. 619 536 */ 620 inline bool LocalTerminationCriteriaMet(const Vsp BspTraversalData &data) const;537 inline bool LocalTerminationCriteriaMet(const VspOspTraversalData &data) const; 621 538 622 539 /** Returns true if global tree can be terminated. 623 540 */ 624 inline bool GlobalTerminationCriteriaMet(const VspBspTraversalData &data) const; 625 626 /** Computes accumulated ray lenght of this rays. 627 */ 628 float AccumulatedRayLength(const RayInfoContainer &rays) const; 629 630 /** Splits polygons with respect to the split plane. 631 632 @param plane the split plane 633 @param polys the polygons to be split. the polygons are consumed and 634 distributed to the containers frontPolys, backPolys, coincident. 635 @param frontPolys returns the polygons in the front of the split plane 636 @param backPolys returns the polygons in the back of the split plane 637 @param coincident returns the polygons coincident to the split plane 638 639 @returns the number of splits 640 */ 641 int SplitPolygons(const Plane3 &plane, 642 PolygonContainer &polys, 643 PolygonContainer &frontPolys, 644 PolygonContainer &backPolys, 645 PolygonContainer &coincident) const; 541 inline bool GlobalTerminationCriteriaMet(const VspOspTraversalData &data) const; 646 542 647 543 /** Adds ray sample contributions to the PVS. … … 655 551 int &contributingSamples); 656 552 657 658 659 660 661 662 /** Take 3 ray endpoints, where two are minimum and one a maximum663 point or the other way round.664 */665 Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;666 667 /** Take plane normal as plane normal and the midpoint of the ray.668 PROBLEM: does not resemble any point where visibility is669 likely to change670 */671 Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;672 673 /** Fit the plane between the two lines so that the plane674 has equal shortest distance to both lines.675 */676 Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;677 678 /** Collects candidates for merging.679 @param leaves the leaves to be merged680 @returns number of leaves in queue681 */682 int CollectMergeCandidates(const vector<BspLeaf *> leaves, vector<MergeCandidate> &candidates);683 684 /** Collects candidates for the merge in the merge queue.685 @returns number of leaves in queue686 */687 int CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);688 689 /** Preprocesses polygons and throws out all polygons which are coincident to690 the view space box faces (they can be problematic).691 */692 void PreprocessPolygons(PolygonContainer &polys);693 694 553 /** Propagates valid flag up the tree. 695 554 */ … … 707 566 /** Returns estimated memory usage of tree. 708 567 */ 709 //float GetMemUsage(const VspBspTraversalQueue &tstack) const;710 568 float GetMemUsage() const; 711 569 712 570 571 protected: 572 573 ViewCellsManager *mViewCellsManager; 574 vector<SortableEntry> *mSplitCandidates; 713 575 714 576 /// Pointer to the root of the tree … … 716 578 717 579 BspTreeStatistics mBspStats; 718 719 /// Strategies for choosing next split plane. 720 enum {NO_STRATEGY = 0, 721 RANDOM_POLYGON = 1, 722 AXIS_ALIGNED = 2, 723 LEAST_RAY_SPLITS = 256, 724 BALANCED_RAYS = 512, 725 PVS = 1024 726 }; 580 581 /// View cell corresponding to the space outside the valid view space 582 BspViewCell *mOutOfBoundsCell; 727 583 728 584 /// box around the whole view domain 729 585 AxisAlignedBox3 mBox; 730 586 731 bool mUseCostHeuristics; 587 588 589 //-- local termination 732 590 733 591 /// minimal number of rays before subdivision termination … … 741 599 /// maximal contribution per ray 742 600 float mTermMaxRayContribution; 743 /// minimal accumulated ray length744 float mTermMinAccRayLength;745 746 //HACK747 int mTermMinPolygons;748 749 float mTermMinGlobalCostRatio;750 int mTermGlobalCostMissTolerance;751 752 int mGlobalCostMisses;753 754 bool mUseSplitCostQueue;755 //-- termination criteria for axis aligned split756 757 /// minimal number of rays for axis aligned split758 int mTermMinRaysForAxisAligned;759 // max ray contribution760 float mTermMaxRayContriForAxisAligned;761 762 /// strategy to get the best split plane763 int mSplitPlaneStrategy;764 /// number of candidates evaluated for the next split plane765 int mMaxPolyCandidates;766 /// number of candidates for split planes evaluated using the rays767 int mMaxRayCandidates;768 /// balancing factor for PVS criterium769 float mCtDivCi;770 771 bool mUseDrivingAxisForMaxCost;772 //-- axis aligned split criteria773 float mAxisAlignedCtDivCi;774 /// spezifies the split border of the axis aligned split775 float mAxisAlignedSplitBorder;776 777 601 /// maximal acceptable cost ratio 778 602 float mTermMaxCostRatio; … … 780 604 int mTermMissTolerance; 781 605 782 //-- factors guiding the split plane heuristics 783 float mLeastRaySplitsFactor; 784 float mBalancedRaysFactor; 785 float mPvsFactor; 786 787 /// if area or volume should be used for PVS heuristics 788 bool mUseAreaForPvs; 789 /// tolerance for polygon split 790 float mEpsilon; 791 /// maximal number of test rays used to evaluate candidate split plane 792 int mMaxTests; 793 /// normalizes different bsp split plane criteria 794 float mCostNormalizer; 606 607 //-- global criteria 608 float mTermMinGlobalCostRatio; 609 int mTermGlobalCostMissTolerance; 610 int mGlobalCostMisses; 611 795 612 /// maximal number of view cells 796 613 int mMaxViewCells; 797 798 ofstream mSubdivisionStats;799 800 // if rays should be stored in leaves801 bool mStoreRays;802 803 /// if only driving axis should be used for split804 bool mOnlyDrivingAxis;805 806 ViewCellsManager *mViewCellsManager;807 808 vector<SortableEntry> *mSplitCandidates;809 810 811 float mRenderCostWeight;812 /// View cell corresponding to the space outside the valid view space813 BspViewCell *mOutOfBoundsCell;814 815 614 /// maximal tree memory 816 615 float mMaxMemory; 817 616 /// the tree is out of memory 818 617 bool mOutOfMemory; 819 820 float mTotalCost; 821 int mTotalPvsSize; 822 823 float mMinBand;824 float mMaxBand;825 826 //int mSplits;827 /// subdivision stats output file828 ofstream mSubdivsionStats;618 619 620 621 //-- split heuristics based parameters 622 623 bool mUseCostHeuristics; 624 /// balancing factor for PVS criterium 625 float mCtDivCi; 626 /// if only driving axis should be used for split 627 bool mOnlyDrivingAxis; 829 628 /// if random split axis should be used 830 629 bool mUseRandomAxis; 831 /// use polygon split whenever there are polys left 832 bool mUsePolygonSplitIfAvailable; 630 /// if vsp bsp tree should simulate octree 631 bool mCirculatingAxis; 632 /// minimal relative position where the split axis can be placed 633 float mMinBand; 634 /// maximal relative position where the split axis can be placed 635 float mMaxBand; 636 637 833 638 /// current time stamp (used for keeping split history) 834 639 int mTimeStamp; 640 // if rays should be stored in leaves 641 bool mStoreRays; 642 643 /// epsilon for geometric comparisons 644 float mEpsilon; 645 646 /// if we should use breath first priority for the splits 647 int mNodePriorityQueueType; 648 649 // priority queue strategy 650 enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED}; 651 652 653 /// subdivision stats output file 654 ofstream mSubdivisionStats; 655 /// keeps track of cost during subdivision 656 float mTotalCost; 657 /// keeps track of overall pvs size during subdivision 658 int mTotalPvsSize; 835 659 /// number of currenly generated view cells 836 660 int mCreatedViewCells; 837 /// if vsp bsp tree should simulate octree 838 bool mCirculatingAxis; 839 840 /// if we should use breath first priority for the splits 841 int mNodePriorityQueueType; 842 843 bool mEmptyViewCellsMergeAllowed; 844 845 // priority queue strategy 846 enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED}; 661 847 662 private: 848 663 -
GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp
r1004 r1006 9 9 #include "Polygon3.h" 10 10 #include "VssRay.h" 11 #include "VspKdTree.h"11 //#include "VspOspTree.h" 12 12 #include "VssTree.h" 13 13 #include "VspBspTree.h" … … 33 33 stream.close(); 34 34 } 35 36 37 // bool38 // X3dExporter::ExportRays(const vector<Ray> &rays,39 // const float length,40 // const RgbColor &color)41 // {42 // vector<Ray>::const_iterator ri = rays.begin();43 // stream<<"<Shape>"<<endl;44 // stream<<"<Appearance>"<<endl;45 // stream<<"<Material ambientColor=\""<<color.r<<" "<<color.g<<" "<<color.b<<46 // "\" />"<<endl;47 // stream<<"</Appearance>"<<endl;48 49 // stream<<"<IndexedLineSet coordIndex=\""<<endl;50 51 // int index = 0;52 // for (; ri != rays.end(); ri++) {53 // stream<<index<<" "<<index+1<<" -1\n";54 // index+=2;55 // }56 57 // stream<<"\" >"<<endl;58 59 // stream<<"<Coordinate point=\""<<endl;60 61 // ri = rays.begin();62 // for (; ri != rays.end(); ri++) {63 // Vector3 a = (*ri).GetLoc();64 65 // Vector3 b;66 // if (length < 0)67 // b = (*ri).GetLoc() - length*(*ri).GetDir();68 // else69 // if ((*ri).intersections.size()==0)70 // b = (*ri).GetLoc() + length*(*ri).GetDir();71 // else72 // b = (*ri).Extrap((*ri).intersections[0].mT);73 74 // stream<<a.x<<" "<<a.y<<" "<<a.z<<" ,";75 // stream<<b.x<<" "<<b.y<<" "<<b.z<<" ,\n";76 // }77 78 // stream<<"\" >"<<endl;79 // stream<<"</Coordinate>"<<endl;80 // stream<<"</IndexedLineSet>"<<endl;81 // stream<<"</Shape>"<<endl;82 // return true;83 // }84 35 85 36 … … 459 410 460 411 412 461 413 void X3dExporter::ExportPolygons(const PolygonContainer &polys) 462 414 { … … 535 487 stream << "</Shape>" << endl; 536 488 } 489 537 490 538 491 bool … … 561 514 } 562 515 516 563 517 bool 564 518 X3dExporter::ExportBspTree(const BspTree &tree) … … 584 538 } 585 539 586 bool X3dExporter::ExportVspKdTree(const VspKdTree &tree, const int maxPvs) 540 #if 0 541 bool X3dExporter::ExportVspOspTree(const VspOspTree &tree, const int maxPvs) 587 542 { 588 543 stack<VspKdNode *> tStack; … … 654 609 return true; 655 610 } 656 611 #endif 657 612 658 613 bool X3dExporter::ExportKdTree(const KdTree &tree) … … 696 651 ExportMesh(mesh); 697 652 delete mesh; 653 698 654 return true; 699 // TODO700 return true;701 655 } 702 656 -
GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.h
r1001 r1006 59 59 const Vector3 direction 60 60 ); 61 61 #if VSP_OPS 62 62 bool 63 ExportVsp KdTree(const VspKdTree &tree, const int maxPvs);64 63 ExportVspOspTree(const VspOspTree &tree, const int maxPvs); 64 #endif 65 65 bool ExportBspTree(const BspTree &tree); 66 66
Note: See TracChangeset
for help on using the changeset viewer.