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