Changeset 1016 for GTP/trunk/Lib/Vis
- Timestamp:
- 06/14/06 11:02:34 (19 years ago)
- Location:
- GTP/trunk/Lib/Vis/Preprocessing/src
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp
r1004 r1016 1709 1709 inline void BspTree::GenerateUniqueIdsForPvs() 1710 1710 { 1711 ViewCell::NewMail(); sBackId = ViewCell::sMailId;1712 ViewCell::NewMail(); sFrontId = ViewCell::sMailId;1713 ViewCell::NewMail(); sFrontAndBackId = ViewCell::sMailId;1711 Intersectable::NewMail(); sBackId = Intersectable::sMailId; 1712 Intersectable::NewMail(); sFrontId = Intersectable::sMailId; 1713 Intersectable::NewMail(); sFrontAndBackId = Intersectable::sMailId; 1714 1714 } 1715 1715 … … 1736 1736 const bool pvsUseLen = false; 1737 1737 1738 1738 1739 if (mSplitPlaneStrategy & PVS) 1739 1740 { -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
r1012 r1016 482 482 483 483 484 485 484 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays) 486 485 { 487 486 VspBspTraversalQueue tQueue; 488 487 488 /// create new vsp tree 489 489 mRoot = new BspLeaf(); 490 490 … … 493 493 ConstructGeometry(mRoot, *geom); 494 494 495 /// we use the overall probability as normalizer 496 /// either the overall area or the volume 495 497 const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(); 496 498 … … 518 520 mTotalPvsSize = tData.mPvs; 519 521 522 // first stats 520 523 mSubdivisionStats 521 524 << "#ViewCells\n1" << endl … … 525 528 526 529 Debug << "total cost: " << mTotalCost << endl; 527 528 530 531 529 532 mBspStats.Start(); 530 533 cout << "Constructing vsp bsp tree ... \n"; 531 534 532 long startTime = GetTime(); 535 const long startTime = GetTime(); 536 // used for intermediate time measurements and progress 537 long interTime = GetTime(); 538 533 539 int nLeaves = 500; 534 540 int nViewCells = 500; 535 541 536 // used for intermediate time measurements and progress537 long interTime = GetTime();538 539 542 mOutOfMemory = false; 540 541 543 mCreatedViewCells = 0; 542 544 … … 558 560 559 561 // subdivide leaf node 560 BspNode *r = Subdivide(tQueue, tData);562 const BspNode *r = Subdivide(tQueue, tData); 561 563 562 564 if (r == mRoot) -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
r1006 r1016 130 130 {} 131 131 132 /** Returns costof the traversal data.132 /** Returns priority of the traversal data. 133 133 */ 134 134 float GetCost() const … … 167 167 // parent data 168 168 VspBspTraversalData mParentData; 169 // cost of applyingthis split169 // prioriry of this split 170 170 float mRenderCost; 171 171 … … 183 183 #if 1 184 184 return mRenderCost; 185 #endif 186 #if 0 185 #else 187 186 return (float) (-mDepth); // for kd tree 188 187 #endif … … 221 220 a certain threshold. 222 221 @param onlyUnmailed if only the unmailed leaves should be considered 223 @param maxPvs the maximal pvs (-1 means unlimited)222 @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited) 224 223 */ 225 224 void CollectLeaves(vector<BspLeaf *> &leaves, … … 359 358 int ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const; 360 359 361 // pointer to the hierarchy of view cells360 /// pointer to the hierarchy of view cells 362 361 ViewCellsTree *mViewCellsTree; 363 362 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
r1015 r1016 24 24 //-- static members 25 25 26 int Vsp OspTree::sFrontId = 0;27 int Vsp OspTree::sBackId = 0;28 int Vsp OspTree::sFrontAndBackId = 0;26 int VspTree::sFrontId = 0; 27 int VspTree::sBackId = 0; 28 int VspTree::sFrontAndBackId = 0; 29 29 30 30 … … 184 184 185 185 186 AxisAlignedBox3 VspInterior::GetBo x() const187 { 188 return mBo x;189 } 190 191 192 void VspInterior::SetBo x(const AxisAlignedBox3 &box)193 { 194 mBo x = box;186 AxisAlignedBox3 VspInterior::GetBoundingBox() const 187 { 188 return mBoundingBox; 189 } 190 191 192 void VspInterior::SetBoundingBox(const AxisAlignedBox3 &box) 193 { 194 mBoundingBox = box; 195 195 } 196 196 … … 258 258 259 259 /******************************************************************************/ 260 /* class Vsp OspTree implementation */260 /* class VspTree implementation */ 261 261 /******************************************************************************/ 262 262 263 263 264 Vsp OspTree::VspOspTree():264 VspTree::VspTree(): 265 265 mRoot(NULL), 266 266 mOutOfBoundsCell(NULL), … … 270 270 { 271 271 bool randomize = false; 272 Environment::GetSingleton()->GetBoolValue("Vsp OspTree.Construction.randomize", randomize);272 Environment::GetSingleton()->GetBoolValue("VspTree.Construction.randomize", randomize); 273 273 if (randomize) 274 274 Randomize(); // initialise random generator for heuristics 275 275 276 276 //-- termination criteria for autopartition 277 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.maxDepth", mTermMaxDepth);278 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.minPvs", mTermMinPvs);279 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.minRays", mTermMinRays);280 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.minProbability", mTermMinProbability);281 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.maxRayContribution", mTermMaxRayContribution);282 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.maxCostRatio", mTermMaxCostRatio);283 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.missTolerance", mTermMissTolerance);284 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.maxViewCells", mMaxViewCells);277 Environment::GetSingleton()->GetIntValue("VspTree.Termination.maxDepth", mTermMaxDepth); 278 Environment::GetSingleton()->GetIntValue("VspTree.Termination.minPvs", mTermMinPvs); 279 Environment::GetSingleton()->GetIntValue("VspTree.Termination.minRays", mTermMinRays); 280 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.minProbability", mTermMinProbability); 281 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.maxRayContribution", mTermMaxRayContribution); 282 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.maxCostRatio", mTermMaxCostRatio); 283 Environment::GetSingleton()->GetIntValue("VspTree.Termination.missTolerance", mTermMissTolerance); 284 Environment::GetSingleton()->GetIntValue("VspTree.Termination.maxViewCells", mMaxViewCells); 285 285 286 286 //-- max cost ratio for early tree termination 287 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.maxCostRatio", mTermMaxCostRatio);288 289 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);290 Environment::GetSingleton()->GetIntValue("Vsp OspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);287 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.maxCostRatio", mTermMaxCostRatio); 288 289 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio); 290 Environment::GetSingleton()->GetIntValue("VspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance); 291 291 292 292 // HACK//mTermMinPolygons = 25; 293 293 294 294 //-- factors for bsp tree split plane heuristics 295 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Termination.ct_div_ci", mCtDivCi);295 Environment::GetSingleton()->GetFloatValue("VspTree.Termination.ct_div_ci", mCtDivCi); 296 296 297 297 //-- partition criteria 298 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Construction.epsilon", mEpsilon);298 Environment::GetSingleton()->GetFloatValue("VspTree.Construction.epsilon", mEpsilon); 299 299 300 300 // if only the driving axis is used for axis aligned split 301 Environment::GetSingleton()->GetBoolValue("Vsp OspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis);302 303 //Environment::GetSingleton()->GetFloatValue("Vsp OspTree.maxTotalMemory", mMaxTotalMemory);304 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.maxStaticMemory", mMaxMemory);305 306 Environment::GetSingleton()->GetBoolValue("Vsp OspTree.useCostHeuristics", mUseCostHeuristics);307 Environment::GetSingleton()->GetBoolValue("Vsp OspTree.simulateOctree", mCirculatingAxis);308 Environment::GetSingleton()->GetBoolValue("Vsp OspTree.useRandomAxis", mUseRandomAxis);309 Environment::GetSingleton()->GetIntValue("Vsp OspTree.nodePriorityQueueType", mNodePriorityQueueType);301 Environment::GetSingleton()->GetBoolValue("VspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis); 302 303 //Environment::GetSingleton()->GetFloatValue("VspTree.maxTotalMemory", mMaxTotalMemory); 304 Environment::GetSingleton()->GetFloatValue("VspTree.maxStaticMemory", mMaxMemory); 305 306 Environment::GetSingleton()->GetBoolValue("VspTree.useCostHeuristics", mUseCostHeuristics); 307 Environment::GetSingleton()->GetBoolValue("VspTree.simulateOctree", mCirculatingAxis); 308 Environment::GetSingleton()->GetBoolValue("VspTree.useRandomAxis", mUseRandomAxis); 309 Environment::GetSingleton()->GetIntValue("VspTree.nodePriorityQueueType", mNodePriorityQueueType); 310 310 311 311 char subdivisionStatsLog[100]; 312 Environment::GetSingleton()->GetStringValue("Vsp OspTree.subdivisionStats", subdivisionStatsLog);312 Environment::GetSingleton()->GetStringValue("VspTree.subdivisionStats", subdivisionStatsLog); 313 313 mSubdivisionStats.open(subdivisionStatsLog); 314 314 315 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Construction.minBand", mMinBand);316 Environment::GetSingleton()->GetFloatValue("Vsp OspTree.Construction.maxBand", mMaxBand);315 Environment::GetSingleton()->GetFloatValue("VspTree.Construction.minBand", mMinBand); 316 Environment::GetSingleton()->GetFloatValue("VspTree.Construction.maxBand", mMaxBand); 317 317 318 318 … … 349 349 350 350 351 VspViewCell *Vsp OspTree::GetOutOfBoundsCell()351 VspViewCell *VspTree::GetOutOfBoundsCell() 352 352 { 353 353 return mOutOfBoundsCell; … … 355 355 356 356 357 VspViewCell *Vsp OspTree::GetOrCreateOutOfBoundsCell()357 VspViewCell *VspTree::GetOrCreateOutOfBoundsCell() 358 358 { 359 359 if (!mOutOfBoundsCell) … … 368 368 369 369 370 const VspTreeStatistics &Vsp OspTree::GetStatistics() const370 const VspTreeStatistics &VspTree::GetStatistics() const 371 371 { 372 372 return mVspStats; … … 374 374 375 375 376 Vsp OspTree::~VspOspTree()376 VspTree::~VspTree() 377 377 { 378 378 DEL_PTR(mRoot); … … 381 381 382 382 383 void Vsp OspTree::Construct(const VssRayContainer &sampleRays,383 void VspTree::Construct(const VssRayContainer &sampleRays, 384 384 AxisAlignedBox3 *forcedBoundingBox) 385 385 { … … 437 437 438 438 // TODO: return memory usage in MB 439 float Vsp OspTree::GetMemUsage() const439 float VspTree::GetMemUsage() const 440 440 { 441 441 return (float) 442 (sizeof(Vsp OspTree) +442 (sizeof(VspTree) + 443 443 mVspStats.Leaves() * sizeof(VspLeaf) + 444 444 mCreatedViewCells * sizeof(VspViewCell) + … … 449 449 450 450 451 void VspOspTree::Construct(RayInfoContainer *rays) 452 { 453 VspOspSplitQueue tQueue; 454 451 void VspTree::Construct(RayInfoContainer *rays) 452 { 453 #if TODO 454 VspSplitQueue tQueue; 455 /// create new vsp tree 455 456 mRoot = new VspLeaf(); 456 457 /// we use the overall probability as normalizer 457 458 const float prop = mBox.GetVolume(); 458 459 459 Vsp OspTraversalData tData(mRoot,460 461 462 463 464 460 VspTraversalData tData(mRoot, 461 0, 462 rays, 463 ComputePvsSize(*rays), 464 prop, 465 mBox); 465 466 466 467 467 468 // compute first split candidate 468 Vsp OspSplitCandidate splitCandidate;469 VspSplitCandidate splitCandidate; 469 470 EvalSplitCandidate(tData, splitCandidate); 470 471 … … 552 553 553 554 mVspStats.Stop(); 554 } 555 556 557 bool VspOspTree::LocalTerminationCriteriaMet(const VspOspTraversalData &data) const 555 #endif 556 } 557 558 559 bool VspTree::LocalTerminationCriteriaMet(const VspTraversalData &data) const 558 560 { 559 561 return … … 566 568 567 569 568 bool Vsp OspTree::GlobalTerminationCriteriaMet(const VspOspTraversalData &data) const570 bool VspTree::GlobalTerminationCriteriaMet(const VspTraversalData &data) const 569 571 { 570 572 return … … 576 578 577 579 // subdivide using a split plane queue 578 VspNode *Vsp OspTree::Subdivide(VspOspSplitQueue &tQueue,579 VspOspSplitCandidate &splitCandidate)580 { 581 Vsp OspTraversalData &tData = splitCandidate.mParentData;580 VspNode *VspTree::Subdivide(SplitQueue &tQueue, 581 VspSplitCandidate &splitCandidate) 582 { 583 VspTraversalData &tData = splitCandidate.mParentData; 582 584 583 585 VspNode *newNode = tData.mNode; … … 585 587 if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData)) 586 588 { 587 Vsp OspTraversalData tFrontData;588 Vsp OspTraversalData tBackData;589 VspTraversalData tFrontData; 590 VspTraversalData tBackData; 589 591 590 592 //-- continue subdivision … … 619 621 << "#ViewCells\n" << mVspStats.Leaves() << endl 620 622 << "#RenderCostDecrease\n" << -costDecr << endl 621 << "#SplitCandidateCost\n" << splitCandidate.Get Cost() << endl623 << "#SplitCandidateCost\n" << splitCandidate.GetPriority() << endl 622 624 << "#TotalRenderCost\n" << mTotalCost << endl 623 625 << "#AvgRenderCost\n" << (float)mTotalPvsSize / (float)mVspStats.Leaves() << endl; … … 626 628 627 629 //-- push the new split candidates on the stack 628 Vsp OspSplitCandidate frontCandidate;629 Vsp OspSplitCandidate backCandidate;630 VspSplitCandidate frontCandidate; 631 VspSplitCandidate backCandidate; 630 632 631 633 EvalSplitCandidate(tFrontData, frontCandidate); 632 634 EvalSplitCandidate(tBackData, backCandidate); 633 635 #if TODO 634 636 tQueue.push(frontCandidate); 635 637 tQueue.push(backCandidate); 636 638 #endif 637 639 // delete old leaf node 638 640 DEL_PTR(tData.mNode); … … 686 688 687 689 688 void Vsp OspTree::EvalSplitCandidate(VspOspTraversalData &tData,689 VspOspSplitCandidate &splitData)690 { 691 Vsp OspTraversalData frontData;692 Vsp OspTraversalData backData;690 void VspTree::EvalSplitCandidate(VspTraversalData &tData, 691 VspSplitCandidate &splitData) 692 { 693 VspTraversalData frontData; 694 VspTraversalData backData; 693 695 694 696 VspLeaf *leaf = dynamic_cast<VspLeaf *>(tData.mNode); … … 701 703 //TODO 702 704 // compute global decrease in render cost 703 splitData.m RenderCost= EvalRenderCostDecrease(splitData.mSplitPlane, tData);705 splitData.mPriority = EvalRenderCostDecrease(splitData.mSplitPlane, tData); 704 706 splitData.mParentData = tData; 705 707 splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1; … … 707 709 708 710 709 VspInterior *Vsp OspTree::SubdivideNode(const AxisAlignedPlane &splitPlane,710 VspOspTraversalData &tData,711 VspOspTraversalData &frontData,712 VspOspTraversalData &backData)711 VspInterior *VspTree::SubdivideNode(const AxisAlignedPlane &splitPlane, 712 VspTraversalData &tData, 713 VspTraversalData &frontData, 714 VspTraversalData &backData) 713 715 { 714 716 VspLeaf *leaf = dynamic_cast<VspLeaf *>(tData.mNode); … … 777 779 // and setup child links 778 780 interior->SetupChildLinks(new VspLeaf(interior), new VspLeaf(interior)); 781 // add bounding box 782 interior->SetBoundingBox(tData.mBoundingBox); 779 783 780 784 frontData.mNode = interior->GetFront(); … … 786 790 } 787 791 788 789 void VspOspTree::AddToPvs(VspLeaf *leaf, 792 /* 793 KdNode *VspOpsTree::SubdivideSpatialNode(KdLeaf *leaf, 794 const AxisAlignedPlane &splitPlane, 795 const AxisAlignedBox3 &box, 796 AxisAlignedBox3 &backBBox, 797 AxisAlignedBox3 &frontBBox) 798 { 799 float position; 800 801 #if TODO 802 mSpatialStat.nodes += 2; 803 mSpatialStat.splits[axis]; 804 #endif 805 806 // add the new nodes to the tree 807 KdInterior *node = new KdInterior(leaf->mParent); 808 809 node->mAxis = splitPlane.mAxis; 810 node->mPosition = splitPlane.mPosition; 811 node->mBox = box; 812 813 backBBox = box; 814 frontBBox = box; 815 816 // first count ray sides 817 int objectsBack = 0; 818 int objectsFront = 0; 819 820 backBBox.SetMax(axis, position); 821 frontBBox.SetMin(axis, position); 822 823 SplitObjects(leaf->m 824 ObjectContainer::const_iterator mi, mi_end = leaf->mObjects.end(); 825 826 for ( mi = leaf->mObjects.begin(); mi != mi_end; ++ mi) 827 { 828 // determine the side of this ray with respect to the plane 829 AxisAlignedBox3 box = (*mi)->GetBox(); 830 831 if (box.Max(axis) > position ) 832 ++ objectsFront; 833 834 if (box.Min(axis) < position ) 835 objectsBack++; 836 } 837 838 839 KdLeaf *back = new KdLeaf(node, objectsBack); 840 KdLeaf *front = new KdLeaf(node, objectsFront); 841 842 // replace a link from node's parent 843 if ( leaf->mParent ) 844 leaf->mParent->ReplaceChildLink(leaf, node); 845 846 // and setup child links 847 node->SetupChildLinks(back, front); 848 849 for (mi = leaf->mObjects.begin(); 850 mi != leaf->mObjects.end(); 851 mi++) { 852 // determine the side of this ray with respect to the plane 853 AxisAlignedBox3 box = (*mi)->GetBox(); 854 855 if (box.Max(axis) >= position ) 856 front->mObjects.push_back(*mi); 857 858 if (box.Min(axis) < position ) 859 back->mObjects.push_back(*mi); 860 861 mStat.objectRefs -= (int)leaf->mObjects.size(); 862 mStat.objectRefs += objectsBack + objectsFront; 863 } 864 865 delete leaf; 866 return node; 867 } 868 */ 869 870 871 872 void VspTree::AddToPvs(VspLeaf *leaf, 790 873 const RayInfoContainer &rays, 791 874 float &sampleContributions, … … 832 915 833 916 834 void Vsp OspTree::SortSplitCandidates(const RayInfoContainer &rays,917 void VspTree::SortSplitCandidates(const RayInfoContainer &rays, 835 918 const int axis, 836 919 float minBand, … … 883 966 884 967 885 float Vsp OspTree::BestCostRatioHeuristics(const RayInfoContainer &rays,968 float VspTree::BestCostRatioHeuristics(const RayInfoContainer &rays, 886 969 const AxisAlignedBox3 &box, 887 970 const int pvsSize, … … 1055 1138 1056 1139 1057 float Vsp OspTree::SelectPlane(const VspOspTraversalData &tData,1058 1059 1060 1140 float VspTree::SelectPlane(const VspTraversalData &tData, 1141 AxisAlignedPlane &plane, 1142 float &pFront, 1143 float &pBack) 1061 1144 { 1062 1145 float nPosition[3]; … … 1134 1217 1135 1218 1136 inline void Vsp OspTree::GenerateUniqueIdsForPvs()1219 inline void VspTree::GenerateUniqueIdsForPvs() 1137 1220 { 1138 1221 Intersectable::NewMail(); sBackId = Intersectable::sMailId; … … 1142 1225 1143 1226 1144 float Vsp OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,1145 const VspOspTraversalData &data) const1227 float VspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 1228 const VspTraversalData &data) const 1146 1229 { 1147 1230 float pvsFront = 0; … … 1158 1241 GenerateUniqueIdsForPvs(); 1159 1242 1160 RayInfoContainer::const_iterator rit, rit_end = data.mRays .end();1161 1162 for (rit = data.mRays .begin(); rit != rit_end; ++ rit)1243 RayInfoContainer::const_iterator rit, rit_end = data.mRays->end(); 1244 1245 for (rit = data.mRays->begin(); rit != rit_end; ++ rit) 1163 1246 { 1164 1247 RayInfo rayInf = *rit; … … 1210 1293 1211 1294 1212 1213 float VspOspTree::EvalSplitCost(const VspOspTraversalData &data, 1214 const AxisAlignedBox3 &box, 1215 const int axis, 1216 const float &position, 1217 float &pFront, 1218 float &pBack) const 1295 float VspTree::EvalSplitCost(const VspTraversalData &data, 1296 const AxisAlignedBox3 &box, 1297 const int axis, 1298 const float &position, 1299 float &pFront, 1300 float &pBack) const 1219 1301 { 1220 1302 float pvsTotal = 0; … … 1263 1345 1264 1346 1265 void Vsp OspTree::AddObjToPvs(Intersectable *obj,1347 void VspTree::AddObjToPvs(Intersectable *obj, 1266 1348 const int cf, 1267 1349 float &frontPvs, … … 1316 1398 1317 1399 1318 void Vsp OspTree::CollectLeaves(vector<VspLeaf *> &leaves,1400 void VspTree::CollectLeaves(vector<VspLeaf *> &leaves, 1319 1401 const bool onlyUnmailed, 1320 1402 const int maxPvsSize) const … … 1350 1432 1351 1433 1352 AxisAlignedBox3 Vsp OspTree::GetBoundingBox() const1434 AxisAlignedBox3 VspTree::GetBoundingBox() const 1353 1435 { 1354 1436 return mBox; … … 1356 1438 1357 1439 1358 VspNode *Vsp OspTree::GetRoot() const1440 VspNode *VspTree::GetRoot() const 1359 1441 { 1360 1442 return mRoot; … … 1362 1444 1363 1445 1364 void Vsp OspTree::EvaluateLeafStats(const VspOspTraversalData &data)1446 void VspTree::EvaluateLeafStats(const VspTraversalData &data) 1365 1447 { 1366 1448 // the node became a leaf -> evaluate stats for leafs … … 1418 1500 1419 1501 1420 void Vsp OspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const1502 void VspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const 1421 1503 { 1422 1504 ViewCell::NewMail(); … … 1425 1507 1426 1508 1427 void Vsp OspTree::CollapseViewCells()1509 void VspTree::CollapseViewCells() 1428 1510 { 1429 1511 // TODO … … 1480 1562 1481 1563 1482 void Vsp OspTree::CollectRays(VssRayContainer &rays)1564 void VspTree::CollectRays(VssRayContainer &rays) 1483 1565 { 1484 1566 vector<VspLeaf *> leaves; … … 1497 1579 1498 1580 1499 void Vsp OspTree::ValidateTree()1581 void VspTree::ValidateTree() 1500 1582 { 1501 1583 stack<VspNode *> nodeStack; … … 1540 1622 1541 1623 1542 void Vsp OspTree::CollectViewCells(VspNode *root,1624 void VspTree::CollectViewCells(VspNode *root, 1543 1625 bool onlyValid, 1544 1626 ViewCellContainer &viewCells, … … 1584 1666 1585 1667 1586 int Vsp OspTree::FindNeighbors(VspLeaf *n,1668 int VspTree::FindNeighbors(VspLeaf *n, 1587 1669 vector<VspLeaf *> &neighbors, 1588 1670 const bool onlyUnmailed) const … … 1631 1713 1632 1714 // Find random neighbor which was not mailed 1633 VspLeaf *Vsp OspTree::GetRandomLeaf(const Plane3 &plane)1715 VspLeaf *VspTree::GetRandomLeaf(const Plane3 &plane) 1634 1716 { 1635 1717 stack<VspNode *> nodeStack; … … 1676 1758 1677 1759 1678 VspLeaf *Vsp OspTree::GetRandomLeaf(const bool onlyUnmailed)1760 VspLeaf *VspTree::GetRandomLeaf(const bool onlyUnmailed) 1679 1761 { 1680 1762 stack<VspNode *> nodeStack; … … 1712 1794 1713 1795 1714 int Vsp OspTree::ComputePvsSize(const RayInfoContainer &rays) const1796 int VspTree::ComputePvsSize(const RayInfoContainer &rays) const 1715 1797 { 1716 1798 int pvsSize = 0; … … 1746 1828 1747 1829 1748 float Vsp OspTree::GetEpsilon() const1830 float VspTree::GetEpsilon() const 1749 1831 { 1750 1832 return mEpsilon; … … 1752 1834 1753 1835 1754 int Vsp OspTree::CastLineSegment(const Vector3 &origin,1836 int VspTree::CastLineSegment(const Vector3 &origin, 1755 1837 const Vector3 &termination, 1756 1838 ViewCellContainer &viewcells) … … 1855 1937 1856 1938 1857 int Vsp OspTree::CastRay(Ray &ray)1939 int VspTree::CastRay(Ray &ray) 1858 1940 { 1859 1941 int hits = 0; … … 1961 2043 1962 2044 1963 VspNode *Vsp OspTree::CollapseTree(VspNode *node, int &collapsed)2045 VspNode *VspTree::CollapseTree(VspNode *node, int &collapsed) 1964 2046 { 1965 2047 // TODO … … 2003 2085 2004 2086 2005 int Vsp OspTree::CollapseTree()2087 int VspTree::CollapseTree() 2006 2088 { 2007 2089 int collapsed = 0; … … 2017 2099 2018 2100 2019 void Vsp OspTree::RepairViewCellsLeafLists()2101 void VspTree::RepairViewCellsLeafLists() 2020 2102 { 2021 2103 // TODO … … 2061 2143 2062 2144 2063 ViewCell *Vsp OspTree::GetViewCell(const Vector3 &point, const bool active)2145 ViewCell *VspTree::GetViewCell(const Vector3 &point, const bool active) 2064 2146 { 2065 2147 if (mRoot == NULL) … … 2100 2182 2101 2183 2102 bool Vsp OspTree::ViewPointValid(const Vector3 &viewPoint) const2184 bool VspTree::ViewPointValid(const Vector3 &viewPoint) const 2103 2185 { 2104 2186 VspNode *node = mRoot; … … 2130 2212 2131 2213 2132 void Vsp OspTree::PropagateUpValidity(VspNode *node)2214 void VspTree::PropagateUpValidity(VspNode *node) 2133 2215 { 2134 2216 const bool isValid = node->TreeValid(); … … 2159 2241 2160 2242 #if ZIPPED_VIEWCELLS 2161 bool Vsp OspTree::Export(ogzstream &stream)2243 bool VspTree::Export(ogzstream &stream) 2162 2244 #else 2163 bool Vsp OspTree::Export(ofstream &stream)2245 bool VspTree::Export(ofstream &stream) 2164 2246 #endif 2165 2247 { … … 2171 2253 2172 2254 #if ZIPPED_VIEWCELLS 2173 void Vsp OspTree::ExportNode(VspNode *node, ogzstream &stream)2255 void VspTree::ExportNode(VspNode *node, ogzstream &stream) 2174 2256 #else 2175 void Vsp OspTree::ExportNode(VspNode *node, ofstream &stream)2257 void VspTree::ExportNode(VspNode *node, ofstream &stream) 2176 2258 #endif 2177 2259 { … … 2203 2285 2204 2286 2205 int Vsp OspTree::SplitRays(const AxisAlignedPlane &plane,2287 int VspTree::SplitRays(const AxisAlignedPlane &plane, 2206 2288 RayInfoContainer &rays, 2207 2289 RayInfoContainer &frontRays, … … 2253 2335 2254 2336 2255 AxisAlignedBox3 Vsp OspTree::GetBBox(VspNode *node) const2337 AxisAlignedBox3 VspTree::GetBBox(VspNode *node) const 2256 2338 { 2257 2339 if (!node->GetParent()) … … 2260 2342 if (!node->IsLeaf()) 2261 2343 { 2262 return (dynamic_cast<VspInterior *>(node))->GetBo x();2344 return (dynamic_cast<VspInterior *>(node))->GetBoundingBox(); 2263 2345 } 2264 2346 2265 2347 VspInterior *parent = dynamic_cast<VspInterior *>(node->GetParent()); 2266 2348 2267 AxisAlignedBox3 box(parent->GetBo x());2349 AxisAlignedBox3 box(parent->GetBoundingBox()); 2268 2350 2269 2351 if (parent->GetFront() == node) … … 2276 2358 2277 2359 2278 } 2360 /*****************************************************************/ 2361 /* class HierarchyManager implementation */ 2362 /*****************************************************************/ 2363 2364 HierarchyManager::HierarchyManager() 2365 { 2366 } 2367 2368 2369 SplitCandidate *HierarchyManager::NextSplitCandidate() 2370 { 2371 SplitCandidate *splitCandidate = mTQueue.top(); 2372 mTQueue.pop(); 2373 2374 return splitCandidate; 2375 } 2376 2377 2378 void HierarchyManager::PrepareTraversal() 2379 { 2380 2381 #if TODO 2382 /// create new vsp tree 2383 mRoot = new VspLeaf(); 2384 /// we use the overall probability as normalizer 2385 const float prop = mBoundingBox.GetVolume(); 2386 2387 VspTraversalData tData(mRoot, 2388 0, 2389 rays, 2390 ComputePvsSize(*rays), 2391 prop, 2392 mBoundingBox); 2393 2394 2395 // compute first split candidates 2396 VspTree::VspSplitCandidate vspSplitCandidate = new VspTree::VspSplitCandidate(); 2397 EvalSplitCandidate(tData, *vspSplitCandidate); 2398 mTQueue.push(splitCandidate); 2399 2400 OspSplitCandidate ospSplitCandidate = new OspSplitCandidate(); 2401 EvalSplitCandidate(tData, *ospSplitCandidate); 2402 mTQueue.push(ospSplitCandidate); 2403 2404 mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume(); 2405 mTotalPvsSize = tData.mPvs; 2406 2407 mSubdivisionStats 2408 << "#ViewCells\n1\n" << endl 2409 << "#RenderCostDecrease\n0\n" << endl 2410 << "#SplitCandidateCost\n0\n" << endl 2411 << "#TotalRenderCost\n" << mTotalCost << endl 2412 << "#AvgRenderCost\n" << mTotalPvsSize << endl; 2413 2414 Debug << "total cost: " << mTotalCost << endl; 2415 2416 #endif 2417 } 2418 2419 2420 void HierarchyManager::Construct(const VssRayContainer &sampleRays, 2421 const ObjectContainer &objects, 2422 AxisAlignedBox3 *forcedBoundingBox) 2423 { 2424 #if TODO 2425 //-- store rays 2426 for (rit = sampleRays.begin(); rit != rit_end; ++ rit) 2427 { 2428 VssRay *ray = *rit; 2429 2430 float minT, maxT; 2431 2432 static Ray hray; 2433 hray.Init(*ray); 2434 2435 // TODO: not very efficient to implictly cast between rays types 2436 if (mBoundingBox.GetRaySegment(hray, minT, maxT)) 2437 { 2438 float len = ray->Length(); 2439 2440 if (!len) 2441 len = Limits::Small; 2442 2443 rays->push_back(RayInfo(ray, minT / len, maxT / len)); 2444 } 2445 } 2446 #endif 2447 } 2448 2449 2450 bool HierarchyManager::FinishedConstruction() 2451 { 2452 return mTQueue.empty(); 2453 } 2454 2455 2456 void HierarchyManager::Construct(RayInfoContainer *rays) 2457 { 2458 PrepareTraversal(); 2459 2460 mVspTree->mVspStats.Start(); 2461 cout << "Constructing vsp bsp tree ... \n"; 2462 2463 const long startTime = GetTime(); 2464 2465 while (!FinishedConstruction()) 2466 { 2467 SplitCandidate *splitCandidate = NextSplitCandidate(); 2468 2469 // cost ratio of cost decrease / totalCost 2470 const float costRatio = splitCandidate->GetPriority() / mTotalCost; 2471 2472 //Debug << "cost ratio: " << costRatio << endl; 2473 2474 if (costRatio < mTermMinGlobalCostRatio) 2475 ++ mGlobalCostMisses; 2476 2477 // subdivide leaf node 2478 // either object space or view space 2479 if (splitCandidate->Type() == SplitCandidate::VIEW_SPACE) 2480 { 2481 VspTree::VspSplitCandidate *sc = 2482 dynamic_cast<VspTree::VspSplitCandidate *>(splitCandidate); 2483 2484 VspNode *r = mVspTree->Subdivide(mTQueue, *sc); 2485 } 2486 else // object space 2487 { 2488 #if TODO 2489 KdNode *r = mKdtree->Subdivide(tOspQueue, dynamic_cast<OspSplitCandidate<(splitCandidate)); 2490 #endif 2491 } 2492 } 2493 2494 cout << "finished\n"; 2495 2496 mVspTree->mVspStats.Stop(); 2497 } 2498 2499 } -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
r1013 r1016 45 45 }; 46 46 47 47 /** Candidate for a view space / object space split. 48 */ 49 class SplitCandidate 50 { 51 public: 52 53 enum {OBJECT_SPACE, VIEW_SPACE}; 54 55 /// the current split plane 56 AxisAlignedPlane mSplitPlane; 57 /// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned) 58 int mSplitAxis; 59 /// the number of misses of max cost ratio until this split 60 int mMaxCostMisses; 61 62 /// priority of this split 63 float mPriority; 64 65 SplitCandidate(): mPriority(0) 66 {}; 67 68 SplitCandidate(const AxisAlignedPlane &plane): mSplitPlane(plane) 69 {} 70 71 virtual int Type() const = 0; 72 73 /** Returns cost of the traversal data. 74 */ 75 float GetPriority() const 76 { 77 #if 1 78 return mPriority; 79 #else 80 return (float) (-mDepth); // for kd tree 81 #endif 82 } 83 84 friend bool operator<(const SplitCandidate &a, const SplitCandidate &b) 85 { 86 return a.GetPriority() < b.GetPriority(); 87 } 88 }; 89 90 91 /** View space partition statistics. 92 */ 48 93 class VspTreeStatistics: public StatisticsBase 49 94 { … … 154 199 155 200 /** Determines whether this node is a leaf or not 156 @return true if leaf201 @return true if leaf 157 202 */ 158 203 virtual bool IsLeaf() const = 0; … … 161 206 162 207 /** Determines whether this node is a root 163 @return true if root208 @return true if root 164 209 */ 165 210 virtual bool IsRoot() const; … … 250 295 } 251 296 252 AxisAlignedBox3 GetBo x() const;253 void SetBo x(const AxisAlignedBox3 &box);297 AxisAlignedBox3 GetBoundingBox() const; 298 void SetBoundingBox(const AxisAlignedBox3 &box); 254 299 255 300 protected: 256 301 257 AxisAlignedBox3 mBo x;302 AxisAlignedBox3 mBoundingBox; 258 303 259 304 /// Splitting plane corresponding to this node … … 310 355 311 356 312 /** 313 This class implements a structure holding two different hierarchies, 314 one for object space partitioning and one for view space partitioning. 315 316 The object space and the view space are subdivided using a cost heuristics. 317 If an object space split or a view space split is chosen is also evaluated 318 based on the heuristics. 319 320 The view space heuristics is evaluated by weighting and adding the pvss of the back and 321 front node of each specific split. unlike for the standalone method vspbsp tree, 322 the pvs of an object would not be the pvs of single object but that of all objects 323 which are contained in the same leaf of the object subdivision. This could be done 324 by storing the pointer to the object space partition parent, which would allow access to all children. 325 Another possibility is to include traced kd-cells in the ray casing process. 326 327 Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object. 328 the contribution to an object to the pvs is the number of view cells it can be seen from. 329 330 331 There is a potential efficiency problem involved in a sense that once a certain type 332 of split is chosen for view space / object space, the candidates for the next split of 333 object space / view space must be reevaluated. 334 357 typedef std::priority_queue<SplitCandidate *> SplitQueue; 358 359 360 #if TODO 361 /** candidate for a view space split 335 362 */ 336 class VspOspTree 363 class OspSplitCandidate: public SplitCandidate 364 { 365 /// parent data 366 OspTraversalData mParentData; 367 368 VspOspSplitCandidate(): mRenderCost(0) 369 {}; 370 371 int Type() const { return OSP_CANDIDATE; } 372 373 VspOspSplitCandidate(const AxisAlignedPlane &plane, const VspOspTraversalData &tData): 374 mSplitPlane(plane), mParentData(tData), mRenderCost(0) 375 {} 376 }; 377 #endif 378 379 /** View Space Partitioning tree. 380 */ 381 class VspTree 337 382 { 338 383 friend class ViewCellsParseHandlers; 339 friend class VspVspViewCellsManager;384 friend class HierarchyManager; 340 385 341 386 public: … … 343 388 /** Additional data which is passed down the BSP tree during traversal. 344 389 */ 345 class Vsp OspTraversalData390 class VspTraversalData 346 391 { 347 392 public: … … 374 419 375 420 376 Vsp OspTraversalData():421 VspTraversalData(): 377 422 mNode(NULL), 378 423 mDepth(0), … … 385 430 {} 386 431 387 Vsp OspTraversalData(VspNode *node,388 389 390 391 392 const AxisAlignedBox3 &box):432 VspTraversalData(VspNode *node, 433 const int depth, 434 RayInfoContainer *rays, 435 const int pvs, 436 const float p, 437 const AxisAlignedBox3 &box): 393 438 mNode(node), 394 439 mDepth(depth), … … 402 447 {} 403 448 404 VspOspTraversalData(PolygonContainer *polys, 405 const int depth, 406 RayInfoContainer *rays, 407 const AxisAlignedBox3 &box): 449 VspTraversalData(const int depth, 450 RayInfoContainer *rays, 451 const AxisAlignedBox3 &box): 408 452 mNode(NULL), 409 453 mDepth(depth), … … 430 474 } 431 475 432 friend bool operator<(const Vsp OspTraversalData &a, const VspOspTraversalData &b)476 friend bool operator<(const VspTraversalData &a, const VspTraversalData &b) 433 477 { 434 478 return a.GetCost() < b.GetCost(); 435 479 } 436 480 }; 437 481 482 /** Candidate for a view space split. 483 */ 484 class VspSplitCandidate: public SplitCandidate 485 { 486 public: 487 /// parent data 488 VspTraversalData mParentData; 489 490 VspSplitCandidate() 491 {}; 492 493 int Type() const { return VIEW_SPACE; } 494 495 VspSplitCandidate(const AxisAlignedPlane &plane, const VspTraversalData &tData): 496 SplitCandidate(plane), mParentData(tData) 497 {} 498 }; 438 499 439 500 /** Struct for traversing line segment. … … 451 512 }; 452 513 453 typedef std::priority_queue<VspOspTraversalData> VspOspTraversalQueue; 454 455 /** candidate for a view space split 456 */ 457 struct VspOspSplitCandidate 458 { 459 /// the current plane 460 AxisAlignedPlane mSplitPlane; 461 /// the number of misses of max cost ratio until this split 462 int mMaxCostMisses; 463 /// parent data 464 VspOspTraversalData mParentData; 465 /// cost of applying this split 466 float mRenderCost; 467 468 VspOspSplitCandidate(): mRenderCost(0) 469 {}; 470 471 VspOspSplitCandidate(const AxisAlignedPlane &plane, const VspOspTraversalData &tData): 472 mSplitPlane(plane), mParentData(tData), mRenderCost(0) 473 {} 474 475 /** Returns cost of the traversal data. 476 */ 477 float GetCost() const 478 { 479 #if 1 480 return mRenderCost; 481 #else 482 return (float) (-mDepth); // for kd tree 483 #endif 484 } 485 486 friend bool operator<(const VspOspSplitCandidate &a, const VspOspSplitCandidate &b) 487 { 488 return a.GetCost() < b.GetCost(); 489 } 490 }; 491 492 typedef std::priority_queue<VspOspSplitCandidate> VspOspSplitQueue; 514 //typedef std::priority_queue<VspTraversalData> VspOspTraversalQueue; 493 515 494 516 /** Default constructor creating an empty tree. 495 517 */ 496 Vsp OspTree();518 VspTree(); 497 519 498 520 /** Default destructor. 499 521 */ 500 ~Vsp OspTree();522 ~VspTree(); 501 523 502 524 /** Returns BSP Tree statistics. … … 510 532 /** Constructs the tree from a given set of rays. 511 533 @param sampleRays the set of sample rays the construction is based on 512 @param viewCells if not NULL, new view cells are 513 created in the leafs and stored in the container 534 @param forcedBoundingBox a given bounding box is taken as view space 514 535 */ 515 536 void Construct(const VssRayContainer &sampleRays, … … 519 540 a certain threshold. 520 541 @param onlyUnmailed if only the unmailed leaves should be considered 521 @param maxPvs the maximal pvs (-1 means unlimited)542 @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited) 522 543 */ 523 544 void CollectLeaves(vector<VspLeaf *> &leaves, … … 638 659 ViewCellContainer &viewCells) const; 639 660 640 // pointer to the hierarchy of view cells661 /// pointer to the hierarchy of view cells 641 662 ViewCellsTree *mViewCellsTree; 642 663 … … 673 694 /** faster evaluation of split plane cost for kd axis aligned cells. 674 695 */ 675 float EvalSplitCost(const Vsp OspTraversalData &data,696 float EvalSplitCost(const VspTraversalData &data, 676 697 const AxisAlignedBox3 &box, 677 698 const int axis, … … 682 703 /** Evaluates candidate for splitting. 683 704 */ 684 void EvalSplitCandidate(Vsp OspTraversalData &tData, VspOspSplitCandidate &splitData);705 void EvalSplitCandidate(VspTraversalData &tData, VspSplitCandidate &splitData); 685 706 686 707 /** Computes priority of the traversal data and stores it in tData. 687 708 */ 688 void EvalPriority(Vsp OspTraversalData &tData) const;709 void EvalPriority(VspTraversalData &tData) const; 689 710 690 711 /** Evaluates render cost decrease of next split. 691 712 */ 692 713 float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 693 const Vsp OspTraversalData &data) const;714 const VspTraversalData &data) const; 694 715 695 716 /** Constructs tree using the split priority queue. … … 724 745 /** Evaluates tree stats in the BSP tree leafs. 725 746 */ 726 void EvaluateLeafStats(const Vsp OspTraversalData &data);747 void EvaluateLeafStats(const VspTraversalData &data); 727 748 728 749 /** Subdivides node with respect to the traversal data. … … 731 752 @returns new root of the subtree 732 753 */ 733 VspNode *Subdivide( VspOspSplitQueue &tQueue,734 Vsp OspSplitCandidate &splitCandidate);754 VspNode *Subdivide(SplitQueue &tQueue, 755 VspSplitCandidate &splitCandidate); 735 756 736 757 … … 750 771 751 772 VspInterior *SubdivideNode(const AxisAlignedPlane &splitPlane, 752 Vsp OspTraversalData &tData,753 Vsp OspTraversalData &frontData,754 Vsp OspTraversalData &backData);773 VspTraversalData &tData, 774 VspTraversalData &frontData, 775 VspTraversalData &backData); 755 776 756 777 /** Selects an axis aligned for the next split. 757 778 @returns cost for this split 758 779 */ 759 float SelectPlane(const Vsp OspTraversalData &tData,780 float SelectPlane(const VspTraversalData &tData, 760 781 AxisAlignedPlane &plane, 761 782 float &pFront, … … 815 836 /** Returns true if tree can be terminated. 816 837 */ 817 inline bool LocalTerminationCriteriaMet(const Vsp OspTraversalData &data) const;838 inline bool LocalTerminationCriteriaMet(const VspTraversalData &data) const; 818 839 819 840 /** Returns true if global tree can be terminated. 820 841 */ 821 inline bool GlobalTerminationCriteriaMet(const Vsp OspTraversalData &data) const;842 inline bool GlobalTerminationCriteriaMet(const VspTraversalData &data) const; 822 843 823 844 /** Adds ray sample contributions to the PVS. … … 951 972 }; 952 973 974 975 class KdTree; 976 977 /** This class implements a structure holding two different hierarchies, 978 one for object space partitioning and one for view space partitioning. 979 980 The object space and the view space are subdivided using a cost heuristics. 981 If an object space split or a view space split is chosen is also evaluated 982 based on the heuristics. 983 984 The view space heuristics is evaluated by weighting and adding the pvss of the back and 985 front node of each specific split. unlike for the standalone method vspbsp tree, 986 the pvs of an object would not be the pvs of single object but that of all objects 987 which are contained in the same leaf of the object subdivision. This could be done 988 by storing the pointer to the object space partition parent, which would allow access to all children. 989 Another possibility is to include traced kd-cells in the ray casing process. 990 991 Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object. 992 the contribution to an object to the pvs is the number of view cells it can be seen from. 993 994 @note 995 There is a potential efficiency problem involved in a sense that once a certain type 996 of split is chosen for view space / object space, the candidates for the next split of 997 object space / view space must be reevaluated. 998 999 */ 1000 class HierarchyManager 1001 { 1002 /** Default constructor. 1003 */ 1004 HierarchyManager(); 1005 1006 /** Constructs the view space and object space subdivision from a given set of rays 1007 and a set of objects. 1008 @param sampleRays the set of sample rays the construction is based on 1009 @param objects the set of objects 1010 */ 1011 void Construct(const VssRayContainer &sampleRays, 1012 const ObjectContainer &objects, 1013 AxisAlignedBox3 *forcedBoundingBox); 1014 1015 public: 1016 VspTree *mVspTree; 1017 KdTree *mKdTree; 1018 1019 protected: 1020 1021 void Construct(RayInfoContainer *rays); 1022 void PrepareTraversal(); 1023 bool FinishedConstruction(); 1024 SplitCandidate *NextSplitCandidate(); 1025 1026 1027 1028 AxisAlignedBox3 mBoundingBox; 1029 1030 SplitQueue mTQueue; 1031 1032 //-- global criteria 1033 float mTermMinGlobalCostRatio; 1034 int mTermGlobalCostMissTolerance; 1035 int mGlobalCostMisses; 1036 1037 /// keeps track of cost during subdivision 1038 float mTotalCost; 1039 }; 1040 953 1041 } 954 1042
Note: See TracChangeset
for help on using the changeset viewer.