- Timestamp:
- 07/24/06 10:12:34 (18 years ago)
- Location:
- GTP/trunk/Lib/Vis
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
r1138 r1145 164 164 </File> 165 165 <File 166 RelativePath="..\src\GlRenderer.cpp">167 </File>168 <File169 RelativePath="..\src\GlRenderer.h">170 <FileConfiguration171 Name="Release|Win32">172 <Tool173 Name="VCCustomBuildTool"174 Description="Performing moc on $(InputName).h"175 CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp176 "177 Outputs="$(InputDir)moc_$(InputName).cpp"/>178 </FileConfiguration>179 </File>180 <File181 166 RelativePath="..\src\GzBinFileInputStream.cpp"> 182 167 </File> … … 246 231 <File 247 232 RelativePath="..\src\MeshKdTree.h"> 248 </File>249 <File250 RelativePath="..\src\moc_GlRenderer.cpp">251 </File>252 <File253 RelativePath="..\src\moc_Preprocessor.cpp">254 </File>255 <File256 RelativePath="..\src\moc_PreprocessorThread.cpp">257 233 </File> 258 234 <File … … 356 332 </File> 357 333 <File 358 RelativePath="..\src\Renderer.cpp">359 </File>360 <File361 RelativePath="..\src\Renderer.h">362 </File>363 <File364 334 RelativePath="..\src\RenderSampler.cpp"> 365 335 </File> … … 548 518 <File 549 519 RelativePath="..\include\ViewCell.h"> 520 </File> 521 </Filter> 522 <Filter 523 Name="Renderer" 524 Filter=""> 525 <File 526 RelativePath="..\src\GlRenderer.cpp"> 527 </File> 528 <File 529 RelativePath="..\src\GlRenderer.h"> 530 </File> 531 <File 532 RelativePath="..\src\QtGlRenderer.cpp"> 533 </File> 534 <File 535 RelativePath="..\src\QtGlRenderer.h"> 536 </File> 537 <File 538 RelativePath="..\src\Renderer.cpp"> 539 </File> 540 <File 541 RelativePath="..\src\Renderer.h"> 550 542 </File> 551 543 </Filter> -
GTP/trunk/Lib/Vis/Preprocessing/scripts/TestPreprocessor.vcproj
r1077 r1145 70 70 <Tool 71 71 Name="VCCLCompilerTool" 72 AdditionalIncludeDirectories="..\include;"$(QTDIR)\include\QtCore";"$(QTDIR)\include\QtGui";"$(QTDIR)\include";"$( QTDIR)\include\QtOpenGl";..\src;"$(CG_INC_PATH)";..\..\..\..\..\..\NonGTP\Devil\include;..\..\..\..\..\..\NonGTP\Zlib\include;..\..\..\..\..\..\NonGTP\Xerces"72 AdditionalIncludeDirectories="..\include;"$(QTDIR)\include\QtCore";"$(QTDIR)\include\QtGui";"$(QTDIR)\include";"$(BOOST_INCLUDE)";"$(QTDIR)\include\QtOpenGl";..\src;"$(CG_INC_PATH)";..\..\..\..\..\..\NonGTP\Devil\include;..\..\..\..\..\..\NonGTP\Zlib\include;..\..\..\..\..\..\NonGTP\Xerces" 73 73 PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" 74 74 RuntimeLibrary="2" … … 85 85 OutputFile="$(OutDir)/Preprocessor.exe" 86 86 LinkIncremental="1" 87 AdditionalLibraryDirectories="..\support\xercesc\lib\;..\support\zlib\lib\;..\support\devil\lib;"$(QTDIR)\lib";..\include;..\src\GL;"$(CG_LIB_PATH)";"$(GTPDIR)\NonGTP\Xerces";"$(GTPDIR)\NonGTP\Xerces\xercesc\lib";"$(GTPDIR)\NonGTP\zlib\lib";"$(GTPDIR)\NonGTP\Devil\lib";..\lib\release;..\..\Preprocessing\lib\release "87 AdditionalLibraryDirectories="..\support\xercesc\lib\;..\support\zlib\lib\;..\support\devil\lib;"$(QTDIR)\lib";..\include;..\src\GL;"$(CG_LIB_PATH)";"$(GTPDIR)\NonGTP\Xerces";"$(GTPDIR)\NonGTP\Xerces\xercesc\lib";"$(GTPDIR)\NonGTP\zlib\lib";"$(GTPDIR)\NonGTP\Devil\lib";..\lib\release;..\..\Preprocessing\lib\release;"$(BOOST_LIB)"" 88 88 GenerateDebugInformation="FALSE" 89 89 SubSystem="1" -
GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
r1141 r1145 23 23 namespace GtpVisibilityPreprocessor { 24 24 25 static CGcontext sCgContext = NULL; 26 static CGprogram sCgFragmentProgram = NULL; 27 static CGprofile sCgFragmentProfile; 28 25 26 /* 29 27 GLuint frontDepthMap; 30 28 GLuint backDepthMap; 31 29 32 30 const int depthMapSize = 512; 33 static vector<OcclusionQuery *> sQueries; 34 35 GlRendererWidget *rendererWidget = NULL; 36 GlDebuggerWidget *debuggerWidget = NULL; 31 32 //static vector<OcclusionQuery *> sQueries; 33 */ 37 34 38 35 static bool arbQuerySupport = false; … … 101 98 { 102 99 cerr<<"gl renderer destructor..\n"; 103 if (sCgFragmentProgram)104 cgDestroyProgram(sCgFragmentProgram);105 if (sCgContext)106 cgDestroyContext(sCgContext); 100 101 //CLEAR_CONTAINER(sQueries); 102 CLEAR_CONTAINER(mOcclusionQueries); 103 107 104 cerr<<"done."<<endl; 108 109 CLEAR_CONTAINER(sQueries); 110 CLEAR_CONTAINER(mOcclusionQueries); 111 } 112 113 114 static void handleCgError() 115 { 116 Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl; 117 exit(1); 118 } 105 } 106 119 107 120 108 void … … 264 252 glEnable(GL_CULL_FACE); 265 253 266 // HACK!! but using glew keeps crashing for some reason ...267 254 InitExtensions(); 268 255 … … 328 315 } 329 316 330 void331 GlRendererWidget::RenderInfo()332 {333 QString s;334 int vc = 0;335 if (mViewCellsManager)336 vc = mViewCellsManager->GetViewCells().size();337 int filter = 0;338 if (mViewCellsManager)339 filter = mViewCellsManager->GetMaxFilterSize();340 341 s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d filter:%04d pvs:%04d error:%5.5f\%",342 mFrame,343 mViewPoint.x,344 mViewPoint.y,345 mViewPoint.z,346 mViewDirection.x,347 mViewDirection.y,348 mViewDirection.z,349 vc,350 351 filter,352 mPvsSize,353 mRenderError*100.0f354 );355 356 glColor3f(0.0f,0.0f,0.0f);357 renderText(0,20,s);358 359 if (mShowRenderCost) {360 static vector<float> costFunction;361 static float maxCost = -1;362 if (costFunction.size()==0) {363 ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree();364 if (tree) {365 tree->GetCostFunction(costFunction);366 maxCost = -1;367 for (int i=0; i < costFunction.size(); i++) {368 // cout<<i<<":"<<costFunction[i]<<" ";369 if (costFunction[i] > maxCost)370 maxCost = costFunction[i];371 }372 }373 }374 375 376 int currentPos = mViewCellsManager->GetViewCells().size();377 float currentCost=-1;378 379 if (currentPos < costFunction.size())380 currentCost = costFunction[currentPos];381 #if 0382 cout<<"costFunction.size()="<<costFunction.size()<<endl;383 cout<<"CP="<<currentPos<<endl;384 cout<<"MC="<<maxCost<<endl;385 cout<<"CC="<<currentCost<<endl;386 #endif387 if (costFunction.size()) {388 glDisable(GL_DEPTH_TEST);389 // init ortographic projection390 glMatrixMode(GL_PROJECTION);391 glPushMatrix();392 393 glLoadIdentity();394 gluOrtho2D(0, 1.0f, 0, 1.0f);395 396 glTranslatef(0.1f, 0.1f, 0.0f);397 glScalef(0.8f, 0.8f, 1.0f);398 glMatrixMode(GL_MODELVIEW);399 glLoadIdentity();400 401 glColor3f(1.0f,0,0);402 glBegin(GL_LINE_STRIP);403 // glVertex3f(0,0,0);404 405 for (int i=0; i < costFunction.size(); i++) {406 float x = i/(float)costFunction.size();407 float y = costFunction[i]/(maxCost*0.5f);408 glVertex3f(x,y,0.0f);409 }410 glEnd();411 412 glColor3f(1.0f,0,0);413 glBegin(GL_LINES);414 float x = currentPos/(float)costFunction.size();415 glVertex3f(x,0.0,0.0f);416 glVertex3f(x,1.0f,0.0f);417 glEnd();418 419 glColor3f(0.0f,0,0);420 // show a grid421 glBegin(GL_LINE_LOOP);422 glVertex3f(0,0,0.0f);423 glVertex3f(1,0,0.0f);424 glVertex3f(1,1,0.0f);425 glVertex3f(0,1,0.0f);426 glEnd();427 428 glBegin(GL_LINES);429 for (int i=0; i < 50000 && i < costFunction.size(); i+=10000) {430 float x = i/(float)costFunction.size();431 glVertex3f(x,0.0,0.0f);432 glVertex3f(x,1.0f,0.0f);433 }434 435 for (int i=0; i < maxCost; i+=100) {436 float y = i/(maxCost*0.5f);437 glVertex3f(0,y,0.0f);438 glVertex3f(1,y,0.0f);439 }440 441 glEnd();442 443 444 // restore the projection matrix445 glMatrixMode(GL_PROJECTION);446 glPopMatrix();447 glMatrixMode(GL_MODELVIEW);448 glEnable(GL_DEPTH_TEST);449 450 }451 }452 }453 454 317 455 318 void … … 477 340 target.x, target.y, target.z, 478 341 up.x, up.y, up.z); 342 } 343 344 void 345 GlRenderer::_RenderScene() 346 { 347 ObjectContainer::const_iterator oi = mObjects.begin(); 348 349 for (; oi != mObjects.end(); oi++) 350 RenderIntersectable(*oi); 351 } 352 353 bool 354 GlRenderer::RenderScene() 355 { 356 static int glList = -1; 357 if (mUseGlLists) { 358 if (glList == -1) { 359 glList = glGenLists(1); 360 glNewList(glList, GL_COMPILE); 361 _RenderScene(); 362 glEndList(); 363 } 364 glCallList(glList); 365 } else 366 _RenderScene(); 367 368 369 return true; 479 370 } 480 371 … … 507 398 } 508 399 509 //std::ofstream outfile("try_arb.txt"); 400 401 402 /****************************************************************/ 403 /* GlRendererBuffer implementation */ 404 /****************************************************************/ 405 406 407 408 GlRendererBuffer::GlRendererBuffer(SceneGraph *sceneGraph, 409 ViewCellsManager *viewcells, 410 KdTree *tree): 411 GlRenderer(sceneGraph, viewcells, tree) 412 { 413 mPixelBuffer = NULL; 414 415 // implement width and height in subclasses 416 } 417 418 510 419 void 511 420 GlRendererBuffer::EvalQueryWithOcclusionQueries( … … 604 513 605 514 void 606 GlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample,607 const bool useOcclusionQueries,608 const int threshold609 )610 {611 // choose a random view point612 mViewCellsManager->GetViewPoint(mViewPoint);613 sample.mPosition = mViewPoint;614 //cout << "viewpoint: " << mViewPoint << endl;615 616 // take a render cost sample by rendering a cube617 Vector3 directions[6];618 619 directions[0] = Vector3(1,0,0);620 directions[1] = Vector3(0,1,0);621 directions[2] = Vector3(0,0,1);622 directions[3] = Vector3(-1,0,0);623 directions[4] = Vector3(0,-1,0);624 directions[5] = Vector3(0,0,-1);625 626 sample.mVisibleObjects = 0;627 628 // reset object counters629 ObjectContainer::const_iterator it, it_end = mObjects.end();630 631 for (it = mObjects.begin(); it != it_end; ++ it)632 {633 (*it)->mCounter = 0;634 }635 636 ++ mFrame;637 638 //glCullFace(GL_FRONT);639 glCullFace(GL_BACK);640 glDisable(GL_CULL_FACE);641 642 643 // query all 6 directions for a full point sample644 for (int i = 0; i < 6; ++ i)645 {646 mViewDirection = directions[i];647 SetupCamera();648 649 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);650 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);651 //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE);652 glDepthFunc(GL_LESS);653 654 mUseFalseColors = true;655 656 // the actual scene rendering fills the depth (for occlusion queries)657 // and the frame buffer (for item buffer)658 RenderScene();659 660 661 if (0)662 {663 char filename[256];664 sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);665 QImage im = toImage();666 im.save(filename, "PNG");667 }668 669 // evaluate the sample670 if (useOcclusionQueries)671 {672 EvalQueryWithOcclusionQueries();673 }674 else675 {676 EvalQueryWithItemBuffer();677 }678 }679 680 // now evaluate the statistics over that sample681 // currently only the number of visible objects is taken into account682 sample.Reset();683 684 for (it = mObjects.begin(); it != it_end; ++ it)685 {686 Intersectable *obj = *it;687 if (obj->mCounter >= threshold)688 {689 ++ sample.mVisibleObjects;690 sample.mVisiblePixels += obj->mCounter;691 }692 }693 694 //cout << "RS=" << sample.mVisibleObjects << " ";695 }696 697 698 void699 GlRendererBuffer::SampleRenderCost(const int numSamples,700 vector<RenderCostSample> &samples,701 const bool useOcclusionQueries,702 const int threshold703 )704 {705 makeCurrent();706 707 if (mPixelBuffer == NULL)708 mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];709 710 // using 90 degree projection to capture 360 view with 6 samples711 SetupProjection(GetHeight(), GetHeight(), 90.0f);712 713 //samples.resize(numSamples);714 halton.Reset();715 716 // the number of queries queried in batch mode717 const int numQ = 500;718 719 //const int numQ = (int)mObjects.size();720 if (useOcclusionQueries)721 {722 cout << "\ngenerating " << numQ << " queries ... ";723 OcclusionQuery::GenQueries(mOcclusionQueries, numQ);724 cout << "finished" << endl;725 }726 727 // sampling queries728 for (int i = 0; i < numSamples; ++ i)729 {730 cout << ".";731 EvalRenderCostSample(samples[i], useOcclusionQueries, threshold);732 }733 734 doneCurrent();735 736 }737 738 739 void740 515 GlRendererBuffer::RandomViewPoint() 741 516 { … … 770 545 771 546 772 GlRendererBuffer::GlRendererBuffer(const int w, 773 const int h, 774 SceneGraph *sceneGraph, 775 ViewCellsManager *viewcells, 776 KdTree *tree): 777 QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) { 778 779 Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames); 780 mPvsErrorBuffer.resize(mPvsStatFrames); 781 ClearErrorBuffer(); 782 783 mPixelBuffer = NULL; 784 785 makeCurrent(); 786 InitGL(); 787 doneCurrent(); 788 789 } 790 791 float 792 GlRendererBuffer::GetPixelError(int &pvsSize) 793 { 794 float pErrorPixels = -1.0f; 795 796 glReadBuffer(GL_BACK); 797 798 // mUseFalseColors = true; 799 800 mUseFalseColors = false; 801 unsigned int pixelCount; 802 803 //static int query = -1; 804 //if (query == -1) 805 // glGenOcclusionQueriesNV(1, (unsigned int *)&query); 806 807 OcclusionQuery query; 808 809 if (mDetectEmptyViewSpace) { 810 // now check whether any backfacing polygon would pass the depth test 811 SetupCamera(); 812 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 813 glEnable( GL_CULL_FACE ); 814 815 RenderScene(); 816 817 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 818 glDepthMask(GL_FALSE); 819 glDisable( GL_CULL_FACE ); 820 821 822 query.BeginQuery(); 823 824 RenderScene(); 825 826 query.EndQuery(); 827 828 // at this point, if possible, go and do some other computation 829 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 830 glDepthMask(GL_TRUE); 831 glEnable( GL_CULL_FACE ); 832 833 // reenable other state 834 pixelCount = query.GetQueryResult(); 835 836 if (pixelCount > 0) 837 return -1.0f; // backfacing polygon found -> not a valid viewspace sample 838 } else 839 glDisable( GL_CULL_FACE ); 840 841 842 ViewCell *viewcell = NULL; 843 844 PrVs prvs; 845 846 mViewCellsManager->SetMaxFilterSize(0); 847 mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth()); 848 viewcell = prvs.mViewCell; 849 850 // ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint); 851 pvsSize = 0; 852 if (viewcell) { 853 SetupCamera(); 854 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 855 856 glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); 857 858 // Render PVS 859 std::map<Intersectable *, 860 PvsData<Intersectable *>, 861 LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin(); 862 863 pvsSize = viewcell->GetPvs().mEntries.size(); 864 865 for (; it != viewcell->GetPvs().mEntries.end(); ++ it) { 866 Intersectable *object = (*it).first; 867 RenderIntersectable(object); 868 } 869 870 // glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); 871 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 872 mUseFalseColors = true; 873 874 query.BeginQuery(); 875 876 SetupCamera(); 877 878 RenderScene(); 879 880 query.EndQuery(); 881 882 883 unsigned int pixelCount; 884 // reenable other state 885 pixelCount = query.GetQueryResult(); 886 887 888 pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight()); 889 if (mSnapErrorFrames && pErrorPixels > 0.01) { 890 891 char filename[256]; 892 sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels); 893 QImage im = toImage(); 894 im.save(mSnapPrefix + filename, "PNG"); 895 if (1) { //0 && mFrame == 1543) { 896 int x,y; 897 int lastIndex = -1; 898 for (y=0; y < im.height(); y++) 899 for (x=0; x < im.width(); x++) { 900 QRgb p = im.pixel(x,y); 901 int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16); 902 if (qGreen(p) != 255 && index!=0) { 903 if (index != lastIndex) { 904 // Debug<<"ei="<<index<<" "; 905 lastIndex = index; 906 } 907 } 908 } 909 } 910 911 912 mUseFalseColors = false; 913 glPushAttrib(GL_CURRENT_BIT); 914 glColor3f(0,1,0); 915 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 916 SetupCamera(); 917 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 918 919 // Render PVS 920 std::map<Intersectable *, 921 PvsData<Intersectable *>, 922 LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin(); 923 924 for (; it != viewcell->GetPvs().mEntries.end(); ++ it) { 925 Intersectable *object = (*it).first; 926 RenderIntersectable(object); 927 } 928 929 im = toImage(); 930 sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels); 931 im.save(mSnapPrefix + filename, "PNG"); 932 glPopAttrib(); 933 } 934 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 935 } 936 937 if (viewcell && mViewCellsManager->GetMaxFilterSize() > 0) 938 mViewCellsManager->DeleteLocalMergeTree(viewcell); 939 940 return pErrorPixels; 941 } 942 943 944 void 945 GlRendererWidget::SetupProjection(const int w, const int h, const float angle) 946 { 947 if (!mTopView) 948 GlRenderer::SetupProjection(w, h, angle); 949 else { 950 glViewport(0, 0, w, h); 951 glMatrixMode(GL_PROJECTION); 952 glLoadIdentity(); 953 gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal())); 954 glMatrixMode(GL_MODELVIEW); 955 } 956 } 957 958 void 959 GlRendererWidget::RenderPvs() 960 { 961 SetupCamera(); 962 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 963 964 ViewCell *viewcell = NULL; 965 966 PrVs prvs; 967 968 if (!mUseFilter) { 969 viewcell = mViewCellsManager->GetViewCell(mViewPoint, true); 970 } else { 971 // mViewCellsManager->SetMaxFilterSize(1); 972 mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth()); 973 viewcell = prvs.mViewCell; 974 } 975 976 if (viewcell) { 977 // copy the pvs so that it can be filtered... 978 ObjectPvs pvs = viewcell->GetPvs(); 979 980 if (mUseSpatialFilter) { 981 mViewCellsManager->ApplySpatialFilter(mKdTree, 982 mSpatialFilterSize* 983 Magnitude(mViewCellsManager->GetViewSpaceBox().Size()), 984 pvs); 985 } 986 987 988 // read back the texture 989 std::map<Intersectable *, 990 PvsData<Intersectable *>, 991 LtSample<Intersectable *> >::const_iterator it = pvs.mEntries.begin(); 992 993 mPvsSize = pvs.mEntries.size(); 994 995 for (; it != pvs.mEntries.end(); ++ it) { 996 Intersectable *object = (*it).first; 997 float visibility = log10((*it).second.mSumPdf + 1)/5.0f; 998 glColor3f(visibility, 0.0f, 0.0f); 999 mUseForcedColors = true; 1000 RenderIntersectable(object); 1001 mUseForcedColors = false; 1002 } 1003 1004 if (mRenderFilter) { 1005 mWireFrame = true; 1006 RenderIntersectable(viewcell); 1007 mWireFrame = false; 1008 } 1009 1010 if (mUseFilter) 1011 mViewCellsManager->DeleteLocalMergeTree(viewcell); 1012 } else { 1013 ObjectContainer::const_iterator oi = mObjects.begin(); 1014 for (; oi != mObjects.end(); oi++) 1015 RenderIntersectable(*oi); 1016 } 1017 } 1018 1019 float 1020 GlRendererWidget::RenderErrors() 1021 { 1022 float pErrorPixels = -1.0f; 1023 1024 glReadBuffer(GL_BACK); 1025 1026 mUseFalseColors = true; 1027 1028 SetupCamera(); 1029 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1030 1031 double eq[4]; 1032 eq[0] = mSceneCutPlane.mNormal.x; 1033 eq[1] = mSceneCutPlane.mNormal.y; 1034 eq[2] = mSceneCutPlane.mNormal.z; 1035 eq[3] = mSceneCutPlane.mD; 1036 1037 if (mCutScene) { 1038 glClipPlane(GL_CLIP_PLANE0, eq); 1039 glEnable(GL_CLIP_PLANE0); 1040 } 1041 1042 if (mDetectEmptyViewSpace) 1043 glEnable( GL_CULL_FACE ); 1044 else 1045 glDisable( GL_CULL_FACE ); 1046 1047 ObjectContainer::const_iterator oi = mObjects.begin(); 1048 for (; oi != mObjects.end(); oi++) 1049 RenderIntersectable(*oi); 1050 1051 ViewCell *viewcell = NULL; 1052 1053 QImage im1, im2; 1054 QImage diff; 1055 1056 if (viewcell) { 1057 // read back the texture 1058 im1 = grabFrameBuffer(true); 1059 1060 RenderPvs(); 1061 1062 // read back the texture 1063 im2 = grabFrameBuffer(true); 1064 1065 diff = im1; 1066 int x, y; 1067 int errorPixels = 0; 1068 1069 for (y = 0; y < im1.height(); y++) 1070 for (x = 0; x < im1.width(); x++) 1071 if (im1.pixel(x, y) == im2.pixel(x, y)) 1072 diff.setPixel(x, y, qRgba(0,0,0,0)); 1073 else { 1074 diff.setPixel(x, y, qRgba(255,128,128,255)); 1075 errorPixels++; 1076 } 1077 pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width()); 1078 } 1079 1080 // now render the pvs again 1081 SetupCamera(); 1082 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1083 mUseFalseColors = false; 1084 1085 oi = mObjects.begin(); 1086 for (; oi != mObjects.end(); oi++) 1087 RenderIntersectable(*oi); 1088 1089 // now render im1 1090 if (viewcell) { 1091 if (0 && mTopView) { 1092 mWireFrame = true; 1093 RenderIntersectable(viewcell); 1094 mWireFrame = false; 1095 } 1096 1097 // init ortographic projection 1098 glMatrixMode(GL_PROJECTION); 1099 glPushMatrix(); 1100 1101 glLoadIdentity(); 1102 gluOrtho2D(0, 1.0f, 0, 1.0f); 1103 1104 glMatrixMode(GL_MODELVIEW); 1105 glLoadIdentity(); 1106 1107 bindTexture(diff); 1108 1109 glPushAttrib(GL_ENABLE_BIT); 1110 glEnable( GL_ALPHA_TEST ); 1111 glDisable( GL_CULL_FACE ); 1112 glAlphaFunc( GL_GREATER, 0.5 ); 1113 1114 glEnable( GL_TEXTURE_2D ); 1115 glBegin(GL_QUADS); 1116 1117 glTexCoord2f(0,0); 1118 glVertex3f(0,0,0); 1119 1120 glTexCoord2f(1,0); 1121 glVertex3f( 1, 0, 0); 1122 1123 glTexCoord2f(1,1); 1124 glVertex3f( 1, 1, 0); 1125 1126 glTexCoord2f(0,1); 1127 glVertex3f(0, 1, 0); 1128 glEnd(); 1129 1130 glPopAttrib(); 1131 1132 // restore the projection matrix 1133 glMatrixMode(GL_PROJECTION); 1134 glPopMatrix(); 1135 glMatrixMode(GL_MODELVIEW); 1136 } 1137 1138 glDisable(GL_CLIP_PLANE0); 1139 1140 mRenderError = pErrorPixels; 1141 return pErrorPixels; 1142 } 1143 1144 void 1145 GlRenderer::_RenderScene() 1146 { 1147 ObjectContainer::const_iterator oi = mObjects.begin(); 1148 1149 for (; oi != mObjects.end(); oi++) 1150 RenderIntersectable(*oi); 1151 } 1152 1153 bool 1154 GlRenderer::RenderScene() 1155 { 1156 static int glList = -1; 1157 if (mUseGlLists) { 1158 if (glList == -1) { 1159 glList = glGenLists(1); 1160 glNewList(glList, GL_COMPILE); 1161 _RenderScene(); 1162 glEndList(); 1163 } 1164 glCallList(glList); 1165 } else 1166 _RenderScene(); 1167 1168 1169 return true; 1170 } 1171 1172 1173 void 1174 GlRendererBuffer::ClearErrorBuffer() 1175 { 1176 for (int i=0; i < mPvsStatFrames; i++) { 1177 mPvsErrorBuffer[i].mError = 1.0f; 1178 } 1179 } 1180 1181 1182 void 1183 GlRendererBuffer::EvalPvsStat() 1184 { 1185 mPvsStat.Reset(); 1186 halton.Reset(); 1187 1188 makeCurrent(); 1189 1190 1191 SetupProjection(GetWidth(), GetHeight()); 1192 1193 1194 for (int i=0; i < mPvsStatFrames; i++) { 1195 float err; 1196 // set frame id for saving the error buffer 1197 mFrame = i; 1198 RandomViewPoint(); 1199 1200 // atlanta problematic frames: 325 525 691 1543 1201 #if 0 1202 if (mFrame != 325 && 1203 mFrame != 525 && 1204 mFrame != 691 && 1205 mFrame != 1543) 1206 mPvsErrorBuffer[i] = -1; 1207 else { 1208 Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl; 1209 } 1210 #endif 1211 if (mPvsErrorBuffer[i].mError > 0.0f) { 1212 int pvsSize; 1213 1214 1215 float error = GetPixelError(pvsSize); 1216 mPvsErrorBuffer[i].mError = error; 1217 mPvsErrorBuffer[i].mPvsSize = pvsSize; 1218 1219 emit UpdatePvsErrorItem(i, 1220 mPvsErrorBuffer[i]); 1221 1222 cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")"; 1223 // swapBuffers(); 1224 } 1225 1226 err = mPvsErrorBuffer[i].mError; 1227 1228 if (err >= 0.0f) { 1229 if (err > mPvsStat.maxError) 1230 mPvsStat.maxError = err; 1231 mPvsStat.sumError += err; 1232 mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize; 1233 1234 if (err == 0.0f) 1235 mPvsStat.errorFreeFrames++; 1236 mPvsStat.frames++; 1237 } 1238 } 1239 1240 glFinish(); 1241 doneCurrent(); 1242 1243 cout<<endl<<flush; 1244 // mRenderingFinished.wakeAll(); 1245 } 1246 1247 1248 1249 1250 1251 void 1252 GlRendererWidget::mousePressEvent(QMouseEvent *e) 1253 { 1254 int x = e->pos().x(); 1255 int y = e->pos().y(); 1256 1257 mousePoint.x = x; 1258 mousePoint.y = y; 1259 1260 } 1261 1262 void 1263 GlRendererWidget::mouseMoveEvent(QMouseEvent *e) 1264 { 1265 float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3; 1266 float TURN_SENSITIVITY=0.1f; 1267 float TILT_SENSITIVITY=32.0 ; 1268 float TURN_ANGLE= M_PI/36.0 ; 1269 1270 int x = e->pos().x(); 1271 int y = e->pos().y(); 1272 1273 if (e->modifiers() & Qt::ControlModifier) { 1274 mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0; 1275 mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0; 1276 } else { 1277 mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY); 1278 float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY; 1279 float angle = atan2(mViewDirection.x, mViewDirection.z); 1280 mViewDirection.x = sin(angle+adiff); 1281 mViewDirection.z = cos(angle+adiff); 1282 } 1283 1284 mousePoint.x = x; 1285 mousePoint.y = y; 1286 1287 updateGL(); 1288 } 1289 1290 void 1291 GlRendererWidget::mouseReleaseEvent(QMouseEvent *) 1292 { 1293 1294 1295 } 1296 1297 void 1298 GlRendererWidget::resizeGL(int w, int h) 1299 { 1300 SetupProjection(w, h); 1301 updateGL(); 1302 } 1303 1304 void 1305 GlRendererWidget::paintGL() 1306 { 1307 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1308 1309 1310 if (!mRenderViewCells) { 1311 if (mRenderErrors) 1312 RenderErrors(); 1313 else 1314 RenderPvs(); 1315 RenderInfo(); 1316 } else { 1317 RenderViewCells(); 1318 1319 mWireFrame = true; 1320 RenderScene(); 1321 mWireFrame = false; 1322 1323 RenderInfo(); 1324 } 1325 1326 mFrame++; 1327 } 1328 1329 1330 void 1331 GlRendererWidget::SetupCamera() 1332 { 1333 if (!mTopView) 1334 GlRenderer::SetupCamera(); 1335 else { 1336 if (0) { 1337 float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05; 1338 Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x, 1339 -1, 1340 mViewDirection.y); 1341 1342 Vector3 target = mViewPoint + dist*mViewDirection; 1343 Vector3 up(0,1,0); 1344 1345 glLoadIdentity(); 1346 gluLookAt(pos.x, pos.y, pos.z, 1347 target.x, target.y, target.z, 1348 up.x, up.y, up.z); 1349 } else { 1350 float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance; 1351 Vector3 pos = mViewPoint + dist*Vector3(0, 1352 1, 1353 0); 1354 1355 Vector3 target = mViewPoint; 1356 Vector3 up(mViewDirection.x, 0, mViewDirection.z); 1357 1358 glLoadIdentity(); 1359 gluLookAt(pos.x, pos.y, pos.z, 1360 target.x, target.y, target.z, 1361 up.x, up.y, up.z); 1362 1363 } 1364 } 1365 1366 } 1367 1368 void 1369 GlRendererWidget::keyPressEvent ( QKeyEvent * e ) 1370 { 1371 switch (e->key()) { 1372 case Qt::Key_T: 1373 mTopView = !mTopView; 1374 SetupProjection(width(), height()); 1375 updateGL(); 1376 break; 1377 case Qt::Key_V: 1378 mRenderViewCells = !mRenderViewCells; 1379 updateGL(); 1380 break; 1381 case Qt::Key_P: 1382 // set random viewpoint 1383 mViewCellsManager->GetViewPoint(mViewPoint); 1384 updateGL(); 1385 break; 1386 1387 default: 1388 e->ignore(); 1389 break; 1390 } 1391 } 1392 1393 1394 RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f): 1395 QWidget(parent, f) 1396 { 1397 1398 QVBoxLayout *vl = new QVBoxLayout; 1399 setLayout(vl); 1400 1401 QWidget *vbox = new QGroupBox("ViewCells", this); 1402 layout()->addWidget(vbox); 1403 1404 vl = new QVBoxLayout; 1405 vbox->setLayout(vl); 1406 1407 QLabel *label = new QLabel("Granularity"); 1408 vbox->layout()->addWidget(label); 1409 1410 QSlider *slider = new QSlider(Qt::Horizontal, vbox); 1411 vl->addWidget(slider); 1412 slider->show(); 1413 slider->setRange(1, 10000); 1414 slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 1415 slider->setValue(200); 1416 1417 connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int))); 1418 1419 label = new QLabel("Filter size"); 1420 vbox->layout()->addWidget(label); 1421 1422 slider = new QSlider(Qt::Horizontal, vbox); 1423 vbox->layout()->addWidget(slider); 1424 slider->show(); 1425 slider->setRange(1, 100); 1426 slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 1427 slider->setValue(3); 1428 1429 connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int))); 1430 1431 1432 label = new QLabel("Spatial Filter size"); 1433 vbox->layout()->addWidget(label); 1434 1435 slider = new QSlider(Qt::Horizontal, vbox); 1436 vbox->layout()->addWidget(slider); 1437 slider->show(); 1438 slider->setRange(1, 100); 1439 slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 1440 slider->setValue(10); 1441 1442 connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSpatialFilterSize(int))); 1443 1444 1445 1446 QWidget *hbox = new QWidget(vbox); 1447 vl->addWidget(hbox); 1448 QHBoxLayout *hlayout = new QHBoxLayout; 1449 hbox->setLayout(hlayout); 1450 1451 QCheckBox *cb = new QCheckBox("Show viewcells", hbox); 1452 hlayout->addWidget(cb); 1453 cb->setChecked(false); 1454 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool))); 1455 1456 cb = new QCheckBox("Show render cost", hbox); 1457 hlayout->addWidget(cb); 1458 cb->setChecked(false); 1459 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool))); 1460 1461 cb = new QCheckBox("Show pvs sizes", hbox); 1462 hlayout->addWidget(cb); 1463 cb->setChecked(false); 1464 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool))); 1465 1466 vbox->resize(800,100); 1467 1468 1469 vbox = new QGroupBox("Rendering", this); 1470 layout()->addWidget(vbox); 1471 1472 vl = new QVBoxLayout; 1473 vbox->setLayout(vl); 1474 1475 1476 1477 slider = new QSlider(Qt::Horizontal, vbox); 1478 vbox->layout()->addWidget(slider); 1479 slider->show(); 1480 slider->setRange(0, 1000); 1481 slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 1482 slider->setValue(1000); 1483 1484 connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int))); 1485 1486 cb = new QCheckBox("Render errors", vbox); 1487 vbox->layout()->addWidget(cb); 1488 cb->setChecked(false); 1489 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool))); 1490 1491 cb = new QCheckBox("Use filter", vbox); 1492 vbox->layout()->addWidget(cb); 1493 cb->setChecked(true); 1494 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseFilter(bool))); 1495 1496 cb = new QCheckBox("Use spatial filter", vbox); 1497 vbox->layout()->addWidget(cb); 1498 cb->setChecked(true); 1499 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseSpatialFilter(bool))); 1500 1501 cb = new QCheckBox("Render filter", vbox); 1502 vbox->layout()->addWidget(cb); 1503 cb->setChecked(true); 1504 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool))); 1505 1506 1507 cb = new QCheckBox("Cut view cells", vbox); 1508 vbox->layout()->addWidget(cb); 1509 cb->setChecked(false); 1510 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool))); 1511 1512 cb = new QCheckBox("Cut scene", vbox); 1513 vbox->layout()->addWidget(cb); 1514 cb->setChecked(false); 1515 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool))); 1516 1517 1518 slider = new QSlider(Qt::Horizontal, vbox); 1519 vbox->layout()->addWidget(slider); 1520 slider->show(); 1521 slider->setRange(1, 1000); 1522 slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 1523 slider->setValue(500); 1524 1525 connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int))); 1526 1527 cb = new QCheckBox("Top View", vbox); 1528 vbox->layout()->addWidget(cb); 1529 cb->setChecked(false); 1530 connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool))); 1531 1532 vbox = new QGroupBox("PVS Errors", this); 1533 layout()->addWidget(vbox); 1534 1535 vl = new QVBoxLayout; 1536 vbox->setLayout(vl); 1537 1538 mPvsErrorWidget = new QListWidget(vbox); 1539 vbox->layout()->addWidget(mPvsErrorWidget); 1540 1541 connect(mPvsErrorWidget, 1542 SIGNAL(doubleClicked(const QModelIndex &)), 1543 this, 1544 SLOT(PvsErrorClicked(const QModelIndex &))); 1545 1546 QPushButton *button = new QPushButton("Next Error Frame", vbox); 1547 vbox->layout()->addWidget(button); 1548 connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void))); 1549 1550 setWindowTitle("Preprocessor Control Widget"); 1551 adjustSize(); 1552 } 1553 1554 1555 1556 void 1557 RendererControlWidget::FocusNextPvsErrorFrame(void) 1558 { 1559 1560 1561 } 1562 1563 void 1564 RendererControlWidget::UpdatePvsErrorItem(int row, 1565 GlRendererBuffer::PvsErrorEntry &pvsErrorEntry) 1566 { 1567 1568 QListWidgetItem *i = mPvsErrorWidget->item(row); 1569 QString s; 1570 s.sprintf("%5.5f", pvsErrorEntry.mError); 1571 if (i) { 1572 i->setText(s); 1573 } else { 1574 new QListWidgetItem(s, mPvsErrorWidget); 1575 } 1576 mPvsErrorWidget->update(); 1577 } 1578 1579 GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph, 1580 ViewCellsManager *viewcells, 1581 KdTree *tree, 1582 QWidget * parent, 1583 const QGLWidget * shareWidget, 1584 Qt::WFlags f 1585 ) 1586 : 1587 GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f) 1588 { 1589 mTopView = false; 1590 mRenderViewCells = false; 1591 mTopDistance = 1.0f; 1592 mCutViewCells = false; 1593 mCutScene = false; 1594 mRenderErrors = false; 1595 mRenderFilter = true; 1596 1597 bool tmp; 1598 1599 Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", tmp ); 1600 mUseFilter = tmp; 1601 1602 Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter", 1603 tmp ); 1604 1605 mUseSpatialFilter = tmp; 1606 1607 mShowRenderCost = false; 1608 mShowPvsSizes = false; 1609 mSpatialFilterSize = 0.01; 1610 mPvsSize = 0; 1611 mRenderError = 0.0f; 1612 mControlWidget = new RendererControlWidget(NULL); 1613 1614 connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int))); 1615 connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int))); 1616 connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int))); 1617 1618 connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int))); 1619 connect(mControlWidget, SIGNAL(SetSpatialFilterSize(int)), this, SLOT(SetSpatialFilterSize(int))); 1620 1621 connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool))); 1622 connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool))); 1623 connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool))); 1624 connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool))); 1625 connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool))); 1626 connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool))); 1627 connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool))); 1628 connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool))); 1629 connect(mControlWidget, SIGNAL(SetUseFilter(bool)), this, SLOT(SetUseFilter(bool))); 1630 connect(mControlWidget, SIGNAL(SetUseSpatialFilter(bool)), 1631 this, SLOT(SetUseSpatialFilter(bool))); 1632 1633 1634 mControlWidget->show(); 1635 } 1636 1637 void 1638 GlRendererWidget::SetViewCellGranularity(int number) 1639 { 1640 if (mViewCellsManager) 1641 // mViewCellsManager->SetMaxFilterSize(number); 1642 mViewCellsManager->CollectViewCells(number); 1643 1644 updateGL(); 1645 } 1646 1647 void 1648 GlRendererWidget::SetVisibilityFilterSize(int number) 1649 { 1650 if (mViewCellsManager) 1651 mViewCellsManager->SetMaxFilterSize(number); 1652 updateGL(); 1653 } 1654 1655 void 1656 GlRendererWidget::SetSpatialFilterSize(int number) 1657 { 1658 mSpatialFilterSize = 1e-3*number; 1659 updateGL(); 1660 } 1661 1662 void 1663 GlRendererWidget::SetSceneCut(int number) 1664 { 1665 // assume the cut plane can only be aligned with xz plane 1666 // shift it along y according to number, which is percentage of the bounding 1667 // box position 1668 if (mViewCellsManager) { 1669 AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox(); 1670 Vector3 p = box.Min() + (number/1000.0f)*box.Max(); 1671 mSceneCutPlane.mNormal = Vector3(0,-1,0); 1672 mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p); 1673 updateGL(); 1674 } 1675 } 1676 1677 void 1678 GlRendererWidget::SetTopDistance(int number) 1679 { 1680 mTopDistance = number/1000.0f; 1681 updateGL(); 1682 } 1683 1684 void 1685 GlRendererWidget::RenderViewCells() 1686 { 1687 mUseFalseColors = true; 1688 1689 SetupCamera(); 1690 glEnable(GL_CULL_FACE); 1691 //glDisable(GL_CULL_FACE); 1692 glCullFace(GL_FRONT); 1693 double eq[4]; 1694 eq[0] = mSceneCutPlane.mNormal.x; 1695 eq[1] = mSceneCutPlane.mNormal.y; 1696 eq[2] = mSceneCutPlane.mNormal.z; 1697 eq[3] = mSceneCutPlane.mD; 1698 1699 if (mCutViewCells) { 1700 glClipPlane(GL_CLIP_PLANE0, eq); 1701 glEnable(GL_CLIP_PLANE0); 1702 } 1703 1704 int i; 1705 ViewCellContainer &viewcells = mViewCellsManager->GetViewCells(); 1706 int maxPvs = -1; 1707 for (i=0; i < viewcells.size(); i++) 1708 { 1709 ViewCell *vc = viewcells[i]; 1710 const int p = vc->GetPvs().CountPvs(); 1711 if (p > maxPvs) 1712 maxPvs = p; 1713 } 1714 1715 1716 for (i=0; i < viewcells.size(); i++) { 1717 ViewCell *vc = viewcells[i]; 1718 // Mesh *m = vc->GetMesh(); 1719 1720 1721 RgbColor c; 1722 1723 if (!mShowPvsSizes) 1724 c = vc->GetColor(); 1725 else { 1726 const float importance = (float)vc->GetPvs().CountPvs() / (float)maxPvs; 1727 c = RgbColor(importance, 1.0f - importance, 0.0f); 1728 } 1729 glColor3f(c.r, c.g, c.b); 1730 1731 RenderViewCell(vc); 1732 } 1733 1734 glDisable(GL_CLIP_PLANE0); 1735 1736 } 1737 1738 void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject, 1739 Beam &beam, 1740 const int desiredSamples, 1741 BeamSampleStatistics &stat) 1742 { 1743 // TODO: should be moved out of here (not to be done every time) 1744 // only back faces are interesting for the depth pass 1745 glShadeModel(GL_FLAT); 1746 glDisable(GL_LIGHTING); 1747 1748 // needed to kill the fragments for the front buffer 1749 glEnable(GL_ALPHA_TEST); 1750 glAlphaFunc(GL_GREATER, 0); 1751 1752 // assumes that the beam is constructed and contains kd-tree nodes 1753 // and viewcells which it intersects 1754 1755 1756 // Get the number of viewpoints to be sampled 1757 // Now it is a sqrt but in general a wiser decision could be made. 1758 // The less viewpoints the better for rendering performance, since less passes 1759 // over the beam is needed. 1760 // The viewpoints could actually be generated outside of the bounding box which 1761 // would distribute the 'efective viewpoints' of the object surface and thus 1762 // with a few viewpoints better sample the viewpoint space.... 1763 1764 //TODO: comment in 1765 //int viewPointSamples = sqrt((float)desiredSamples); 1766 int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1); 1767 1768 // the number of direction samples per pass is given by the number of viewpoints 1769 int directionalSamples = desiredSamples / viewPointSamples; 1770 1771 Debug << "directional samples: " << directionalSamples << endl; 1772 for (int i = 0; i < viewPointSamples; ++ i) 1773 { 1774 Vector3 viewPoint = beam.mBox.GetRandomPoint(); 1775 1776 // perhaps the viewpoint should be shifted back a little bit so that it always lies 1777 // inside the source object 1778 // 'ideally' the viewpoints would be distributed on the soureObject surface, but this 1779 // would require more complicated sampling (perhaps hierarchical rejection sampling of 1780 // the object surface is an option here - only the mesh faces which are inside the box 1781 // are considered as candidates) 1782 1783 SampleViewpointContributions(sourceObject, 1784 viewPoint, 1785 beam, 1786 directionalSamples, 1787 stat); 1788 } 1789 1790 1791 // note: 1792 // this routine would be called only if the number of desired samples is sufficiently 1793 // large - for other rss tree cells the cpu based sampling is perhaps more efficient 1794 // distributing the work between cpu and gpu would also allow us to place more sophisticated 1795 // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU 1796 // in order that thios scheme is working well the gpu render buffer should run in a separate 1797 // thread than the cpu sampler, which would not be such a big problem.... 1798 1799 // disable alpha test again 1800 glDisable(GL_ALPHA_TEST); 1801 } 1802 1803 1804 void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject, 1805 const Vector3 viewPoint, 1806 Beam &beam, 1807 const int samples, 1808 BeamSampleStatistics &stat) 1809 { 1810 // 1. setup the view port to match the desired samples 1811 glViewport(0, 0, samples, samples); 1812 1813 // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox 1814 SetupProjectionForViewPoint(viewPoint, beam, sourceObject); 1815 1816 1817 // 3. reset z-buffer to 0 and render the source object for the beam 1818 // with glCullFace(Enabled) and glFrontFace(GL_CW) 1819 // save result to the front depth map 1820 // the front depth map holds ray origins 1821 1822 1823 // front depth buffer must be initialised to 0 1824 float clearDepth; 1825 1826 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); 1827 glClearDepth(0.0f); 1828 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 1829 1830 1831 //glFrontFace(GL_CW); 1832 glEnable(GL_CULL_FACE); 1833 glCullFace(GL_FRONT); 1834 glColorMask(0, 0, 0, 0); 1835 1836 1837 // stencil is increased where the source object is located 1838 glEnable(GL_STENCIL_TEST); 1839 glStencilFunc(GL_ALWAYS, 0x1, 0x1); 1840 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 1841 1842 1843 #if 0 1844 static int glSourceObjList = -1; 1845 if (glSourceObjList != -1) 1846 { 1847 glSourceObjList = glGenLists(1); 1848 glNewList(glSourceObjList, GL_COMPILE); 1849 1850 RenderIntersectable(sourceObject); 1851 1852 glEndList(); 1853 } 1854 glCallList(glSourceObjList); 1855 1856 #else 1857 RenderIntersectable(sourceObject); 1858 1859 #endif 1860 1861 // copy contents of the front depth buffer into depth texture 1862 glBindTexture(GL_TEXTURE_2D, frontDepthMap); 1863 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize); 1864 1865 1866 // reset clear function 1867 glClearDepth(clearDepth); 1868 1869 1870 1871 // 4. set up the termination depth buffer (= standard depth buffer) 1872 // only rays which have non-zero entry in the origin buffer are valid since 1873 // they realy start on the object surface (this is tagged by setting a 1874 // stencil buffer bit at step 3). 1875 1876 glStencilFunc(GL_EQUAL, 0x1, 0x1); 1877 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 1878 1879 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1880 glDepthMask(1); 1881 1882 glEnable(GL_DEPTH_TEST); 1883 1884 glEnable(GL_CULL_FACE); 1885 glCullFace(GL_BACK); 1886 1887 // setup front depth buffer 1888 glEnable(GL_TEXTURE_2D); 1889 1890 // bind pixel shader implementing the front depth buffer functionality 1891 cgGLBindProgram(sCgFragmentProgram); 1892 cgGLEnableProfile(sCgFragmentProfile); 1893 1894 1895 // 5. render all objects inside the beam 1896 // we can use id based false color to read them back for gaining the pvs 1897 1898 glColorMask(1, 1, 1, 1); 1899 1900 1901 // if objects not stored in beam => extract objects 1902 if (beam.mFlags & !Beam::STORE_OBJECTS) 1903 { 1904 vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end(); 1905 1906 Intersectable::NewMail(); 1907 for (it = beam.mKdNodes.begin(); it != it_end; ++ it) 1908 { 1909 mKdTree->CollectObjects(*it, beam.mObjects); 1910 } 1911 } 1912 1913 1914 // (objects can be compiled to a gl list now so that subsequent rendering for 1915 // this beam is fast - the same hold for step 3) 1916 // Afterwards we have two depth buffers defining the ray origin and termination 1917 1918 1919 #if 0 1920 static int glObjList = -1; 1921 if (glObjList != -1) 1922 { 1923 glObjList = glGenLists(1); 1924 glNewList(glObjList, GL_COMPILE); 1925 1926 ObjectContainer::const_iterator it, it_end = beam.mObjects.end(); 1927 for (it = beam.mObjects.begin(); it != it_end; ++ it) 1928 { 1929 // render all objects except the source object 1930 if (*it != sourceObject) 1931 RenderIntersectable(*it); 1932 } 1933 1934 glEndList(); 1935 } 1936 1937 glCallList(glObjList); 1938 #else 1939 ObjectContainer::const_iterator it, it_end = beam.mObjects.end(); 1940 for (it = beam.mObjects.begin(); it != it_end; ++ it) 1941 { 1942 // render all objects except the source object 1943 if (*it != sourceObject) 1944 RenderIntersectable(*it); 1945 } 1946 #endif 1947 1948 1949 1950 // 6. Use occlusion queries for all viewcell meshes associated with the beam -> 1951 // a fragment passes if the corresponding stencil fragment is set and its depth is 1952 // between origin and termination buffer 1953 1954 // create new queries if necessary 1955 OcclusionQuery::GenQueries(sQueries, (int)beam.mViewCells.size()); 1956 1957 // check whether any backfacing polygon would pass the depth test? 1958 // matt: should check both back /front facing because of dual depth buffer 1959 // and danger of cutting the near plane with front facing polys. 1960 1961 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1962 glDepthMask(GL_FALSE); 1963 glDisable(GL_CULL_FACE); 1964 1965 1966 ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end(); 1967 1968 int queryIdx = 0; 1969 1970 for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit) 1971 { 1972 sQueries[queryIdx ++]->BeginQuery(); 1973 1974 RenderIntersectable(*vit); 1975 1976 sQueries[queryIdx]->EndQuery(); 1977 1978 ++ queryIdx; 1979 } 1980 1981 1982 1983 // at this point, if possible, go and do some other computation 1984 1985 1986 1987 // 7. The number of visible pixels is the number of sample rays which see the source 1988 // object from the corresponding viewcell -> remember these values for later update 1989 // of the viewcell pvs - or update immediately? 1990 1991 queryIdx = 0; 1992 1993 for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit) 1994 { 1995 // fetch queries 1996 unsigned int pixelCount = sQueries[queryIdx ++]->GetQueryResult(); 1997 1998 if (pixelCount) 1999 Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl; 2000 } 2001 2002 2003 // 8. Copmpute rendering statistics 2004 // In general it is not neccessary to remember to extract all the rays cast. I hope it 2005 // would be sufficient to gain only the intergral statistics about the new contributions 2006 // and so the rss tree would actually store no new rays (only the initial ones) 2007 // the subdivision of the tree would only be driven by the statistics (the glrender could 2008 // evaluate the contribution entropy for example) 2009 // However might be an option to extract/store only those the rays which made a contribution 2010 // (new viewcell has been discovered) or relative contribution greater than a threshold ... 2011 2012 ObjectContainer pvsObj; 2013 stat.pvsSize = ComputePvs(beam.mObjects, pvsObj); 2014 2015 // to gain ray source and termination 2016 // copy contents of ray termination buffer into depth texture 2017 // and compare with ray source buffer 2018 #if 0 2019 VssRayContainer rays; 2020 2021 glBindTexture(GL_TEXTURE_2D, backDepthMap); 2022 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize); 2023 2024 ComputeRays(Intersectable *sourceObj, rays); 2025 2026 #endif 2027 2028 2029 2030 //-- cleanup 2031 2032 2033 // reset gl state 2034 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 2035 glDepthMask(GL_TRUE); 2036 glEnable(GL_CULL_FACE); 2037 glDisable(GL_STENCIL_TEST); 2038 cgGLDisableProfile(sCgFragmentProfile); 2039 glDisable(GL_TEXTURE_2D); 2040 2041 // remove objects from beam 2042 if (beam.mFlags & !Beam::STORE_OBJECTS) 2043 beam.mObjects.clear(); 2044 } 2045 2046 2047 void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint, 2048 const Beam &beam, 2049 Intersectable *sourceObject) 2050 { 2051 float left, right, bottom, top, znear, zfar; 2052 2053 beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar, 2054 mSceneGraph->GetBox()); 2055 2056 //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl; 2057 glMatrixMode(GL_PROJECTION); 2058 glLoadIdentity(); 2059 glFrustum(left, right, bottom, top, znear, zfar); 2060 //glFrustum(-1, 1, -1, 1, 1, 20000); 2061 2062 const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f; 2063 const Vector3 up = 2064 Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal)); 2065 2066 #ifdef _DEBUG 2067 Debug << "view point: " << viewPoint << endl; 2068 Debug << "eye: " << center << endl; 2069 Debug << "up: " << up << endl; 2070 #endif 2071 2072 glMatrixMode(GL_MODELVIEW); 2073 glLoadIdentity(); 2074 gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z, 2075 center.x, center.y, center.z, 2076 up.x, up.y, up.z); 2077 } 2078 2079 2080 void GlRendererBuffer::InitGL() 2081 { 2082 makeCurrent(); 2083 GlRenderer::InitGL(); 2084 2085 #if 1 2086 // initialise dual depth buffer textures 2087 glGenTextures(1, &frontDepthMap); 2088 glBindTexture(GL_TEXTURE_2D, frontDepthMap); 2089 2090 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 2091 depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); 2092 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2093 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2094 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 2095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 2096 2097 glGenTextures(1, &backDepthMap); 2098 glBindTexture(GL_TEXTURE_2D, backDepthMap); 2099 2100 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 2101 depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); 2102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 2105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 2106 2107 // cg initialization 2108 cgSetErrorCallback(handleCgError); 2109 sCgContext = cgCreateContext(); 2110 2111 if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1)) 2112 sCgFragmentProfile = CG_PROFILE_ARBFP1; 2113 else 2114 { 2115 // try FP30 2116 if (cgGLIsProfileSupported(CG_PROFILE_FP30)) 2117 sCgFragmentProfile = CG_PROFILE_FP30; 2118 else 2119 { 2120 Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl; 2121 exit(1); 2122 } 2123 } 2124 2125 2126 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext, 2127 CG_SOURCE, "../src/dual_depth.cg", 2128 sCgFragmentProfile, 2129 NULL, 2130 NULL); 2131 2132 if (!cgIsProgramCompiled(sCgFragmentProgram)) 2133 cgCompileProgram(sCgFragmentProgram); 2134 2135 cgGLLoadProgram(sCgFragmentProgram); 2136 cgGLBindProgram(sCgFragmentProgram); 2137 2138 Debug << "---- PROGRAM BEGIN ----\n" << 2139 cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n"; 2140 2141 #endif 2142 doneCurrent(); 2143 } 2144 2145 2146 void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays) 2147 { 2148 for (int i = 0; i < depthMapSize * depthMapSize; ++ i) 2149 { 2150 //todo glGetTexImage() 2151 } 2152 } 2153 2154 2155 2156 inline bool ilt(Intersectable *obj1, Intersectable *obj2) 2157 { 2158 return obj1->mId < obj2->mId; 2159 } 2160 2161 2162 int GlRendererBuffer::ComputePvs(ObjectContainer &objects, 2163 ObjectContainer &pvs) const 2164 { 2165 int pvsSize = 0; 2166 QImage image = toImage(); 2167 Intersectable::NewMail(); 2168 2169 std::stable_sort(objects.begin(), objects.end(), ilt); 2170 2171 MeshInstance dummy(NULL); 2172 2173 Intersectable *obj = NULL; 2174 2175 for (int x = 0; x < image.width(); ++ x) 2176 { 2177 for (int y = 0; y < image.height(); ++ y) 2178 { 2179 QRgb pix = image.pixel(x, y); 2180 const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix)); 2181 2182 dummy.SetId(id); 2183 2184 ObjectContainer::iterator oit = 2185 lower_bound(objects.begin(), objects.end(), &dummy, ilt); 2186 2187 2188 if (//(oit != oit.end()) && 2189 ((*oit)->GetId() == id) && 2190 !obj->Mailed()) 2191 { 2192 obj = *oit; 2193 obj->Mail(); 2194 ++ pvsSize; 2195 pvs.push_back(obj); 2196 } 2197 } 2198 } 2199 2200 return pvsSize; 2201 } 2202 2203 /***********************************************************************/ 2204 /* GlDebuggerWidget implementation */ 2205 /***********************************************************************/ 2206 2207 2208 GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent) 2209 : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf) 2210 { 2211 // create the pbuffer 2212 //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this); 2213 timerId = startTimer(20); 2214 setWindowTitle(("OpenGL pbuffers")); 2215 } 2216 2217 2218 GlDebuggerWidget::~GlDebuggerWidget() 2219 { 2220 mRenderBuffer->releaseFromDynamicTexture(); 2221 glDeleteTextures(1, &dynamicTexture); 2222 2223 DEL_PTR(mRenderBuffer); 2224 } 2225 2226 2227 void GlDebuggerWidget::initializeGL() 2228 { 2229 glMatrixMode(GL_PROJECTION); 2230 glLoadIdentity(); 2231 2232 glFrustum(-1, 1, -1, 1, 10, 100); 2233 glTranslatef(-0.5f, -0.5f, -0.5f); 2234 glTranslatef(0.0f, 0.0f, -15.0f); 2235 glMatrixMode(GL_MODELVIEW); 2236 2237 glEnable(GL_CULL_FACE); 2238 initCommon(); 2239 initPbuffer(); 2240 2241 } 2242 2243 2244 void GlDebuggerWidget::resizeGL(int w, int h) 2245 { 2246 glViewport(0, 0, w, h); 2247 } 2248 2249 2250 void GlDebuggerWidget::paintGL() 2251 { 2252 // draw a spinning cube into the pbuffer.. 2253 mRenderBuffer->makeCurrent(); 2254 2255 BeamSampleStatistics stats; 2256 mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats); 2257 2258 glFlush(); 2259 2260 // rendering directly to a texture is not supported on X11, unfortunately 2261 mRenderBuffer->updateDynamicTexture(dynamicTexture); 2262 2263 // and use the pbuffer contents as a texture when rendering the 2264 // background and the bouncing cubes 2265 makeCurrent(); 2266 glBindTexture(GL_TEXTURE_2D, dynamicTexture); 2267 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 2268 2269 // draw the background 2270 glMatrixMode(GL_MODELVIEW); 2271 glPushMatrix(); 2272 glLoadIdentity(); 2273 glMatrixMode(GL_PROJECTION); 2274 glPushMatrix(); 2275 glLoadIdentity(); 2276 2277 glPopMatrix(); 2278 glMatrixMode(GL_MODELVIEW); 2279 glPopMatrix(); 2280 } 2281 2282 2283 void GlDebuggerWidget::initPbuffer() 2284 { 2285 // set up the pbuffer context 2286 mRenderBuffer->makeCurrent(); 2287 /*mRenderBuffer->InitGL(); 2288 2289 glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height()); 2290 glMatrixMode(GL_PROJECTION); 2291 glLoadIdentity(); 2292 glOrtho(-1, 1, -1, 1, -99, 99); 2293 glTranslatef(-0.5f, -0.5f, 0.0f); 2294 glMatrixMode(GL_MODELVIEW); 2295 glLoadIdentity(); 2296 2297 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/ 2298 2299 // generate a texture that has the same size/format as the pbuffer 2300 dynamicTexture = mRenderBuffer->generateDynamicTexture(); 2301 2302 // bind the dynamic texture to the pbuffer - this is a no-op under X11 2303 mRenderBuffer->bindToDynamicTexture(dynamicTexture); 2304 makeCurrent(); 2305 } 2306 2307 void GlDebuggerWidget::initCommon() 2308 { 2309 glEnable(GL_TEXTURE_2D); 2310 glEnable(GL_DEPTH_TEST); 2311 2312 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 2313 } 2314 2315 } 547 } -
GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h
r1008 r1145 3 3 4 4 //#include "glInterface.h" 5 #include <QtOpenGL> 6 #include <QWaitCondition>7 5 6 //#include <QWaitCondition> 7 //#include <QtOpenGL> 8 8 //#include <QGLPixelBuffer> 9 10 //class QWidget; 9 11 10 12 #include "Vector3.h" … … 14 16 #include "Beam.h" 15 17 16 class QWidget;17 18 18 19 namespace GtpVisibilityPreprocessor { … … 105 106 bool mUseGlLists; 106 107 107 QString mSnapPrefix;108 string mSnapPrefix; 108 109 109 110 KdTree *mKdTree; 110 111 111 QWaitCondition mRenderingFinished;112 //QWaitCondition mRenderingFinished; 112 113 113 114 vector<OcclusionQuery *> mOcclusionQueries; … … 117 118 KdTree *tree); 118 119 119 ~GlRenderer();120 virtual ~GlRenderer(); 120 121 121 122 … … 151 152 152 153 153 class GlRendererBuffer : public QObject, public QGLPixelBuffer,public GlRenderer154 class GlRendererBuffer: public GlRenderer 154 155 { 155 Q_OBJECT 156 157 //Q_OBJECT 156 158 public: 157 GlRendererBuffer(const int w, 158 const int h, 159 SceneGraph *sceneGraph, 159 GlRendererBuffer(SceneGraph *sceneGraph, 160 160 ViewCellsManager *viewcells, 161 161 KdTree *tree); … … 182 182 vector<RenderCostSample> &samples, 183 183 const bool useOcclusionQueries, 184 const int threshold = 0) ;185 186 187 void 188 EvalPvsStat(); 189 190 void 191 192 193 194 virtual int GetWidth() const { return width(); }195 virtual int GetHeight() const { return height(); }184 const int threshold = 0) 185 {} 186 187 /** Implerment in subclasses. 188 */ 189 void EvalPvsStat() {}; 190 191 void ClearErrorBuffer(); 192 193 194 virtual int GetWidth() const { return 0; } 195 virtual int GetHeight() const { return 0; } 196 196 197 197 … … 230 230 int mPvsStatFrames; 231 231 struct PvsErrorEntry { 232 PvsErrorEntry() {}233 float mError;234 int mPvsSize;235 Vector3 mPosition;236 Vector3 mDirection;232 PvsErrorEntry() {} 233 float mError; 234 int mPvsSize; 235 Vector3 mPosition; 236 Vector3 mDirection; 237 237 }; 238 238 … … 240 240 241 241 242 pr ivate:243 242 protected: 243 unsigned int *mPixelBuffer; 244 244 245 245 static void GenQueries(const int numQueries); … … 258 258 259 259 public: 260 signals: 261 void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &); 262 }; 263 264 265 class RendererControlWidget : public QWidget 266 { 267 Q_OBJECT 268 public: 269 270 QListWidget *mPvsErrorWidget; 271 272 RendererControlWidget(QWidget * parent = 0, Qt::WFlags f = 0); 273 274 public slots: 275 276 void FocusNextPvsErrorFrame(); 277 void UpdatePvsErrorItem(int i, 278 GlRendererBuffer::PvsErrorEntry &); 279 280 signals: 281 282 void SetViewCellGranularity(int); 283 void SetSceneCut(int); 284 void SetTopDistance(int); 285 void SetVisibilityFilterSize(int); 286 void SetSpatialFilterSize(int); 287 288 void SetRenderFilter(bool); 289 void SetUseFilter(bool); 290 void SetUseSpatialFilter(bool); 291 void SetRenderErrors(bool); 292 void SetShowViewCells(bool); 293 void SetShowRenderCost(bool); 294 void SetShowPvsSizes(bool); 295 void SetTopView(bool); 296 void SetCutViewCells(bool); 297 void SetCutScene(bool); 298 299 300 }; 301 302 class GlRendererWidget : public QGLWidget, public GlRenderer 303 { 304 Q_OBJECT 305 public: 306 307 // point of the last mouse click used for movement in the scene 308 Vector3 mousePoint; 309 310 bool mTopView; 311 bool mRenderViewCells; 312 bool mCutViewCells; 313 bool mCutScene; 314 bool mRenderErrors; 315 bool mRenderFilter; 316 bool mUseFilter; 317 bool mUseSpatialFilter; 318 bool mShowRenderCost; 319 320 bool mShowPvsSizes; 321 float mSpatialFilterSize; 322 323 Plane3 mSceneCutPlane; 324 float mTopDistance; 325 326 // some statistics 327 int mPvsSize; 328 float mRenderError; 329 330 RendererControlWidget *mControlWidget; 331 332 GlRendererWidget(SceneGraph *sceneGraph, 333 ViewCellsManager *viewcells, 334 KdTree *tree, 335 QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WFlags f = 0 336 ); 337 338 339 virtual void SetupCamera(); 340 341 void initializeGL() { 342 InitGL(); 343 } 344 void resizeGL(int w, int h); 345 void paintGL(); 346 void timerEvent(QTimerEvent *) { 347 update(); 348 } 349 350 void mousePressEvent(QMouseEvent *); 351 void mouseReleaseEvent(QMouseEvent *); 352 void mouseMoveEvent(QMouseEvent *); 353 354 void keyPressEvent ( QKeyEvent * e ) ; 355 356 void 357 RenderPvs(); 358 359 float 360 RenderErrors(); 361 void 362 RenderInfo(); 363 364 virtual int GetWidth() const { return width(); } 365 virtual int GetHeight() const { return height(); } 366 367 virtual void 368 SetupProjection(const int w, const int h, const float angle = 70.0f); 369 370 void 371 RenderViewCells(); 372 373 public slots: 374 375 void SetRenderErrors(bool b) { 376 mRenderErrors = b; 377 updateGL(); 378 } 379 380 void SetRenderFilter(bool b) { 381 mRenderFilter = b; 382 updateGL(); 383 } 384 385 void SetUseFilter(bool b) { 386 mUseFilter = b; 387 updateGL(); 388 } 389 390 void SetUseSpatialFilter(bool b) { 391 mUseSpatialFilter = b; 392 updateGL(); 393 } 394 395 396 void 397 SetViewCellGranularity(int number); 398 399 void 400 SetVisibilityFilterSize(int number); 401 402 void 403 SetSpatialFilterSize(int number); 404 405 void 406 SetSceneCut(int cut); 407 408 void 409 SetTopDistance(int dist); 410 411 void SetShowViewCells(bool b) { 412 mRenderViewCells = b; 413 updateGL(); 414 } 415 416 void SetShowRenderCost(bool b) { 417 mShowRenderCost = b; 418 updateGL(); 419 } 420 421 void SetShowPvsSizes(bool b) { 422 mShowPvsSizes = b; 423 updateGL(); 424 } 425 426 void SetTopView(bool b) { 427 mTopView = b; 428 updateGL(); 429 } 430 431 void SetCutViewCells(bool b) { 432 mCutViewCells = b; 433 updateGL(); 434 } 435 void SetCutScene(bool b) { 436 mCutScene = b; 437 updateGL(); 438 } 439 440 441 }; 442 443 444 extern GlRendererWidget *rendererWidget; 445 446 class GlDebuggerWidget : public QGLWidget 447 { 448 Q_OBJECT 449 public: 450 GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent = NULL); 451 ~GlDebuggerWidget(); 452 void initializeGL(); 453 void resizeGL(int w, int h); 454 void paintGL(); 455 void timerEvent(QTimerEvent *) { update(); } 456 void mousePressEvent(QMouseEvent *) { killTimer(timerId); } 457 void mouseReleaseEvent(QMouseEvent *) { timerId = startTimer(20); } 458 459 void initCommon(); 460 void initPbuffer(); 461 462 463 GlRendererBuffer *mRenderBuffer; 464 465 Beam mBeam; 466 int mSamples; 467 Intersectable *mSourceObject; 468 469 private: 470 GLuint dynamicTexture; 471 int timerId; 472 }; 473 474 extern GlDebuggerWidget *debuggerWidget; 260 // matt: remove qt dependencies 261 // signals: 262 // void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &); 263 }; 475 264 476 265 }; -
GTP/trunk/Lib/Vis/Preprocessing/src/OcclusionQuery.cpp
r1001 r1145 1 //#include "glInterface.h"2 1 #include "OcclusionQuery.h" 3 2 #include <iostream> 4 //#include <GL/gl.h>5 //#include <QtOpenGL>6 3 #include <glInterface.h> 7 4 -
GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
r1144 r1145 21 21 const static bool ADDITIONAL_GEOMETRY_HACK = false; 22 22 23 Preprocessor *preprocessor;23 //Preprocessor *preprocessor; 24 24 25 25 … … 163 163 cout << "done.\n"; 164 164 165 #if 0 166 cout << "Deleting vsp osp tree...\n"; 167 DEL_PTR(mVspOspTree); 165 cout << "Deleting vsp tree...\n"; 166 DEL_PTR(mVspTree); 168 167 cout << "done.\n"; 169 #endif 168 169 cout << "Deleting osp tree...\n"; 170 DEL_PTR(mOspTree); 171 cout << "done.\n"; 170 172 171 173 cout << "Deleting vspbsp tree...\n"; … … 408 410 // NOTE: render texture should be power of 2 and square 409 411 // renderer must be initialised 410 renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree); 412 // $$matt 413 // renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree); 411 414 // renderer->makeCurrent(); 412 415 … … 468 471 469 472 470 inline bool ilt(Intersectable *obj1, Intersectable *obj2)473 static inline bool ilt(Intersectable *obj1, Intersectable *obj2) 471 474 { 472 475 return obj1->mId < obj2->mId; -
GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
r1022 r1145 8 8 #include "KdTree.h" 9 9 10 #include <QObject> 10 // matt: remove qt dependencies 11 //#include <QObject> 11 12 12 13 namespace GtpVisibilityPreprocessor { … … 33 34 */ 34 35 35 /** Main class of the visibility preprocessor. Responsible for loading and 36 saving of the input and output files. Initiates construction of the kD-tree, 37 viewcell loading/generation and the visibility computation itself. 38 */ 39 class Preprocessor : public QObject { 40 Q_OBJECT 36 /** Main class of the visibility preprocessor. Responsible for loading and 37 saving of the input and output files. Initiates construction of the kD-tree, 38 viewcell loading/generation and the visibility computation itself. 39 */ 40 // matt: remove qt dependencies 41 class Preprocessor// : public QObject 42 { 43 //Q_OBJECT 41 44 42 45 public: … … 49 52 /** Load the input scene. 50 53 @param filename file to load 51 @return true on success54 @return true on success 52 55 */ 53 56 virtual bool LoadScene(const string filename); … … 202 205 203 206 GlRendererBuffer *renderer; 204 205 207 // matt: remove qt dependencies 208 //signals: 206 209 void EvalPvsStat(); 207 210 208 211 }; 209 212 210 211 212 extern Preprocessor *preprocessor; 213 //extern Preprocessor *preprocessor; 213 214 214 215 } -
GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp
r878 r1145 1 #include <QApplication> 2 1 //#include <QApplication> 3 2 #include "PreprocessorThread.h" 4 3 #include "Camera.h" … … 11 10 12 11 12 // matt: remove qt dependencies 13 /* 13 14 PreprocessorThread::PreprocessorThread(Preprocessor *p, 14 15 QObject *parent):QThread(parent) 15 16 { 16 17 mPreprocessor = p; 18 17 19 if (p->mQuitOnFinish) 18 20 connect(this, SIGNAL(finished()), qApp, SLOT(closeAllWindows(void))); 19 21 } 22 */ 20 23 21 void 22 PreprocessorThread::Main()24 PreprocessorThread::PreprocessorThread(Preprocessor *p): 25 mPreprocessor(p) 23 26 { 24 25 Camera camera; 26 27 if (0) { 28 // camera.LookAtBox(mPreprocessor->mKdTree->GetBox()); 29 // camera.LookInBox(mPreprocessor->mKdTree->GetBox()); 30 camera.SetPosition(Vector3(3473, 6.778, -1699)); 31 camera.SetDirection(Vector3(-0.2432, 0, 0.97)); 32 // camera.SetPosition(Vector3(991.7, 187.8, -271)); 33 // camera.SetDirection(Vector3(0.9, 0, -0.4)); 34 35 camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 36 } 37 38 if (0) { 39 camera.LookInBox(mPreprocessor->mKdTree->GetBox()); 40 camera.SetPosition(camera.mPosition + Vector3(-250,0,-550)); 41 camera.SnapImage("camera2.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 42 } 43 44 if (0) { 45 camera.SetPosition( mPreprocessor->mKdTree->GetBox().Center() - Vector3(0,-100,0) ); 46 camera.SetDirection(Vector3(1, 0, 0)); 47 camera.SnapImage("camera3.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 48 } 49 50 if (mPreprocessor->mComputeVisibility) { 51 mPreprocessor->ComputeVisibility(); 52 // mPreprocessor->ExportPreprocessedData("scene.vis"); 53 mPreprocessor->PostProcessVisibility(); 54 } 55 27 } 56 28 57 29 58 cerr << "Preprocessor main finished...\n"; 30 void PreprocessorThread::operator()() 31 { 32 Main(); 33 } 34 35 void PreprocessorThread::Main() 36 { 37 Camera camera; 38 39 if (0) 40 { 41 // camera.LookAtBox(mPreprocessor->mKdTree->GetBox()); 42 // camera.LookInBox(mPreprocessor->mKdTree->GetBox()); 43 camera.SetPosition(Vector3(3473, 6.778, -1699)); 44 camera.SetDirection(Vector3(-0.2432, 0, 0.97)); 45 // camera.SetPosition(Vector3(991.7, 187.8, -271)); 46 // camera.SetDirection(Vector3(0.9, 0, -0.4)); 47 48 camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 49 } 50 51 if (0) { 52 camera.LookInBox(mPreprocessor->mKdTree->GetBox()); 53 camera.SetPosition(camera.mPosition + Vector3(-250,0,-550)); 54 camera.SnapImage("camera2.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 55 } 56 57 if (0) { 58 camera.SetPosition( mPreprocessor->mKdTree->GetBox().Center() - Vector3(0,-100,0) ); 59 camera.SetDirection(Vector3(1, 0, 0)); 60 camera.SnapImage("camera3.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph); 61 } 62 63 if (mPreprocessor->mComputeVisibility) { 64 mPreprocessor->ComputeVisibility(); 65 // mPreprocessor->ExportPreprocessedData("scene.vis"); 66 mPreprocessor->PostProcessVisibility(); 67 } 68 69 cerr << "Preprocessor main finished...\n"; 59 70 60 71 } -
GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h
r860 r1145 1 1 #ifndef __PREPROCESSOR_THREAD_H 2 2 #define __PREPROCESSOR_THREAD_H 3 4 #include <QThread>3 // matt: remove qt dependencies 4 //#include <QThread> 5 5 6 6 namespace GtpVisibilityPreprocessor { … … 8 8 class Preprocessor; 9 9 10 class PreprocessorThread : public QThread 10 /** This class represents a preprocessor thread. 11 */ 12 class PreprocessorThread//: public QThread 11 13 { 12 Q_OBJECT14 //Q_OBJECT 13 15 14 16 Preprocessor *mPreprocessor; 15 17 public: 16 PreprocessorThread(Preprocessor *p, QObject *parent = 0); 18 //PreprocessorThread(Preprocessor *p, QObject *parent = 0); 19 PreprocessorThread(Preprocessor *p); 17 20 ~PreprocessorThread(); 21 22 void operator()(); 18 23 19 24 void Main(); 20 25 21 protected:26 /*protected: 22 27 void run() { 23 28 Main(); 24 } 29 }*/ 25 30 }; 26 31 -
GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp
r1112 r1145 484 484 { 485 485 // compute rendering error 486 486 487 if (renderer && renderer->mPvsStatFrames) { 487 488 // emit EvalPvsStat(); … … 835 836 836 837 if (0 && mPass > 0) { 838 char buf[100]; 837 839 if (mUseImportanceSampling) 838 renderer->mSnapPrefix.sprintf("snap/i-%02d-", mPass); 840 { 841 sprintf(buf, "snap/i-%02d-", mPass); 842 843 renderer->mSnapPrefix = buf; 844 } 839 845 else 840 renderer->mSnapPrefix.sprintf("snap/r-%02d-", mPass); 846 { 847 sprintf(buf, "snap/r-%02d-", mPass); 848 849 renderer->mSnapPrefix = buf; 850 } 851 841 852 renderer->mSnapErrorFrames = true; 842 853 } -
GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp
r1112 r1145 2086 2086 // exporter->ExportKdTree(*mKdTree); 2087 2087 exporter->SetWireframe(); 2088 exporter->ExportScene(preprocessor->mSceneGraph->mRoot);2088 // exporter->ExportScene(preprocessor->mSceneGraph->mRoot); 2089 2089 exporter->SetWireframe(); 2090 2090 exporter->ExportBox(box); -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
r1142 r1145 250 250 bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; } 251 251 252 int IncMail() { return ++ mMailbox - sMailId; }252 int IncMail() { return ++ mMailbox - sMailId; } 253 253 254 254 -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
r1144 r1145 53 53 mMinPvsSize(0), // one means only empty view cells are invalid 54 54 mMaxPvsRatio(1.0), 55 mViewCellPvsIsUpdated(false) 55 mViewCellPvsIsUpdated(false), 56 mPreprocessor(NULL) 56 57 { 57 58 mViewSpaceBox.Initialize(); … … 343 344 SimpleRayContainer simpleRays; 344 345 345 preprocessor->GenerateRays(samplesPerPass,346 mPreprocessor->GenerateRays(samplesPerPass, 346 347 sampleType, 347 348 simpleRays); 348 349 349 350 // shoot simple ray and add it to importance samples 350 preprocessor->CastRays(simpleRays, passSamples);351 mPreprocessor->CastRays(simpleRays, passSamples); 351 352 352 353 return (int)passSamples.size(); … … 390 391 int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays) 391 392 { 393 mPreprocessor = preprocessor; 394 392 395 int numSamples = 0; 393 396 … … 544 547 if (mEvaluateViewCells) 545 548 { 546 EvalViewCellPartition( preprocessor);549 EvalViewCellPartition(); 547 550 } 548 551 … … 597 600 int histoMaxVal; 598 601 Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal); 599 maxRenderCost = max( histoMaxVal, maxRenderCost);602 maxRenderCost = max((float)histoMaxVal, maxRenderCost); 600 603 601 604 … … 872 875 873 876 874 void ViewCellsManager::EvalViewCellPartition( Preprocessor *preprocessor)877 void ViewCellsManager::EvalViewCellPartition() 875 878 { 876 879 int samplesPerPass; … … 895 898 cout << "reseting pvs ... "; 896 899 897 898 bool startFromZero = true; 900 const bool startFromZero = true; 899 901 900 902 // reset pvs and start over from zero … … 903 905 mViewCellsTree->ResetPvs(); 904 906 } 905 else // statistics without addidtional samples 906 { 907 else // start from current sampless 908 { 909 // statistics before casting more samples 907 910 cout << "compute new statistics ... "; 908 911 sprintf(s, "-%09d-eval.log", castSamples); … … 1015 1018 } 1016 1019 } 1017 1018 // find empty view cells bug1019 if (TEST_EMPTY_VIEW_CELLS)1020 {1021 TestEmptyViewCells(preprocessor->mObjects);1022 }1023 1020 } 1024 1021 … … 1030 1027 1031 1028 1032 // Returns index of the best view cells of the neighborhood1029 /// Returns index of the best view cells of the neighborhood 1033 1030 int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood) 1034 1031 { … … 1070 1067 1071 1068 case PER_TRIANGLE: 1072 { cout << "pertriangle" << endl;1069 {//cout << "pertriangle" << endl; 1073 1070 // HACK 1074 1071 MeshInstance *mi = dynamic_cast<MeshInstance *>(obj); … … 1077 1074 if (mi->GetMesh()) 1078 1075 { 1079 return mi->GetMesh()->mFaces.size();1076 return (float)mi->GetMesh()->mFaces.size(); 1080 1077 } 1081 1078 } … … 1292 1289 sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs); 1293 1290 1294 int start = mViewCells.size() *minValid;1295 int end = mViewCells.size() *maxValid;1291 int start = mViewCells.size() * minValid; 1292 int end = mViewCells.size() * maxValid; 1296 1293 1297 1294 for (int i = 0; i < mViewCells.size(); ++ i) … … 1957 1954 float ViewCellsManager::GetRendercost(ViewCell *viewCell) const 1958 1955 { 1959 return mViewCellsTree->GetPvsSize(viewCell);1956 return (float)mViewCellsTree->GetPvsSize(viewCell); 1960 1957 } 1961 1958 … … 2449 2446 2450 2447 2451 /******************************************************************* ***/2452 /* BspViewCellsManager implementation*/2453 /******************************************************************* ***/2448 /*******************************************************************/ 2449 /* BspViewCellsManager implementation */ 2450 /*******************************************************************/ 2454 2451 2455 2452 … … 4578 4575 vector<RenderCostSample> samples; 4579 4576 4580 if (! preprocessor->GetRenderer())4577 if (!mPreprocessor->GetRenderer()) 4581 4578 return; 4582 4579 4583 //start the frompoint queries4580 //start the view point queries 4584 4581 long startTime = GetTime(); 4585 4582 cout << "starting sampling of render cost ... "; 4586 4583 4587 preprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);4584 mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true); 4588 4585 4589 4586 cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl; … … 4916 4913 // print subdivision statistics 4917 4914 Debug << mVspTree->GetStatistics() << endl; 4915 Debug << mOspTree->GetStatistics() << endl; 4918 4916 4919 4917 // print view cell statistics … … 5333 5331 5334 5332 const int savedColorCode = mColorCode; 5333 mColorCode = 0; 5335 5334 const int maxPvs = 200;//mOspTree.GetStatistics().maxPvs; 5336 5335 5337 5336 exporter->ExportOspTree(*mOspTree, mColorCode == 0 ? 0 : maxPvs); 5337 5338 mColorCode = savedColorCode; 5338 5339 5339 5340 delete exporter; -
GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
r1142 r1145 41 41 42 42 43 /** Probably Visible Set */ 43 /** Probably Visible Set 44 */ 44 45 class PrVs 45 46 { … … 379 380 void SetViewCellsActive(); 380 381 381 /** Evaluates worthof current view cell hierarchy.382 */ 383 void EvalViewCellPartition( Preprocessor *preprocessor);382 /** Evaluates render cost statistics of current view cell hierarchy. 383 */ 384 void EvalViewCellPartition(); 384 385 385 386 /** Sets maximal size of a view cell filter. … … 479 480 480 481 protected: 482 481 483 /** Exports bounding boxes as xml stream 482 484 */ … … 570 572 //////////////////////////////////////////////// 571 573 572 /// if bounding boxes should also be exported 574 Preprocessor *mPreprocessor; 575 /// if bounding boxes should be exported together with the view cells 573 576 bool mExportBboxesForPvs; 574 577 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
r1141 r1145 640 640 // compute first split candidate 641 641 VspBspSplitCandidate splitCandidate; 642 EvalSplitCandidate(tData, splitCandidate); 642 splitCandidate.mParentData = tData; 643 644 EvalSplitCandidate(splitCandidate); 643 645 644 646 tQueue.push(splitCandidate); … … 814 816 // evaluate subdivision stats 815 817 if (1) 816 { 817 const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 818 const float cBack = (float)tBackData.mPvs * tBackData.mProbability; 819 const float cData = (float)tData.mPvs * tData.mProbability;; 820 821 const float costDecr = (cFront + cBack - cData) / mBox.GetVolume(); 822 823 mTotalCost += costDecr; 824 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 825 826 AddSubdivisionStats(mBspStats.Leaves(), 827 -costDecr, 828 0, 829 mTotalCost, 830 (float)mTotalPvsSize / (float)mBspStats.Leaves()); 831 } 818 EvalSubdivisionStats(tData, tFrontData, tBackData); 819 832 820 833 821 // push the children on the stack … … 964 952 //-- push the new split candidates on the stack 965 953 VspBspSplitCandidate frontCandidate; 954 frontCandidate.mParentData = tFrontData; 955 966 956 VspBspSplitCandidate backCandidate; 967 968 EvalSplitCandidate(tFrontData, frontCandidate); 969 EvalSplitCandidate(tBackData, backCandidate); 957 backCandidate.mParentData = tBackData; 958 959 EvalSplitCandidate(frontCandidate); 960 EvalSplitCandidate(backCandidate); 970 961 971 962 tQueue.push(frontCandidate); … … 1047 1038 1048 1039 1040 /* 1049 1041 void VspBspTree::EvalSplitCandidate(VspBspTraversalData &tData, 1050 1042 VspBspSplitCandidate &splitData) … … 1067 1059 splitData.mParentData = tData; 1068 1060 splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1; 1061 } 1062 */ 1063 1064 void VspBspTree::EvalSplitCandidate(VspBspSplitCandidate &splitCandidate) 1065 { 1066 VspBspTraversalData frontData; 1067 VspBspTraversalData backData; 1068 1069 BspLeaf *leaf = dynamic_cast<BspLeaf *>(splitCandidate.mParentData.mNode); 1070 1071 // compute locally best split plane 1072 bool success = SelectPlane(splitCandidate.mSplitPlane, leaf, splitCandidate.mParentData, 1073 frontData, backData, splitCandidate.mSplitAxis); 1074 1075 float oldRenderCost; 1076 1077 // compute global decrease in render cost 1078 const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 1079 splitCandidate.mParentData, 1080 oldRenderCost); 1081 1082 splitCandidate.mRenderCostDecr = renderCostDecr; 1083 1084 // TODO: geometry could be reused 1085 delete frontData.mGeometry; 1086 delete backData.mGeometry; 1087 1088 // set priority for queue 1089 #if 0 1090 const float priority = (float)-data.mDepth; 1091 #else 1092 1093 // take render cost of node into account 1094 // otherwise danger of being stuck in a local minimum!! 1095 const float factor = mRenderCostDecreaseWeight; 1096 const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost; 1097 #endif 1098 1099 splitCandidate.mPriority = priority; 1100 1101 // max cost threshold violated? 1102 splitCandidate.mMaxCostMisses = 1103 success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1; 1104 } 1105 1106 1107 void VspBspTree::EvalSubdivisionStats(const VspBspTraversalData &tData, 1108 const VspBspTraversalData &tFrontData, 1109 const VspBspTraversalData &tBackData) 1110 { 1111 const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 1112 const float cBack = (float)tBackData.mPvs * tBackData.mProbability; 1113 const float cData = (float)tData.mPvs * tData.mProbability; 1114 1115 const float costDecr = 1116 (cFront + cBack - cData) / mBox.GetVolume(); 1117 1118 mTotalCost += costDecr; 1119 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 1120 1121 AddSubdivisionStats(mBspStats.Leaves(), 1122 -costDecr, 1123 0, 1124 mTotalCost, 1125 (float)mTotalPvsSize / (float)mBspStats.Leaves()); 1069 1126 } 1070 1127 … … 1896 1953 1897 1954 float VspBspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane, 1898 const VspBspTraversalData &data) const 1955 const VspBspTraversalData &data, 1956 float &normalizedOldRenderCost) const 1899 1957 { 1900 1958 float pvsFront = 0; … … 1972 2030 const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack; 1973 2031 1974 //Debug << "decrease: " << oldRenderCost - newRenderCost << endl;1975 2032 const float renderCostDecrease = (oldRenderCost - newRenderCost) / mBox.GetVolume(); 1976 2033 1977 const float weight = mRenderCostDecreaseWeight;1978 2034 // take render cost of node into account to avoid being stuck in a local minimum 1979 const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume(); 1980 1981 //Debug << "rendercostdecr: " << weight * renderCostDecrease << " old render cost: " << (1.0f - weight) * normalizedOldRenderCost << endl; 1982 return weight * renderCostDecrease + (1.0f - weight) * normalizedOldRenderCost; 2035 normalizedOldRenderCost = oldRenderCost / mBox.GetVolume(); 2036 2037 return renderCostDecrease; 1983 2038 } 1984 2039 -
GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
r1133 r1145 170 170 float mPriority; 171 171 172 VspBspSplitCandidate(): mPriority(0) 172 float mRenderCostDecr; 173 174 VspBspSplitCandidate(): mPriority(0), mRenderCostDecr(0) 173 175 {}; 174 176 175 177 VspBspSplitCandidate(const Plane3 &plane, const VspBspTraversalData &tData): 176 mSplitPlane(plane), mParentData(tData), mPriority(0) 178 mSplitPlane(plane), mParentData(tData), mPriority(0), mRenderCostDecr(0) 177 179 {} 178 180 … … 404 406 /** Evaluates candidate for splitting. 405 407 */ 406 void EvalSplitCandidate(VspBsp TraversalData &tData, VspBspSplitCandidate &splitData);408 void EvalSplitCandidate(VspBspSplitCandidate &splitData); 407 409 408 410 /** Computes priority of the traversal data and stores it in tData. … … 413 415 */ 414 416 float EvalRenderCostDecrease(const Plane3 &candidatePlane, 415 const VspBspTraversalData &data) const; 417 const VspBspTraversalData &data, 418 float &normalizedOldRenderCost) const; 416 419 417 420 /** Constructs tree using the split priority queue. … … 705 708 //float GetMemUsage(const VspBspTraversalQueue &tstack) const; 706 709 710 711 void EvalSubdivisionStats(const VspBspTraversalData &tData, 712 const VspBspTraversalData &tFrontData, 713 const VspBspTraversalData &tBackData 714 ); 707 715 708 716 /** Adds stats to subdivision log file. -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
r1144 r1145 103 103 104 104 105 void OspTreeStatistics::Print(ostream &app) const 106 { 107 app << "=========== OspTree statistics ===============\n"; 108 109 app << setprecision(4); 110 111 app << "#N_CTIME ( Construction time [s] )\n" << Time() << " \n"; 112 113 app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 114 115 app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n"; 116 117 app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 118 119 app << "#AXIS_ALIGNED_SPLITS (number of axis aligned splits)\n" << splits[0] + splits[1] + splits[2] << endl; 120 121 app << "#N_SPLITS ( Number of splits in axes x y z)\n"; 122 123 for (int i = 0; i < 3; ++ i) 124 app << splits[i] << " "; 125 app << endl; 126 127 app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n" 128 << maxDepthNodes * 100 / (double)Leaves() << endl; 129 130 app << "#N_PMINPVSLEAVES ( Percentage of leaves with mininimal PVS )\n" 131 << minPvsNodes * 100 / (double)Leaves() << endl; 132 133 //app << "#N_PMINRAYSLEAVES ( Percentage of leaves with minimal number of rays)\n" 134 // << minRaysNodes * 100 / (double)Leaves() << endl; 135 136 app << "#N_MAXCOSTNODES ( Percentage of leaves with terminated because of max cost ratio )\n" 137 << maxCostNodes * 100 / (double)Leaves() << endl; 138 139 app << "#N_PMINPROBABILITYLEAVES ( Percentage of leaves with mininum probability )\n" 140 << minProbabilityNodes * 100 / (double)Leaves() << endl; 141 142 // app << "#N_PMAXRAYCONTRIBLEAVES ( Percentage of leaves with maximal ray contribution )\n" 143 // << maxRayContribNodes * 100 / (double)Leaves() << endl; 144 145 app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl; 146 147 app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl; 148 149 app << "#AVGDEPTH ( average depth )\n" << AvgDepth() << endl; 150 151 app << "#N_INVALIDLEAVES (number of invalid leaves )\n" << invalidLeaves << endl; 152 153 // app << "#N_RAYS (number of rays / leaf)\n" << AvgRays() << endl; 154 //app << "#N_PVS: " << pvs << endl; 155 156 app << "========== END OF VspTree statistics ==========\n"; 157 } 158 159 105 160 /******************************************************************/ 106 161 /* class VspNode implementation */ … … 471 526 void VspTree::AddSubdivisionStats(const int viewCells, 472 527 const float renderCostDecr, 473 const float splitCandidateCost,474 528 const float totalRenderCost, 475 529 const float avgRenderCost) … … 478 532 << "#ViewCells\n" << viewCells << endl 479 533 << "#RenderCostDecrease\n" << renderCostDecr << endl 480 << "#SplitCandidateCost\n" << splitCandidateCost << endl481 534 << "#TotalRenderCost\n" << totalRenderCost << endl 482 535 << "#AvgRenderCost\n" << avgRenderCost << endl; … … 584 637 585 638 639 void VspTree::EvalSubdivisionStats(const VspTraversalData &tData, 640 const VspTraversalData &tFrontData, 641 const VspTraversalData &tBackData 642 ) 643 { 644 const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 645 const float cBack = (float)tBackData.mPvs * tBackData.mProbability; 646 const float cData = (float)tData.mPvs * tData.mProbability; 647 648 const float costDecr = 649 (cFront + cBack - cData) / mBoundingBox.GetVolume(); 650 651 mTotalCost += costDecr; 652 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 653 654 AddSubdivisionStats(mVspStats.Leaves(), 655 -costDecr, 656 mTotalCost, 657 (float)mTotalPvsSize / (float)mVspStats.Leaves()); 658 } 659 660 586 661 VspNode *VspTree::Subdivide(SplitQueue &tQueue, 587 VspSplitCandidate &splitCandidate,662 SplitCandidate *splitCandidate, 588 663 const bool globalCriteriaMet) 589 664 { 590 VspTraversalData &tData = splitCandidate.mParentData; 665 // doto remove dynamic cast 666 VspSplitCandidate *sc = dynamic_cast<VspSplitCandidate *>(splitCandidate); 667 VspTraversalData &tData = sc->mParentData; 591 668 592 669 VspNode *newNode = tData.mNode; … … 600 677 601 678 // create new interior node and two leaf node 602 const AxisAlignedPlane splitPlane = s plitCandidate.mSplitPlane;679 const AxisAlignedPlane splitPlane = sc->mSplitPlane; 603 680 newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData); 604 681 605 const int maxCostMisses = s plitCandidate.mMaxCostMisses;682 const int maxCostMisses = sc->mMaxCostMisses; 606 683 607 684 … … 611 688 612 689 613 if (1) 614 { 615 //-- subdivision statistics 616 617 const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 618 const float cBack = (float)tBackData.mPvs * tBackData.mProbability; 619 const float cData = (float)tData.mPvs * tData.mProbability; 620 621 const float costDecr = 622 (cFront + cBack - cData) / mBoundingBox.GetVolume(); 623 624 mTotalCost += costDecr; 625 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 626 627 AddSubdivisionStats(mVspStats.Leaves(), 628 -costDecr, 629 splitCandidate.GetPriority(), 630 mTotalCost, 631 (float)mTotalPvsSize / (float)mVspStats.Leaves()); 632 } 633 634 690 if (1) //-- subdivision statistics 691 EvalSubdivisionStats(tData, tFrontData, tBackData); 692 635 693 //-- evaluate new split candidates for global greedy cost heuristics 694 636 695 VspSplitCandidate *frontCandidate = new VspSplitCandidate(tFrontData); 637 696 VspSplitCandidate *backCandidate = new VspSplitCandidate(tBackData); … … 645 704 // delete old view cell 646 705 delete tData.mNode->mViewCell; 706 647 707 // delete old leaf node 648 708 DEL_PTR(tData.mNode); … … 702 762 SelectSplitPlane(splitCandidate.mParentData, splitCandidate.mSplitPlane, frontProb, backProb); 703 763 764 float oldRenderCost; 765 704 766 // compute global decrease in render cost 705 const float priority = EvalRenderCostDecrease(splitCandidate.mSplitPlane, splitCandidate.mParentData); 767 const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 768 splitCandidate.mParentData, 769 oldRenderCost); 770 771 splitCandidate.SetRenderCostDecrease(renderCostDecr); 772 773 #if 0 774 const float priority = (float)-data.mDepth; 775 #else 776 777 // take render cost of node into account 778 // otherwise danger of being stuck in a local minimum!! 779 const float factor = mRenderCostDecreaseWeight; 780 const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost; 781 #endif 782 706 783 splitCandidate.SetPriority(priority); 707 splitCandidate.mMaxCostMisses = success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1; 784 785 // max cost threshold violated? 786 splitCandidate.mMaxCostMisses = 787 success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1; 708 788 //Debug << "p: " << tData.mNode << " depth: " << tData.mDepth << endl; 709 789 } … … 1404 1484 1405 1485 //if (axis != 1) 1406 Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox) 1407 <<"\t pb=(" << pvsBack << ")\t pf=(" << pvsFront << ")" << endl; 1486 //Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox) 1487 // <<"\t pb=(" << pvsBack << ")\t pf=(" << pvsFront << ")" << endl; 1488 1489 const float volRatio = tData.mBoundingBox.GetVolume() / (sizeBox * mBoundingBox.GetVolume()); 1490 1491 Debug << "\n§§§§ eval local cost §§§§" << endl 1492 << "back pvs: " << penaltyBack << " front pvs: " << penaltyFront << " total pvs: " << penaltyOld << endl 1493 << "back p: " << pBack * volRatio << " front p " << pFront * volRatio << " p: " << pOverall * volRatio << endl 1494 << "old rc: " << oldRenderCost * volRatio << " new rc: " << newRenderCost * volRatio << endl 1495 << "render cost decrease: " << oldRenderCost * volRatio - newRenderCost * volRatio << endl; 1408 1496 1409 1497 return ratio; … … 1497 1585 1498 1586 float VspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 1499 const VspTraversalData &data) const 1500 { 1501 #if 0 1502 return (float)-data.mDepth; 1503 #endif 1587 const VspTraversalData &data, 1588 float &normalizedOldRenderCost) const 1589 { 1504 1590 float pvsFront = 0; 1505 1591 float pvsBack = 0; … … 1511 1597 float pBack = 0; 1512 1598 1599 const float viewSpaceVol = mBoundingBox.GetVolume(); 1513 1600 1514 1601 // create unique ids for pvs heuristics 1515 Intersectable::NewMail( );1602 Intersectable::NewMail(3); 1516 1603 1517 1604 RayInfoContainer::const_iterator rit, rit_end = data.mRays->end(); … … 1555 1642 const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack; 1556 1643 1644 normalizedOldRenderCost = oldRenderCost / viewSpaceVol; 1645 1557 1646 //Debug << "decrease: " << oldRenderCost - newRenderCost << endl; 1558 const float renderCostDecrease = (oldRenderCost - newRenderCost) / mBoundingBox.GetVolume(); 1559 1560 // take render cost of node into account 1561 // otherwise danger of being stuck in a local minimum!! 1562 const float factor = mRenderCostDecreaseWeight; 1563 1564 const float normalizedOldRenderCost = oldRenderCost / mBoundingBox.GetVolume(); 1565 return factor * renderCostDecrease + (1.0f - factor) * normalizedOldRenderCost; 1647 const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol; 1648 1649 1650 Debug << "\n==== eval render cost decrease ===" << endl 1651 << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 1652 << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl 1653 << "old rc: " << normalizedOldRenderCost << " new rc: " << newRenderCost / viewSpaceVol << endl 1654 << "render cost decrease: " << renderCostDecrease << endl; 1655 1656 return renderCostDecrease; 1566 1657 } 1567 1658 … … 1579 1670 1580 1671 // create unique ids for pvs heuristics 1581 Intersectable::NewMail( );1672 Intersectable::NewMail(3); 1582 1673 1583 1674 const int pvsSize = data.mPvs; … … 1601 1692 pOverall = data.mProbability; 1602 1693 1603 // we take simplified computation for spatial mid split1694 // we use spatial mid split => simplified computation 1604 1695 pBack = pFront = pOverall * 0.5f; 1605 1696 … … 1625 1716 return; 1626 1717 1627 //const float renderCost = mViewCellsManager-> EvalRenderCost(obj);1718 //const float renderCost = mViewCellsManager->SimpleRay &raynderCost(obj); 1628 1719 const int renderCost = 1; 1629 1720 … … 1634 1725 } 1635 1726 1636 // TODO: does this really belong to no pvs? 1727 // QUESTION matt: is it safe to assume that 1728 // the object belongs to no pvs in this case? 1637 1729 //if (cf == Ray::COINCIDENT) return; 1638 1730 … … 2162 2254 2163 2255 Intersectable::NewMail(); 2164 ViewCell::NewMail();2256 //ViewCell::NewMail(); 2165 2257 2166 2258 Vector3 entp = origin; … … 2225 2317 ViewCell *vc = leaf->GetViewCell(); 2226 2318 2227 if (!vc->Mailed()) 2228 { 2229 vc->Mail(); 2319 // don't have to mail because each view cell belongs to exactly one leaf 2320 //if (!vc->Mailed()) 2321 //{ 2322 // vc->Mail(); 2230 2323 viewcells.push_back(vc); 2231 2324 ++ hits; 2232 }2325 //} 2233 2326 #if 0 2234 2327 leaf->mRays.push_back(RayInfo(new VssRay(origin, termination, NULL, NULL, 0))); … … 2785 2878 //-- debug output 2786 2879 2787 Debug << "******* OSP options ******** " << endl;2880 Debug << "******* OSP tree options ******** " << endl; 2788 2881 2789 2882 Debug << "max depth: " << mTermMaxDepth << endl; … … 2951 3044 2952 3045 KdNode *OspTree::Subdivide(SplitQueue &tQueue, 2953 OspSplitCandidate &splitCandidate,3046 SplitCandidate *splitCandidate, 2954 3047 const bool globalCriteriaMet) 2955 3048 { 2956 OspTraversalData &tData = splitCandidate.mParentData; 3049 OspSplitCandidate *sc = dynamic_cast<OspSplitCandidate *>(splitCandidate); 3050 OspTraversalData &tData = sc->mParentData; 3051 2957 3052 KdNode *newNode = tData.mNode; 2958 3053 … … 2965 3060 2966 3061 // create new interior node and two leaf node 2967 const AxisAlignedPlane splitPlane = s plitCandidate.mSplitPlane;3062 const AxisAlignedPlane splitPlane = sc->mSplitPlane; 2968 3063 2969 3064 newNode = SubdivideNode(splitPlane, … … 2972 3067 tBackData); 2973 3068 2974 const int maxCostMisses = s plitCandidate.mMaxCostMisses;3069 const int maxCostMisses = sc->mMaxCostMisses; 2975 3070 2976 3071 // how often was max cost ratio missed in this branch? … … 3015 3110 SelectSplitPlane(splitCandidate.mParentData, splitCandidate.mSplitPlane, frontProb, backProb); 3016 3111 3017 const float priority = EvalRenderCostDecrease(splitCandidate.mSplitPlane, splitCandidate.mParentData); 3112 float oldRenderCost; 3113 3114 // compute global decrease in render cost 3115 const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 3116 splitCandidate.mParentData, 3117 oldRenderCost); 3118 3119 splitCandidate.SetRenderCostDecrease(renderCostDecr); 3120 3121 #if 0 3122 const float priority = (float)-data.mDepth; 3123 #else 3124 // take render cost of node into account 3125 // otherwise danger of being stuck in a local minimum!! 3126 const float factor = mRenderCostDecreaseWeight; 3127 const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost; 3128 3129 #endif 3130 3018 3131 // compute global decrease in render cost 3019 3132 splitCandidate.SetPriority(priority); … … 3112 3225 SortSplitCandidates(tData, axis, minBand, maxBand); 3113 3226 3114 float totalVol = PrepareHeuristics(tData); 3227 int numViewCells; 3228 3229 float totalVol = PrepareHeuristics(tData, numViewCells); 3115 3230 float voll = 0; 3116 3231 float volr = totalVol; 3232 3233 int vcl = 0; 3234 int vcr = numViewCells; 3117 3235 3118 3236 const int totalPvs = tData.mNode->mObjects.size(); … … 3121 3239 int pvsr = totalPvs; 3122 3240 3123 // if no good split can be found, take mid split 3241 float sum = (float)totalVol * sizeBox; 3242 3243 ///////////////////////////////// 3244 3245 // note: initialised to take mid split 3246 // if no good split can be found, 3124 3247 position = minBox + 0.5f * sizeBox; 3125 3248 … … 3127 3250 float ratio = 99999999.0f; 3128 3251 bool splitPlaneFound = false; 3129 3130 float minSum = 1e20f;3131 3252 3132 3253 float volBack = voll; 3133 3254 float volFront = volr; 3134 3255 3135 int pvsBack = 0; 3136 int pvsFront = 0; 3137 3138 3139 float sum = (float)totalVol * sizeBox; 3256 int pvsBack = pvsl; 3257 int pvsFront = pvsr; 3258 3259 float minSum = 1e20f; 3260 3261 ///////////////////////////// 3140 3262 3141 3263 Intersectable::NewMail(); … … 3150 3272 Intersectable *object = (*ci).mObject; 3151 3273 3152 EvalHeuristicsContribution(*ci, voll, volr, pvsl, pvsr); 3153 3154 cout << "incr: " << ci->mObject->mViewCellPvs.GetSize() << " obj id " 3155 << ci->mObject->GetId() << endl; 3274 EvalHeuristicsContribution(tData.mNode, 3275 *ci, 3276 voll, volr, 3277 pvsl, pvsr, 3278 vcl, vcr); 3156 3279 3157 3280 // Note: sufficient to compare size of bounding boxes of front and back side? 3281 3158 3282 if (((*ci).mPos >= minBand) && ((*ci).mPos <= maxBand)) 3159 3283 { 3160 //sum = costl * ((*ci).value - minBox) + costr * (maxBox - (*ci).value); 3161 sum = voll * pvsBack + volr * pvsFront; 3162 3163 cout << "pos: " << (*ci).mPos 3164 << "\t (pvsl: " << pvsBack << ", pvsr: " << pvsFront << ")" 3284 sum = voll * pvsl + volr * pvsr; 3285 3286 // note matt: can happen that volr is less than zero: bug or numerical error? 3287 //if (volr < 0) Debug << "warning!! " << totalVol << " " << volRightDecr << " " << volRightDecr - totalVol << endl; 3288 3289 /*Debug << "pos: " << (*ci).mPos 3290 << "\t (pvsl: " << pvsl << ", pvsr: " << pvsr << ")" 3165 3291 << "\t (voll: " << voll << ", volr: " << volr << ")" 3166 << "\t sum: " << sum << endl; 3292 << "\t (vcl: " << vcl << ", vcr: " << vcr << ", nvc: " << numViewCells << ")" 3293 << "\t sum: " << sum << endl;*/ 3167 3294 3168 3295 if (sum < minSum) … … 3193 3320 const float pFront = volFront; 3194 3321 3195 const float penaltyOld = (float)totalPvs; //EvalPvsPenalty(pvsSize, lowerPvsLimit, upperPvsLimit);3196 const float penaltyFront = (float)pvsFront; //EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);3197 const float penaltyBack = (float)pvsBack; //EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);3322 const float penaltyOld = (float)totalPvs; 3323 const float penaltyFront = (float)pvsFront; 3324 const float penaltyBack = (float)pvsBack; 3198 3325 3199 3326 const float oldRenderCost = penaltyOld * pOverall + Limits::Small; … … 3206 3333 } 3207 3334 3208 //if (axis != 1) 3209 Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" 3210 << position << " t=" << (position - minBox) / (maxBox - minBox) 3211 << "\t pb=(" << volBack << ")\t pf=(" << volFront << ")" << endl; 3335 //Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" 3336 // << position << " t=" << (position - minBox) / (maxBox - minBox) 3337 // << "\t pb=(" << volBack << ")\t pf=(" << volFront << ")" << endl; 3338 3339 const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume(); 3340 3341 Debug << "\n§§§§ eval local cost §§§§" << endl 3342 << "back pvs: " << pvsBack << " front pvs: " << pvsFront << " total pvs: " << totalPvs << endl 3343 << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl 3344 << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl 3345 << "render cost decrease: " << oldRenderCost / viewSpaceVol - newRenderCost / viewSpaceVol << endl; 3212 3346 3213 3347 return ratio; … … 3255 3389 3256 3390 // if hitpoint with object is inside this node 3257 if ( GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)3391 if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) 3258 3392 { 3259 3393 pos = ray->mOrigin[axis]; … … 3267 3401 } 3268 3402 3269 if ( GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)3403 if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)) 3270 3404 { 3271 3405 pos = ray->mTermination[axis]; … … 3274 3408 SortableEntry(SortableEntry::BOX_INTERSECT, 3275 3409 pos, 3276 ray->m OriginObject,3410 ray->mTerminationObject, 3277 3411 ray) 3278 3412 ); … … 3319 3453 3320 3454 3321 float OspTree::PrepareHeuristics(const VssRay &ray )3455 float OspTree::PrepareHeuristics(const VssRay &ray, int &numViewCells) 3322 3456 { 3323 3457 float vol = 0; 3458 numViewCells = 0; 3324 3459 3325 3460 ViewCellContainer viewCells; 3326 3461 3327 3462 mVspTree->GetViewCells(ray, viewCells); 3328 3463 3329 3464 ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 3330 3465 … … 3335 3470 if (!vc->Mailed()) 3336 3471 { 3472 //Debug << "single vol: "<< vc->GetVolume() << endl; 3337 3473 vc->Mail(); 3338 3474 vc->mCounter = 0; 3339 3475 vol += vc->GetVolume(); 3340 } 3476 ++ numViewCells; 3477 } 3478 3479 // view cell volume already added => just increase counter 3480 ++ vc->mCounter; 3341 3481 } 3342 3482 … … 3345 3485 3346 3486 3347 float OspTree::PrepareHeuristics(const OspTraversalData &tData )3487 float OspTree::PrepareHeuristics(const OspTraversalData &tData, int &numViewCells) 3348 3488 { 3489 float vol = 0; 3490 3349 3491 Intersectable::NewMail(); 3350 3492 ViewCell::NewMail(); 3351 3352 float vol = 0; 3493 numViewCells = 0; 3353 3494 3354 3495 KdLeaf *leaf = tData.mNode; … … 3359 3500 { 3360 3501 VssRay *ray = (*rit).mRay; 3502 3503 int newViewCells; 3361 3504 3362 3505 // if hitpoint with one of the objects is inside this node, we 3363 3506 // evaluate the volume of the view cells seen by this ray 3364 if ((GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf) || 3365 (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)) 3366 { 3367 vol += PrepareHeuristics(tData); 3368 } 3369 } 3370 3507 if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) 3508 { 3509 vol += PrepareHeuristics(*ray, newViewCells); 3510 numViewCells += newViewCells; 3511 } 3512 3513 // count double if both hit points are within the kd node 3514 if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)) 3515 { 3516 vol += PrepareHeuristics(*ray, newViewCells); 3517 numViewCells += newViewCells; 3518 } 3519 } 3520 3521 //Debug << "vol: " << vol << endl; 3371 3522 return vol; 3372 3523 } 3373 3524 3374 3525 3375 void OspTree::EvalHeuristicsContribution(const SortableEntry &ci, 3526 void OspTree::EvalHeuristicsContribution(KdLeaf *leaf, 3527 const SortableEntry &ci, 3376 3528 float &volLeft, 3377 3529 float &volRight, 3378 3530 int &pvsLeft, 3379 int &pvsRight) 3531 int &pvsRight, 3532 int &viewCellsLeft, 3533 int &viewCellsRight) 3380 3534 { 3381 3535 Intersectable *obj = ci.mObject; 3382 3536 VssRay *ray = ci.mRay; 3383 3537 3384 3538 switch (ci.mType) 3385 3539 { … … 3395 3549 // compute volume contribution from view cells 3396 3550 case SortableEntry::BOX_INTERSECT: 3397 EvalVolumeContribution(*ray, volRight, volLeft); 3551 if ((ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) || 3552 (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))) 3553 { 3554 EvalVolumeContribution(*ray, volLeft, volRight, viewCellsLeft, viewCellsRight); 3555 } 3398 3556 break; 3399 3557 default: … … 3406 3564 3407 3565 3408 void OspTree::EvalVolumeContribution(const VssRay &ray, float &volLeft, float &volRight) 3566 void OspTree::EvalVolumeContribution(const VssRay &ray, 3567 float &volLeft, 3568 float &volRight, 3569 int &viewCellsLeft, 3570 int &viewCellsRight) 3409 3571 { 3410 3572 ViewCellContainer viewCells; … … 3413 3575 3414 3576 ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 3415 3577 3416 3578 for (vit = viewCells.begin(); vit != vit_end; ++ vit) 3417 3579 { 3418 // view cells comesto left child node3580 // add view cells volume to left child node 3419 3581 ViewCell *viewCell = *vit; 3420 3582 … … 3422 3584 { 3423 3585 viewCell->Mail(); 3586 3424 3587 volLeft += viewCell->GetVolume(); 3588 3589 ++ viewCellsLeft; 3425 3590 } 3426 3591 3427 3592 // remove from right child node 3428 3429 3593 if (-- viewCell->mCounter == 0) 3430 3594 { 3431 3595 volRight -= viewCell->GetVolume(); 3596 3597 -- viewCellsRight; 3432 3598 } 3433 3599 } … … 3520 3686 pBack = nProbBack[bestAxis]; 3521 3687 3522 //Debug << "val: " << nCostRatio[bestAxis] << " axis: " << bestAxis << endl;3688 Debug << "val: " << nCostRatio[bestAxis] << " axis: " << bestAxis << endl; 3523 3689 return nCostRatio[bestAxis]; 3524 3690 } 3525 3691 3526 3692 3693 bool OspTree::EndPointInsideNode(KdLeaf *leaf, 3694 VssRay &ray, 3695 bool isTermination) const 3696 { 3697 // test if the leaf where the hitpoint is located is the current leaf 3698 if (isTermination) 3699 { 3700 return ray.mTerminationObject && (GetLeaf(ray.mTermination, ray.mOriginNode) == leaf); 3701 } 3702 else 3703 { 3704 return ray.mOriginObject && (GetLeaf(ray.mOrigin, ray.mOriginNode) == leaf); 3705 } 3706 } 3707 3708 3709 #if TODO 3710 void OspTree::EvalSubdivisionStats(const VspTraversalData &tData, 3711 const VspTraversalData &tFrontData, 3712 const VspTraversalData &tBackData 3713 ) 3714 { 3715 const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability; 3716 const float cBack = (float)tBackData.mPvs * tBackData.mProbability; 3717 const float cData = (float)tData.mPvs * tData.mProbability; 3718 3719 const float costDecr = 3720 (cFront + cBack - cData) / mBoundingBox.GetVolume(); 3721 3722 mTotalCost += costDecr; 3723 mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs; 3724 3725 AddSubdivisionStats(mVspStats.Leaves(), 3726 -costDecr, 3727 sc->GetPriority(), 3728 mTotalCost, 3729 (float)mTotalPvsSize / (float)mVspStats.Leaves()); 3730 } 3731 #endif 3732 3733 3734 int OspTree::ClassifyRay(VssRay *ray, 3735 KdLeaf *leaf, 3736 const AxisAlignedPlane &plane) const 3737 { 3738 const bool originInside = EndPointInsideNode(leaf, *ray, false); 3739 const bool terminationInside = EndPointInsideNode(leaf, *ray, true); 3740 3741 const bool originGt = 3742 ray->mOrigin[plane.mAxis] > plane.mPosition; 3743 3744 const bool terminationGt = 3745 ray->mTermination[plane.mAxis] > plane.mPosition; 3746 3747 // add view cell volume to front volume 3748 const bool addToFront = ((originInside && originGt) || (terminationInside && terminationGt)); 3749 3750 // add view cell volume to back volume 3751 const bool addToBack = ((originInside && !originGt) || (terminationInside && !terminationGt)); 3752 3753 // classify ray with respect to the child nodes the view cells contribute 3754 if (addToFront && addToBack) 3755 return 0; 3756 else if (addToBack) 3757 return -1; 3758 else if (addToFront) 3759 return 1; 3760 3761 return -2; 3762 } 3763 3764 3527 3765 float OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 3528 const OspTraversalData &tData) const 3529 { 3530 #if 0 3531 return (float)-tData.mDepth; 3532 #endif 3533 3766 const OspTraversalData &tData, 3767 float &normalizedOldRenderCost) const 3768 { 3534 3769 float pvsFront = 0; 3535 3770 float pvsBack = 0; … … 3541 3776 float pBack = 0; 3542 3777 3543 Intersectable::NewMail(); 3778 const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume(); 3779 3780 //Intersectable::NewMail(); 3544 3781 KdLeaf::NewMail(); 3545 3782 ViewCell::NewMail(); … … 3549 3786 3550 3787 // evaluate reverse pvs and view cell volume on left and right cell 3788 // note: should I take all leaf objects or rather the objects hit by rays? 3551 3789 for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit) 3552 3790 { … … 3556 3794 ++ totalPvs; 3557 3795 3558 cout << "totalpvs " << totalPvs << endl; 3559 3796 //cout << "totalpvs " << totalPvs << endl; 3797 3798 // test if box falls in left / right child node 3560 3799 if (box.Max(candidatePlane.mAxis) > candidatePlane.mPosition) 3561 3800 { … … 3569 3808 3570 3809 3571 ViewCell::NewMail(); 3810 // sum up volume seen from the objects of left and right children 3811 // => the volume is the weight for the render cost equation 3812 ViewCell::NewMail(3); 3572 3813 3573 3814 RayInfoContainer::const_iterator rit, rit_end = tData.mRays->end(); … … 3577 3818 VssRay *ray = (*rit).mRay; 3578 3819 3579 // if hitpoint with one of the objects is inside this node 3580 if (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf) 3581 { 3820 // test if intersection point with one of the objects is inside this node 3821 const bool originInside = EndPointInsideNode(leaf, *ray, false); 3822 const bool terminationInside = EndPointInsideNode(leaf, *ray, true); 3823 3824 if (originInside || terminationInside) 3825 { 3826 // add volume to volumes of left and / or right children 3827 // if one of the ray end points is inside 3828 const int classification = ClassifyRay(ray, leaf, candidatePlane); 3829 3582 3830 ViewCellContainer viewCells; 3583 3831 mVspTree->GetViewCells(*ray, viewCells); … … 3585 3833 ViewCellContainer::const_iterator vit, vit_end = viewCells.end(); 3586 3834 3587 // add view cells volume to front3835 // evaluate view cells volume contribution 3588 3836 for (vit = viewCells.begin(); vit != vit_end; ++ vit) 3589 3837 { 3590 ViewCell *vc = *vit; 3591 3592 if (!vc->Mailed()) 3593 { 3594 vc->Mail(); 3595 3596 const float vol = vc->GetVolume(); 3597 pOverall += vol; 3598 3599 if (ray->mOrigin[candidatePlane.mAxis] > candidatePlane.mPosition) 3600 pFront += vol; 3601 else 3602 pBack += vol; 3603 } 3838 AddViewCellVolume(*vit, classification, pFront, pBack, pOverall); 3604 3839 } 3605 3840 } … … 3611 3846 const float newRenderCost = pvsFront * pFront + pvsBack * pBack; 3612 3847 3613 Debug << "total pvs: " << totalPvs << " p " << pOverall << endl 3614 << "old: " << oldRenderCost << " new: " << newRenderCost << " decrease: " 3615 << oldRenderCost - newRenderCost << endl; 3616 3617 // todo matt§§: how to normalize volume?? 3618 const float renderCostDecrease = (oldRenderCost - newRenderCost);// / mBoundingBox.GetVolume(); 3619 3620 // take render cost of node into account 3621 // otherwise danger of being stuck in a local minimum!! 3622 const float factor = mRenderCostDecreaseWeight; 3623 3624 const float normalizedOldRenderCost = oldRenderCost;// / mBoundingBox.GetVolume(); 3625 return factor * renderCostDecrease + (1.0f - factor) * normalizedOldRenderCost; 3848 // normalize volume with view space volume 3849 const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol; 3850 3851 Debug << "\n==== eval render cost decrease ===" << endl 3852 << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 3853 << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl 3854 << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl 3855 << "render cost decrease: " << renderCostDecrease << endl; 3856 3857 normalizedOldRenderCost = oldRenderCost / viewSpaceVol; 3858 3859 return renderCostDecrease; 3626 3860 } 3627 3861 … … 3741 3975 } 3742 3976 } 3743 3744 3977 } 3745 3978 … … 3961 4194 3962 4195 4196 void OspTree::AddViewCellVolume(ViewCell *vc, 4197 const int cf, 4198 float &frontVol, 4199 float &backVol, 4200 float &totalVol) const 4201 { 4202 //const float renderCost = mViewCellsManager->SimpleRay &raynderCost(obj); 4203 const float vol = vc->GetVolume(); 4204 4205 // view cell not found yet => new 4206 if (!vc->Mailed() && !vc->Mailed(1) && !vc->Mailed(2)) 4207 { 4208 totalVol += vol; 4209 } 4210 4211 if (cf >= 0) // front volume 4212 { 4213 if (!vc->Mailed() && !vc->Mailed(2)) 4214 { 4215 frontVol += vol; 4216 4217 // already in back volume => in both volumes 4218 if (vc->Mailed(1)) 4219 vc->Mail(2); 4220 else 4221 vc->Mail(); 4222 } 4223 } 4224 4225 if (cf <= 0) // back volume 4226 { 4227 if (!vc->Mailed(1) && !vc->Mailed(2)) 4228 { 4229 backVol += vol; 4230 4231 // already in front volume => in both volume 4232 if (vc->Mailed()) 4233 vc->Mail(2); 4234 else 4235 vc->Mail(1); 4236 } 4237 } 4238 } 4239 3963 4240 3964 4241 /********************************************************************/ … … 3989 4266 3990 4267 3991 SplitCandidate *HierarchyManager::PrepareVsp(const VssRayContainer &sampleRays,4268 VspTree::VspSplitCandidate *HierarchyManager::PrepareVsp(const VssRayContainer &sampleRays, 3992 4269 AxisAlignedBox3 *forcedViewSpace, 3993 4270 RayInfoContainer &rays) … … 4009 4286 const int pvsSize = mVspTree.ComputePvsSize(rays); 4010 4287 4011 Debug << "pvs size: " << pvsSize << endl;4012 Debug << "rays size: " << rays.size() << endl;4288 Debug << "pvs size: " << (int)pvsSize << endl; 4289 Debug << "rays size: " << (int)rays.size() << endl; 4013 4290 4014 4291 //-- prepare view space partition … … 4052 4329 4053 4330 4054 SplitCandidate * HierarchyManager::PrepareOsp(const VssRayContainer &sampleRays,4331 OspTree::OspSplitCandidate * HierarchyManager::PrepareOsp(const VssRayContainer &sampleRays, 4055 4332 const ObjectContainer &objects, 4056 4333 AxisAlignedBox3 *forcedObjectSpace, … … 4139 4416 const long startTime = GetTime(); 4140 4417 4141 int i = 0; 4418 RunConstruction(true); 4419 4420 cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl; 4421 4422 mVspTree.mVspStats.Stop(); 4423 } 4424 4425 4426 bool HierarchyManager::SubdivideSplitCandidate(SplitCandidate *sc) 4427 { 4428 const bool globalTerminationCriteriaMet = 4429 GlobalTerminationCriteriaMet(sc); 4430 4431 const bool vspSplit = (sc->Type() == SplitCandidate::VIEW_SPACE); 4432 4433 if (vspSplit) 4434 { 4435 mVspTree.Subdivide(mTQueue, sc, globalTerminationCriteriaMet); 4436 return true; 4437 } 4438 else 4439 { 4440 mOspTree.Subdivide(mTQueue, sc, globalTerminationCriteriaMet); 4441 return false; 4442 } 4443 } 4444 4445 4446 void HierarchyManager::RunConstruction(const bool repair) 4447 { 4448 int numNodes = 0; 4449 4142 4450 while (!FinishedConstruction()) 4143 4451 { 4144 mCurrentCandidate = NextSplitCandidate(); 4145 4146 const bool globalTerminationCriteriaMet = 4147 GlobalTerminationCriteriaMet(mCurrentCandidate); 4148 4149 cout << "view cells: " << i ++ << endl; 4150 4452 SplitCandidate *splitCandidate = NextSplitCandidate(); 4453 4454 cout << "nodes: " << ++ numNodes << endl; 4455 4456 mTotalCost -= splitCandidate->GetRenderCostDecrease(); 4457 4458 //-- subdivide leaf node 4459 SubdivideSplitCandidate(splitCandidate); 4460 4151 4461 // cost ratio of cost decrease / totalCost 4152 const float costRatio = mCurrentCandidate->GetPriority() / mTotalCost; 4153 //Debug << "cost ratio: " << costRatio << endl; 4462 const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost; 4463 4464 Debug << "\n**********" << endl 4465 << "total cost: " << mTotalCost << " render cost decr: " 4466 << splitCandidate->GetRenderCostDecrease() 4467 << " cost ratio: " << costRatio << endl << endl; 4154 4468 4155 4469 if (costRatio < mTermMinGlobalCostRatio) 4156 4470 ++ mGlobalCostMisses; 4157 4158 //-- subdivide leaf node4159 4160 // we have either a object space or view space split4161 if (mCurrentCandidate->Type() == SplitCandidate::VIEW_SPACE)4162 {4163 VspTree::VspSplitCandidate *sc =4164 dynamic_cast<VspTree::VspSplitCandidate *>(mCurrentCandidate);4165 4166 VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);4167 }4168 else // object space split4169 {4170 OspTree::OspSplitCandidate *sc =4171 dynamic_cast<OspTree::OspSplitCandidate *>(mCurrentCandidate);4172 4173 KdNode *r = mOspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);4174 }4175 4471 4176 4472 // reevaluate candidates affected by the split 4177 4473 // for view space splits, this would be object space splits 4178 4474 // and other way round 4179 RepairQueue(); 4180 4181 DEL_PTR(mCurrentCandidate); 4182 } 4183 4184 cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl; 4185 4186 mVspTree.mVspStats.Stop(); 4475 if (repair) 4476 RepairQueue(); 4477 4478 DEL_PTR(splitCandidate); 4479 } 4187 4480 } 4188 4481 … … 4195 4488 RayInfoContainer *objectSpaceRays = new RayInfoContainer(); 4196 4489 4490 4197 4491 ///////////////////////////////////////////////////////////// 4198 4492 // view space space partition 4199 4493 ///////////////////////////////////////////////////////////// 4494 4200 4495 4201 4496 // makes no sense otherwise because only one kd cell available … … 4207 4502 mVspTree.mStoreKdPvs = false; 4208 4503 4209 SplitCandidate *sc = PrepareVsp(sampleRays, forcedViewSpace, *viewSpaceRays); 4210 mTQueue.Push(sc); 4504 VspTree::VspSplitCandidate *vsc = 4505 PrepareVsp(sampleRays, forcedViewSpace, *viewSpaceRays); 4506 // add to queue 4507 mTQueue.Push(vsc); 4211 4508 4212 4509 long startTime = GetTime(); … … 4218 4515 int i = 0; 4219 4516 4220 while (!FinishedConstruction()) 4221 { 4222 SplitCandidate *splitCandidate = NextSplitCandidate(); 4223 4224 const bool globalTerminationCriteriaMet = 4225 GlobalTerminationCriteriaMet(splitCandidate); 4226 4227 cout << "vsp nodes: " << i ++ << endl; 4228 4229 // cost ratio of cost decrease / totalCost 4230 const float costRatio = splitCandidate->GetPriority() / mTotalCost; 4231 //cout << "cost ratio: " << costRatio << endl; 4232 4233 if (costRatio < mTermMinGlobalCostRatio) 4234 ++ mGlobalCostMisses; 4235 4236 //-- subdivide leaf node 4237 4238 // we have either a object space or view space split 4239 VspTree::VspSplitCandidate *sc = 4240 dynamic_cast<VspTree::VspSplitCandidate *>(splitCandidate); 4241 4242 4243 VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet); 4244 4245 DEL_PTR(splitCandidate); 4246 } 4517 // all objects can be seen from everywhere 4518 mTotalCost = (float)vsc->mParentData.mPvs; 4519 4520 const bool repairQueue = false; 4521 4522 // process view space candidates 4523 RunConstruction(repairQueue); 4247 4524 4248 4525 cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl; 4249 4526 mVspTree.mVspStats.Stop(); 4250 4527 4251 4528 4529 4252 4530 ///////////////////////////////////////////////////////////// 4253 4531 // object space partition 4254 4532 ///////////////////////////////////////////////////////////// 4255 4533 4256 Debug << " **************** osp construction **************" << endl;4534 Debug << "\n$$$$$$$$$ osp tree construction $$$$$$$$$$\n" << endl; 4257 4535 cout << "starting osp contruction ... " << endl; 4258 4536 4537 // compute first candidate 4538 OspTree::OspSplitCandidate *osc = 4539 PrepareOsp(sampleRays, objects, forcedViewSpace, *objectSpaceRays); 4540 4541 mTQueue.Push(osc); 4542 4543 mOspTree.mOspStats.Reset(); 4544 mOspTree.mOspStats.Start(); 4545 4259 4546 startTime = GetTime(); 4260 4547 4261 SplitCandidate *osc = 4262 PrepareOsp(sampleRays, objects, forcedViewSpace, *objectSpaceRays); 4263 4264 mTQueue.Push(osc); 4265 4266 4267 i = 0; 4268 while (!FinishedConstruction()) 4269 { 4270 SplitCandidate *splitCandidate = NextSplitCandidate(); 4271 4272 const bool globalTerminationCriteriaMet = 4273 GlobalTerminationCriteriaMet(splitCandidate); 4274 4275 // cost ratio of cost decrease / totalCost 4276 const float costRatio = splitCandidate->GetPriority() / mTotalCost; 4277 4278 //Debug << "cost ratio: " << costRatio << endl; 4279 //cout << "kd nodes: " << i ++ << endl; 4280 4281 if (costRatio < mTermMinGlobalCostRatio) 4282 ++ mGlobalCostMisses; 4283 4284 //-- subdivide leaf node 4285 4286 // object space split 4287 OspTree::OspSplitCandidate *sc = 4288 dynamic_cast<OspTree::OspSplitCandidate *>(splitCandidate); 4289 4290 KdNode *r = mOspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet); 4291 4292 DEL_PTR(splitCandidate); 4293 } 4294 4295 cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl; 4296 4548 // reset cost 4549 // start with one big kd cell - all objects can be seen from everywhere 4550 // note: only true for view space = object space 4551 mTotalCost = (float)osc->mParentData.mNode->mObjects.size();//(float)sc->mParentData.mPvs; 4552 4553 Debug << "reseting cost, new total cost: " << mTotalCost << endl; 4554 4555 // process object space candidates 4556 RunConstruction(repairQueue); 4557 4558 cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl; 4559 4560 mOspTree.mOspStats.Stop(); 4561 4562 // reset parameters 4297 4563 mVspTree.mUseKdPvsForHeuristics = savedCountMethod; 4298 4564 mVspTree.mStoreKdPvs = savedStoreMethod; … … 4304 4570 AxisAlignedBox3 *forcedViewSpace) 4305 4571 { 4572 // only view space partition 4573 // object kd tree is taken for osp 4574 4306 4575 mVspTree.mVspStats.Reset(); 4307 4576 mVspTree.mVspStats.Start(); … … 4315 4584 4316 4585 long startTime = GetTime(); 4317 int i = 0; 4318 4319 while (!FinishedConstruction()) 4320 { 4321 SplitCandidate *splitCandidate = NextSplitCandidate(); 4322 4323 const bool globalTerminationCriteriaMet = 4324 GlobalTerminationCriteriaMet(splitCandidate); 4325 4326 cout << "vsp nodes: " << i ++ << endl; 4327 4328 // cost ratio of cost decrease / totalCost 4329 const float costRatio = splitCandidate->GetPriority() / mTotalCost; 4330 //cout << "cost ratio: " << costRatio << endl; 4331 4332 if (costRatio < mTermMinGlobalCostRatio) 4333 ++ mGlobalCostMisses; 4334 4335 //-- subdivide leaf node 4336 4337 // we have either a object space or view space split 4338 VspTree::VspSplitCandidate *sc = 4339 dynamic_cast<VspTree::VspSplitCandidate *>(splitCandidate); 4340 4341 4342 VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet); 4343 4344 DEL_PTR(splitCandidate); 4345 } 4586 4587 RunConstruction(false); 4346 4588 4347 4589 cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl; … … 4350 4592 4351 4593 4352 bool HierarchyManager::FinishedConstruction() 4594 bool HierarchyManager::FinishedConstruction() const 4353 4595 { 4354 4596 return mTQueue.Empty(); -
GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
r1144 r1145 66 66 int mMaxCostMisses; 67 67 68 /// priority of this split69 //float mPriority;70 71 68 SplitCandidate() 72 69 {}; … … 78 75 virtual int Type() const = 0; 79 76 virtual bool GlobalTerminationCriteriaMet() const = 0; 77 78 /** Set render cost decrease achieved through this split. 79 */ 80 void SetRenderCostDecrease(const float renderCostDecr) 81 { 82 mRenderCostDecrease = renderCostDecr; 83 } 84 85 float GetRenderCostDecrease() const 86 { 87 return mRenderCostDecrease; 88 } 89 90 protected: 91 92 /// render cost decrease achieved through this split 93 float mRenderCostDecrease; 94 80 95 }; 81 96 … … 814 829 */ 815 830 float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 816 const VspTraversalData &data) const; 831 const VspTraversalData &data, 832 float &normalizedOldRenderCost) const; 817 833 818 834 /** Collects view cells in the subtree under root. … … 852 868 */ 853 869 VspNode *Subdivide(SplitQueue &tQueue, 854 VspSplitCandidate &splitCandidate,870 SplitCandidate *splitCandidate, 855 871 const bool globalCriteriaMet); 856 872 … … 859 875 void AddSubdivisionStats(const int viewCells, 860 876 const float renderCostDecr, 861 const float splitCandidateCost,862 877 const float totalRenderCost, 863 878 const float avgRenderCost); … … 1024 1039 RayInfoContainer &rays); 1025 1040 1041 void EvalSubdivisionStats(const VspTraversalData &tData, 1042 const VspTraversalData &tFrontData, 1043 const VspTraversalData &tBackData); 1026 1044 protected: 1045 1027 1046 1028 1047 bool mUseKdPvsForHeuristics; … … 1442 1461 */ 1443 1462 float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane, 1444 const OspTraversalData &data) const; 1463 const OspTraversalData &data, 1464 float &normalizedOldRenderCost) const; 1445 1465 1446 1466 … … 1463 1483 */ 1464 1484 KdNode *Subdivide(SplitQueue &tQueue, 1465 OspSplitCandidate &splitCandidate,1485 SplitCandidate *splitCandidate, 1466 1486 const bool globalCriteriaMet); 1467 1487 … … 1585 1605 @param rightPvs updates the right pvs 1586 1606 */ 1587 void EvalHeuristicsContribution(const SortableEntry &ci, 1607 void EvalHeuristicsContribution(KdLeaf *leaf, 1608 const SortableEntry &ci, 1588 1609 float &volLeft, 1589 1610 float &volRight, 1590 1611 int &pvsLeft, 1591 int &pvsRight); 1612 int &pvsRight, 1613 int &viewCellsLeft, 1614 int &viewCellsRight); 1592 1615 1593 1616 /** Evaluate the contributions of view cell volume of the left and the right view cell. 1594 1617 */ 1595 void EvalVolumeContribution(const VssRay &ray, float &volLeft, float &volRight); 1618 void EvalVolumeContribution(const VssRay &ray, 1619 float &volLeft, 1620 float &volRight, 1621 int &viewCellsLeft, 1622 int &viewCellsRight); 1596 1623 1597 1624 /** Prepares objects for the cost heuristics. 1598 1625 @returns pvs size of the node 1599 1626 */ 1600 float PrepareHeuristics(const OspTraversalData &tData );1627 float PrepareHeuristics(const OspTraversalData &tData, int &numViewCells); 1601 1628 1602 1629 /** Prepares heuristics for a particular ray. 1603 1630 */ 1604 float PrepareHeuristics(const VssRay &ray );1631 float PrepareHeuristics(const VssRay &ray, int &numViewCells); 1605 1632 1606 1633 /** Prepares construction for vsp and osp trees. … … 1620 1647 RayInfoContainer &rays); 1621 1648 1622 1649 /** Reads parameters from environment singleton. 1650 */ 1623 1651 void ReadEnvironment(); 1652 1653 /** Returns true if the specified ray end points is inside the kd leaf. 1654 @param isTermination if origin or termination point should be checked 1655 */ 1656 bool EndPointInsideNode(KdLeaf *leaf, VssRay &ray, bool isTermination) const; 1657 1658 void AddViewCellVolume(ViewCell *vc, 1659 const int cf, 1660 float &frontPvs, 1661 float &backPvs, 1662 float &totalPvs) const; 1663 1664 int ClassifyRay(VssRay *ray, KdLeaf *leaf, const AxisAlignedPlane &plane) const; 1624 1665 1625 1666 protected: … … 1779 1820 RayInfoContainer &objectSpaceRays); 1780 1821 1781 bool FinishedConstruction(); 1822 void RunConstruction(const bool repair); 1823 bool SubdivideSplitCandidate(SplitCandidate *sc); 1824 1825 bool FinishedConstruction() const; 1782 1826 1783 1827 SplitCandidate *NextSplitCandidate(); … … 1787 1831 void CollectDirtyCandidates(vector<SplitCandidate *> &dirtyList); 1788 1832 1789 SplitCandidate *PrepareVsp(const VssRayContainer &sampleRays,1833 VspTree::VspSplitCandidate *PrepareVsp(const VssRayContainer &sampleRays, 1790 1834 AxisAlignedBox3 *forcedViewSpace, 1791 1835 RayInfoContainer &rays); 1792 1836 1793 SplitCandidate *PrepareOsp(const VssRayContainer &sampleRays,1837 OspTree::OspSplitCandidate *PrepareOsp(const VssRayContainer &sampleRays, 1794 1838 const ObjectContainer &objects, 1795 1839 AxisAlignedBox3 *forcedObjectSpace, -
GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp
r1076 r1145 432 432 exporter->SetFilled(); 433 433 //Randomize(); 434 debuggerWidget = new GlDebuggerWidget(renderer); 434 // §§matt 435 // debuggerWidget = new GlDebuggerWidget(renderer); 435 436 436 437 /*debuggerWidget->mBeam = beam; … … 439 440 440 441 Debug << "showing window" << endl; 441 debuggerWidget->show(); */442 443 renderer->makeCurrent(); 442 debuggerWidget->show(); 443 444 renderer->makeCurrent();*/ 444 445 445 446 for (int i = 0; i < 10; ++ i) … … 464 465 465 466 BeamSampleStatistics stats; 466 467 renderer->SampleBeamContributions(sourceObj,467 // §§matt 468 /* renderer->SampleBeamContributions(sourceObj, 468 469 beam, 469 470 200000, … … 475 476 image.save(s, "PNG"); 476 477 Debug << "beam statistics: " << stats << endl << endl; 477 478 */ 478 479 if (1) 479 480 { -
GTP/trunk/Lib/Vis/Preprocessing/src/common.h
r1112 r1145 38 38 //#pragma warning(disable:4244) 39 39 40 #if 0 // $$$matt: comment this out because conflicts with definition in qt library!!40 #if 0 // Note matt: comment this out because conflicts with definition in qt library!! 41 41 typedef unsigned int uint; 42 42 #endif -
GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
r1112 r1145 16 16 #include "ResourceManager.h" 17 17 18 #include <QApplication> 19 #include <QtOpenGL> 18 //#include <QApplication> 19 //#include <QtOpenGL> 20 #include <boost/thread/thread.hpp> 21 #include <boost/thread/xtime.hpp> 20 22 #include "GlRenderer.h" 21 23 … … 25 27 26 28 using namespace GtpVisibilityPreprocessor; 29 30 Preprocessor *preprocessor = NULL; 31 32 #if QT_ENABLED 33 QApplication *app = NULL; 34 #endif 35 36 37 void Cleanup() 38 { 39 #if QT_ENABLED 40 DEL_PTR(rendererWidget); 41 #endif 42 43 DEL_PTR(preprocessor); 44 45 Environment::DelSingleton(); 46 MeshManager::DelSingleton(); 47 MaterialManager::DelSingleton(); 48 } 49 50 51 void DisplayWidget() 52 { 53 #if QT_ENABLED 54 QApplication *app = NULL; 55 56 // create a qt application first (must be created before any opengl widget ...) 57 app = new QApplication(argc, argv); 58 59 if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) { 60 QMessageBox::information(0, "OpenGL pbuffers", 61 "This system does not support OpenGL/pbuffers.", 62 QMessageBox::Ok); 63 return -1; 64 } 65 66 // note matt: capsulate qt dependent code as good as possible 67 rendererWidget = 68 new GlRendererWidget(p->mSceneGraph, p->mViewCellsManager, p->mKdTree); 69 70 rendererWidget->resize(640, 480); 71 rendererWidget->show(); 72 73 if (0 && p->GetRenderer()) 74 { 75 cout<<"CONNECTING"<<endl; 76 QObject::connect(p->GetRenderer(), 77 SIGNAL(UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &)), 78 rendererWidget->mControlWidget, 79 SLOT(UpdatePvsErrorItem(int i, 80 GlRendererBuffer::PvsErrorEntry &))); 81 82 cout<<"CONNECTED"<<endl; 83 } 84 #endif 85 } 86 27 87 28 88 int … … 30 90 { 31 91 32 //Now just call this function at the start of your program and if you're 33 //compiling in debug mode (F5), any leaks will be displayed in the Output 34 //window when the program shuts down. If you're not in debug mode this will 35 //be ignored. Use it as you will! 36 //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() { 37 _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF); 38 _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE); 39 _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); 40 41 InitTiming(); 42 43 Debug.open("debug.log"); 44 45 Environment::GetSingleton()->Parse(argc, argv, USE_EXE_PATH); 46 MeshKdTree::ParseEnvironment(); 47 48 char buff[128]; 49 Environment::GetSingleton()->GetStringValue("Preprocessor.type", buff); 50 string preprocessorType(buff); 51 52 Preprocessor *p = NULL; 53 54 55 if (preprocessorType == "vss") 56 { 57 p = new VssPreprocessor(); 58 } 59 else 60 { 61 if (preprocessorType == "rss") 62 { 63 p = new RssPreprocessor(); 92 //Now just call this function at the start of your program and if you're 93 //compiling in debug mode (F5), any leaks will be displayed in the Output 94 //window when the program shuts down. If you're not in debug mode this will 95 //be ignored. Use it as you will! 96 //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() { 97 _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF); 98 _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE); 99 _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); 100 101 int returnCode = 0; 102 103 InitTiming(); 104 105 Debug.open("debug.log"); 106 107 Environment::GetSingleton()->Parse(argc, argv, USE_EXE_PATH); 108 MeshKdTree::ParseEnvironment(); 109 110 char buff[128]; 111 Environment::GetSingleton()->GetStringValue("Preprocessor.type", buff); 112 string preprocessorType(buff); 113 114 if (preprocessorType == "vss") 115 { 116 preprocessor = new VssPreprocessor(); 64 117 } 65 118 else 66 119 { 67 if (preprocessorType == "exact") 68 { 69 p = new ExactPreprocessor(); 70 } 71 else 72 { 73 if (preprocessorType == "sampling") 120 if (preprocessorType == "rss") 74 121 { 75 p = new SamplingPreprocessor();122 preprocessor = new RssPreprocessor(); 76 123 } 77 124 else 78 { 79 if (preprocessorType == "render") 80 { 81 p = new RenderSampler(); 82 } 83 else { 84 Environment::DelSingleton(); 85 cerr<<"Unknown preprocessor type"<<endl; 86 Debug<<"Unknown preprocessor type"<<endl; 87 exit(1); 88 } 125 { 126 if (preprocessorType == "exact") 127 { 128 preprocessor = new ExactPreprocessor(); 129 } 130 else 131 { 132 if (preprocessorType == "sampling") 133 { 134 preprocessor = new SamplingPreprocessor(); 135 } 136 else 137 { 138 if (preprocessorType == "render") 139 { 140 preprocessor = new RenderSampler(); 141 } 142 else { 143 Environment::DelSingleton(); 144 cerr<<"Unknown preprocessor type"<<endl; 145 Debug<<"Unknown preprocessor type"<<endl; 146 exit(1); 147 } 148 } 149 } 89 150 } 90 } 91 } 92 } 93 94 QApplication *app = NULL; 95 96 if (p->mUseGlRenderer || p->mUseGlDebugger) { 151 } 97 152 98 // create a qt application first (must be created before any opengl widget... 99 app = new QApplication(argc, argv); 100 101 if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) { 102 QMessageBox::information(0, "OpenGL pbuffers", 103 "This system does not support OpenGL/pbuffers.", 104 QMessageBox::Ok); 105 return -1; 106 } 107 } 108 109 preprocessor = p; 110 111 Environment::GetSingleton()->GetStringValue("Scene.filename", buff); 112 string filename(buff); 113 114 p->LoadScene(filename); 115 116 p->BuildKdTree(); 117 p->KdTreeStatistics(cout); 118 119 // parse view cells related options 120 p->PrepareViewCells(); 121 122 123 // create a preprocessor thread 124 PreprocessorThread *pt = new PreprocessorThread(p, app); 125 126 // p->mSceneGraph->Export("soda.x3d"); 127 if (0) { 128 p->Export(filename + "-out.x3d", true, false, false); 129 p->Export(filename + "-kdtree.x3d", false, true, false); 130 } 131 132 if (p->mUseGlRenderer) { 133 134 rendererWidget = new GlRendererWidget(p->mSceneGraph, p->mViewCellsManager, p->mKdTree); 135 // renderer->resize(640, 480); 136 137 rendererWidget->resize(640, 480); 138 rendererWidget->show(); 139 140 if (0 && p->GetRenderer()) { 141 142 cout<<"CONNECTING"<<endl; 143 QObject::connect(p->GetRenderer(), 144 SIGNAL(UpdatePvsErrorItem(int i, 145 GlRendererBuffer::PvsErrorEntry &)), 146 147 rendererWidget->mControlWidget, 148 SLOT(UpdatePvsErrorItem(int i, 149 GlRendererBuffer::PvsErrorEntry &))); 150 cout<<"CONNECTED"<<endl; 151 } 152 153 pt->start(QThread::LowPriority); 154 155 156 } else{ 157 // just call the mail method -> will be executed in the main thread 158 pt->Main(); 159 } 160 161 162 int returnCode = 0; 163 164 if (app) 165 { 166 returnCode = app->exec(); 167 DEL_PTR(app); 168 } 169 170 //-- clean up 171 DEL_PTR(p); 172 Environment::DelSingleton(); 173 DEL_PTR(rendererWidget); 174 175 MeshManager::DelSingleton(); 176 MaterialManager::DelSingleton(); 177 178 DEL_PTR(pt); 179 180 return returnCode; 153 154 //-- load scene 155 156 Environment::GetSingleton()->GetStringValue("Scene.filename", buff); 157 string filename(buff); 158 preprocessor->LoadScene(filename); 159 160 //-- build kd tree from scene geometry 161 162 preprocessor->BuildKdTree(); 163 preprocessor->KdTreeStatistics(cout); 164 165 // parse view cells related options 166 preprocessor->PrepareViewCells(); 167 168 // p->mSceneGraph->Export("soda.x3d"); 169 if (0) { 170 preprocessor->Export(filename + "-out.x3d", true, false, false); 171 preprocessor->Export(filename + "-kdtree.x3d", false, true, false); 172 } 173 174 175 // create a preprocessor thread 176 //PreprocessorThread *pt = new PreprocessorThread(p, app); 177 PreprocessorThread pt(preprocessor); 178 179 if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger) 180 { 181 // display the render widget 182 DisplayWidget(); 183 184 // create and run the thread 185 boost::thread thrd(pt); 186 thrd.join(); 187 //pt->start(QThread::LowPriority); 188 } 189 else 190 { 191 // just call the mail method -> will be executed in the main thread 192 pt.Main(); 193 } 194 195 #if QT_ENABLED 196 if (app) 197 { 198 returnCode = app->exec(); 199 DEL_PTR(app); 200 } 201 #endif 202 203 Cleanup(); 204 205 return returnCode; 181 206 } 182 207
Note: See TracChangeset
for help on using the changeset viewer.