00001 /* 00002 File: HierRad.cc 00003 00004 Function: See header file 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1997-2000, Andrew Willmott 00009 00010 Notes: 00011 */ 00012 00031 #include "HierRad.h" 00032 #include "GenLink.h" 00033 #include "Haar.h" 00034 #include <stdio.h> 00035 #include <unistd.h> 00036 00037 00038 00039 #ifdef RAD_VIS 00040 #include <strstream.h> 00041 #endif 00042 00043 #ifdef DEBUG 00044 #define DBG_COUT if (1) cerr 00045 #define DBG_COUT2 if (0) cerr 00046 #else 00047 #define DBG_COUT if (0) cerr 00048 #define DBG_COUT2 if (0) cerr 00049 #endif 00050 00051 HierRad::HierRad() : RadMethod(), cluster(0), leaves(0) 00052 { 00053 } 00054 00055 HierRad::~HierRad() 00056 { 00057 delete cluster; 00058 delete leaves; 00059 } 00060 00061 Void HierRad::SetScene(scScenePtr theScene) 00062 { 00063 Int i; 00064 00065 DBG_COUT << "setting HR scene..." << endl; 00066 00067 00068 clusterableElems.Clear(); 00069 00070 RadMethod::SetScene(theScene); // this calls ResetOptions too 00071 00072 // we don't do any remeshing, so collect stats here. 00073 00074 stats.Init(); 00075 for (i = 0; i < baseElems.NumItems(); i++) 00076 stats.Update(baseElems[i]); 00077 #ifdef DEBUG 00078 stats.Report(cerr); 00079 #endif 00080 } 00081 00082 Void HierRad::ResetOptions() 00083 { 00084 Int i, j; 00085 00086 gRadControl->finalPass = false; 00087 00088 if (clusterableElems.NumItems() > 0 00089 ) 00090 { 00091 DBG_COUT << "resetting existing elements" << endl; 00092 00093 // delete any previous meshing/clusters/etc. 00094 for (i = clusterableElems.NumItems() - 1; i >= 0; i--) 00095 clusterableElems[i]->Reset(); 00096 if (cluster) 00097 cluster->Reset(); 00098 } 00099 else 00100 { 00101 DBG_COUT << "creating elements" << endl; 00102 00103 delete cluster; 00104 cluster = 0; 00105 00106 // XXX cluster + higher order not supported yet. 00107 if (gRadControl->basis > kHaar) 00108 gRadControl->cluster = false; 00109 00110 // add patches to the elements list 00111 DBG_COUT << "base elems = " << baseElems.NumItems() << endl; 00112 clusterableElems.SetSize(baseElems.NumItems()); 00113 // upcast from RadElem pointer to HRElem pointer; we can assume that 00114 // all patches are a subclass of HRMeshElem. 00115 for (i = 0; i < baseElems.NumItems(); i++) 00116 clusterableElems[i] = (HRElemPtr) (HRMeshElem*) baseElems[i]; 00117 00118 00119 DBG_COUT << "total HR elems = " << clusterableElems.NumItems() << endl; 00120 } 00121 00122 numTrees = 0; 00123 leaves = 0; 00124 00125 ColourMeshInitial(); 00126 ColourVertices(); 00127 00128 #ifdef RAD_VIS 00129 gRadControl->pvData = 0; 00130 Field(out1) << clusterableElems.NumItems() << " patch elements"; 00131 Field(out1) << show; 00132 #endif 00133 } 00134 00135 00136 Void HierRad::Draw(Renderer &r) 00137 { 00138 Bool saveWire = gRadControl->wire; 00139 00140 if (gRadControl->patchView && gRadControl->pvData) 00141 { 00142 // draw contributors to this element 00143 gRadControl->outlineClusters = true; 00144 gRadControl->pvData->DrawContributors(r); 00145 gRadControl->outlineClusters = false; 00146 gRadControl->wire = true; 00147 } 00148 00149 // draw traditional patches 00150 RadMethod::Draw(r); 00151 00152 00153 // draw cluster last if it exists, so as to get transparency effects 00154 if (gRadControl->cluster && cluster) 00155 cluster->DrawElem(r); 00156 00157 gRadControl->wire = saveWire; 00158 } 00159 00160 Void HierRad::DrawMatrix(Renderer &r) 00161 { 00162 #ifdef RAD_VIS 00163 if (numTrees == 0) 00164 return; 00165 00166 00167 if (!gRadControl->drawMatrix || gRadControl->stop 00168 || gRadControl->cluster) 00169 return; 00170 00171 Int i; 00172 00173 for (i = 0; i < numTrees; i++) 00174 trees[i]->DrawMatrix(r, numTrees); 00175 #endif 00176 } 00177 00178 HRLink *HierRad::CreateLink() 00179 { 00180 HRLink *result; 00181 00182 // Create a top-level link between two patches 00183 00184 if (gRadControl->cluster) 00185 result = new GenLink; 00186 else if (gRadControl->basis == kHaar) 00187 result = new HaarLink; 00188 else 00189 _Error("(HierRad::CreateLink) Unsupported basis"); 00190 00191 return(result); 00192 } 00193 00194 00195 // --- Rendering methods ------------------------------------------------------ 00196 00197 // NOTE: All these routines return false if the render should 00198 // terminate. 00199 00200 Bool HierRad::CreateClusterLink() 00201 // Cluster the scene, and create the single initial top-level 00202 // link. 00203 { 00204 HRLink *newLink; 00205 00206 // Create cluster 00207 if (Stage(2)) return(false); 00208 if (!cluster) 00209 { 00210 cluster = new Cluster; 00211 cluster->SetElems(&clusterableElems); 00212 cluster->CreateHierarchy(); 00213 } 00214 00215 clusTree = cluster; 00216 trees = &clusTree; 00217 numTrees = 1; 00218 00219 // Create single top-level link 00220 linkPatch = 0; 00221 if (Stage(3)) return(false); 00222 00223 newLink = new GenLink; 00224 00225 newLink->MakeLink(cluster, cluster); 00226 cluster->links.Prepend(newLink); 00227 00228 return(true); 00229 } 00230 00231 Bool HierRad::CreateInitialPatchLinks() 00232 // Creates top-level links between initial base polygons 00233 { 00234 Int i, j; 00235 HRLink *newLink1, *newLink2; 00236 00237 // We only want to test visibility once 00238 // between each pair of patches. 00239 00240 numTrees = clusterableElems.NumItems(); 00241 trees = (HRElemPtr*) clusterableElems.Ref(); 00242 if (Stage(2)) return(false); 00243 00244 for (i = 0; i < numTrees; i++) 00245 { 00246 linkPatch = i; 00247 if (Stage(3)) return(false); 00248 00249 for (j = i + 1; j < numTrees; j++) 00250 { 00251 00252 newLink1 = 0; 00253 if (trees[i]->EltRho() != cBlack) 00254 { 00255 // Add link from j -> i 00256 00257 newLink1 = CreateLink(); 00258 if (newLink1->MakeLink(trees[j], trees[i])) 00259 { 00260 DBG_COUT2 << "link " << trees[j]->id << " to " 00261 << trees[i]->id << endl; 00262 trees[i]->links.Prepend(newLink1); 00263 } 00264 else 00265 { 00266 newLink1->FreeLink(newLink1); 00267 DBG_COUT << "top-level link REDACTED" << endl; 00268 continue; // don't bother with the other direction. 00269 } 00270 } 00271 00272 if (trees[j]->EltRho() != cBlack) 00273 { 00274 // Add link from i -> j, reusing i->j link visibility 00275 // if possible. 00276 00277 newLink2 = CreateLink(); 00278 if (newLink2->MakeLink(trees[i], trees[j], newLink1, true)) 00279 { 00280 DBG_COUT2 << "link " << trees[i]->id 00281 << " to " << trees[j]->id << endl; 00282 trees[j]->links.Prepend(newLink2); 00283 } 00284 else 00285 { 00286 DBG_COUT << "top-level link REDACTED" << endl; 00287 newLink2->FreeLink(newLink2); 00288 } 00289 } 00290 } 00291 } 00292 00293 return(true); 00294 } 00295 00296 Bool HierRad::TwoStageSolve() 00298 { 00299 Int i; 00300 GCLReal origErr; 00301 GCLReal resErr; 00302 00303 origErr = 1.0; 00304 error = 1.0; 00305 gRadControl->refineLevels = 32; 00306 if (gRadControl->solver != sv_scheduled) 00307 iterations = 0; 00308 if (Stage(5)) return(false); 00309 00310 // Refine the links in the scene 00311 if (Stage(6)) return(false); 00312 for (i = 0; i < numTrees; i++) 00313 { 00314 linkPatch = i; 00315 if (Stage(7)) return(false); 00316 trees[i]->Refine(); 00317 } 00318 00319 #ifdef RAD_RESTART_FROM_EMITTERS 00320 if (gRadControl->solver == sv_scheduled && iterations > 0) 00321 { 00322 DBG_COUT << "resetting radiosities" << endl; 00323 00324 for (i = 0; i < numTrees; i++) 00325 trees[i]->InitRad(); 00326 } 00327 #endif 00328 00329 // Solve for radiosities... 00330 do 00331 { 00332 resErr = 0.0; 00333 if (Stage(5)) return(false); 00334 00335 // Do a gather over the whole scene 00336 if (Stage(8)) return(false); 00337 for (i = 0; i < numTrees; i++) 00338 { 00339 poly = i; 00340 if (Stage(9)) return(false); 00341 #ifdef RAD_VIS 00342 // if (doUpdate && gRadControl->showLinks) 00343 // display->Clear().Draw(gRadControl->scene); 00344 #endif 00345 trees[i]->GatherAll(); 00346 #ifdef RAD_VIS 00347 // if (doUpdate && gRadControl->showLinks) 00348 // display->Show(); 00349 #endif 00350 } 00351 00352 // Now reconstruct the basis functions with a push/pull. 00353 // Separating the gather and push/pull stages like 00354 // this is the equivalent of Jacobi iteration, which is 00355 // more memory and time consuming than Gauss Seidel. Our 00356 // experiments with Gauss Seidel have shown that it can 00357 // lead to some instability problems however, especially 00358 // when there are a small number of very bright lights. 00359 00360 if (Stage(10)) return(false); 00361 for (i = 0; i < numTrees; i++) 00362 { 00363 poly = i; 00364 if (Stage(11)) return(false); 00365 trees[i]->ClearB(); 00366 trees[i]->PushPull(); 00367 resErr += abs(trees[i]->Error()); 00368 } 00369 00370 if (origErr == 1.0 && resErr > 0.0) 00371 origErr = resErr; 00372 error = resErr / origErr; 00373 if (!gRadControl->solver == sv_scheduled) 00374 iterations++; 00375 00376 if (Stage(12)) return(false); 00377 } 00378 while (gRadControl->solver != sv_scheduled && error > gRadControl->error); // UUU 00379 00380 return(true); 00381 } 00382 00383 Bool HierRad::MultiGridSolve() 00384 { 00385 Int i; 00386 Bool subdivided; 00387 GCLReal origErr; 00388 GCLReal resErr; 00389 00390 // Here we mix a single refine stage with a single solve stage, and 00391 // repeat until all links have been fully refined. 00392 00393 origErr = 1.0; 00394 error = 1.0; 00395 subdivided = true; 00396 iterations = 0; 00397 00398 // make sure mixed clusters etc. are refined before we start... 00399 // a bit hacky... 00400 if (gRadControl->cluster) 00401 { 00402 Double save1 = gRadControl->kAError; 00403 Double save2 = gRadControl->kFError; 00404 00405 gRadControl->refineLevels = 32; 00406 gRadControl->kAError = 1e9; 00407 gRadControl->kFError = 1e9; 00408 cluster->Refine(); 00409 gRadControl->kAError = save1; 00410 gRadControl->kFError = save2; 00411 } 00412 00413 // refine only one level at a time. 00414 gRadControl->refineLevels = 1; 00415 00416 do 00417 { 00418 resErr = 0.0; 00419 iterations++; 00420 if (Stage(5)) return(false); 00421 00422 // Do a gather over the whole scene 00423 if (Stage(8)) return(false); 00424 for (i = 0; i < numTrees; i++) 00425 { 00426 poly = i; 00427 if (Stage(9)) return(false); 00428 #ifdef RAD_VIS 00429 // if (doUpdate && gRadControl->showLinks) 00430 // display->Clear().Draw(gRadControl->scene); 00431 #endif 00432 trees[i]->GatherAll(); 00433 #ifdef RAD_VIS 00434 // if (doUpdate && gRadControl->showLinks) 00435 // display->Show(); 00436 #endif 00437 } 00438 00439 // Push/pull 00440 if (Stage(10)) return(false); 00441 for (i = 0; i < numTrees; i++) 00442 { 00443 poly = i; 00444 if (Stage(11)) return(false); 00445 trees[i]->ClearB(); 00446 trees[i]->PushPull(); 00447 resErr += abs(trees[i]->Error()); 00448 } 00449 00450 if (origErr == 1.0) 00451 origErr = resErr; 00452 error = resErr / origErr; 00453 if (Stage(12)) return(false); 00454 00455 if (!subdivided) // don't refine if we've subdivided all we can. 00456 continue; 00457 00458 // Refine the links in the scene 00459 if (Stage(6)) return(false); 00460 subdivided = false; 00461 for (i = 0; i < numTrees; i++) 00462 { 00463 linkPatch = i; 00464 if (Stage(7)) return(false); 00465 if (trees[i]->Refine()) 00466 subdivided = true; 00467 } 00468 00469 if (iterations > 30) break; // XXX 00470 } 00471 while ((gRadControl->refAllLinks && subdivided) || error > gRadControl->error); 00472 00473 return(true); 00474 } 00475 00476 Bool HierRad::ScheduledSolve() 00477 { 00478 GCLReal origErr; 00479 00480 // Here we repeat a two stage solve, dropping epsilon by a 00481 // set amount on each occasion. 00482 00483 origErr = gRadControl->kFError; 00484 iterations = 0; 00485 00486 do 00487 { 00488 if (!TwoStageSolve()) return(false); 00489 iterations++; 00490 gRadControl->kFError /= gRadControl->alpha; 00491 #ifdef RAD_VIS 00492 Field(out1) << "epsilon = " << gRadControl->kFError << show; 00493 #endif 00494 } while (iterations < gRadControl->schedIterations && !Pause()); 00495 00496 gRadControl->kFError = origErr; 00497 00498 return(true); 00499 } 00500 00501 Bool HierRad::Render() 00504 { 00505 Bool result; 00506 Int i; 00507 00508 // Initialisation 00509 00510 gRadControl->useBF = !(gRadControl->solver == sv_twoStage); 00511 linksCreated = 0; 00512 linksCreatedLast = 0; 00513 00514 if (gRadControl->basis != kHaar) 00515 // turn off anchoring & balancing for non-haar meshes 00516 { 00517 gRadControl->anchor = false; 00518 gRadControl->graded = false; 00519 } 00520 00521 RadMethod::Render(); 00522 00523 if (Stage(1)) return(false); 00524 00525 // Set up initial emission of the patches 00526 if (gRadControl->cluster) 00527 result = CreateClusterLink(); 00528 else 00529 result = CreateInitialPatchLinks(); 00530 00531 if (!result) 00532 return(false); 00533 00534 for (i = 0; i < numTrees; i++) 00535 trees[i]->InitRad(); 00536 00537 if (Stage(4)) return(false); 00538 00539 if (gRadControl->solver == sv_scheduled) 00540 result = ScheduledSolve(); 00541 else if (gRadControl->solver == sv_interleaved) 00542 result = MultiGridSolve(); 00543 else if (gRadControl->solver == sv_twoStage) 00544 result = TwoStageSolve(); 00545 else 00546 _Error("Unknown solver algorithm"); 00547 00548 if (Stage(13)) return(false); 00549 00550 return(result); 00551 } 00552 00553 00554 #ifdef RAD_VIS 00555 Void HierRad::DumpStats() 00556 { 00557 } 00558 00559 Int HierRad::Stage(Int stage) 00560 { 00561 Int i; 00562 ostrstream outMsg; 00563 Char tempStr[256]; 00564 Bool animate = gRadControl->animate || gRadControl->pause; 00565 00566 switch (stage) 00567 { 00568 case 1: // pre setup 00569 Field(out2) << "Starting patches: " << numTrees << show; 00570 Field(out1) << "Initialising patches." << show; 00571 ColourVertices(); 00572 StartUpdate(); 00573 break; 00574 00575 case 2: // create links (post setup) 00576 if (gRadControl->cluster) 00577 Field(out1) << "Creating clusters..." << show; 00578 else 00579 Field(out1) << "Creating links... " << show; 00580 ColourVertices(); 00581 display->Redraw(); 00582 break; 00583 00584 case 3: // create a link 00585 doUpdate = animate || Update(); 00586 if (doUpdate) 00587 { 00588 RenderMatrix(); 00589 if (animate) 00590 Field(out1) << "Creating links for element " << linkPatch 00591 << "/" << numTrees << show; 00592 else 00593 Field(out1) << "Created " << linkPatch << " links out of " 00594 << numTrees << show; 00595 } 00596 break; 00597 00598 case 4: // solve system with refinement 00599 Field(out1) << "Solving system with refinement" << show; 00600 ColourVertices(); 00601 display->Redraw(); 00602 break; 00603 00604 case 5: // solve system iteration 00605 RenderMatrix(); 00606 Field(out1) << "Starting iteration " << iterations << show; 00607 Field(out2) << "Iteration " << iterations << show; 00608 doUpdate = animate || Update(); 00609 break; 00610 00611 case 6: // refine links 00612 Field(out1) << "Refining links" << show; 00613 break; 00614 00615 case 7: // refine 1 link 00616 doUpdate = animate || Update(); 00617 if (doUpdate) 00618 { 00619 Field(out1) << "Refining links for element " << linkPatch << show; 00620 Field(out3) << "Total links created so far: " << linksCreated << show; 00621 RenderMatrix(); 00622 } 00623 break; 00624 00625 case 8: // gather 00626 Field(out1) << "Gathering radiosity" << show; 00627 ColourVertices(); 00628 display->Redraw(); 00629 break; 00630 00631 case 9: // gather across 1 link 00632 doUpdate = animate || Update(); 00633 if (doUpdate) 00634 { 00635 Field(out1) << "Gathering to element " << poly << show; 00636 ColourVertices(); 00637 display->Redraw(); 00638 } 00639 break; 00640 00641 case 10: // push/pull 00642 Field(out1) << "Push/Pulling hierarchies" << show; 00643 break; 00644 00645 case 11: // push/pull 1 00646 doUpdate = animate || Update(); 00647 if (doUpdate) 00648 { 00649 Field(out1) << "Push/Pull element " << poly << show; 00650 ColourVertices(); 00651 display->Redraw(); 00652 } 00653 break; 00654 00655 case 12: // finish one system iteration 00656 { 00657 HRStats stats; 00658 00659 ColourVertices(); 00660 display->Redraw(); 00661 00662 stats.Init(); 00663 for (i = 0; i < numTrees; i++) 00664 trees[i]->CalcStats(&stats); 00665 00666 Field(out2) << "Overall error: " << error << show; 00667 00668 outMsg << "Iterations: " << iterations << 00669 ", patches: " << stats.numPatches; 00670 if (stats.numVolClusters > 0) 00671 outMsg << ", vc: " << stats.numVolClusters; 00672 if (stats.numFaceClusters > 0) 00673 outMsg << ", fc: " << stats.numFaceClusters; 00674 outMsg << ", links: " << stats.numLinks; 00675 memcpy(tempStr, outMsg.str(), outMsg.pcount()); 00676 tempStr[outMsg.pcount()] = 0; 00677 00678 Field(out3) << tempStr << show; 00679 } 00680 break; 00681 case 13: // all done 00682 Field(out1) << "Colouring models...." << show; 00683 gRadControl->finalPass = true; 00684 ColourVertices(); 00685 Field(out1) << "Finished." << show; 00686 display->Redraw(); 00687 break; 00688 00689 } 00690 00691 return(Pause()); 00692 } 00693 00694 #else 00695 00696 static Char *tBasis[] = {"none", "haar", "f2", "f3", "m2", "m3"}; 00697 static Int tBasisOrder[] = {0, 1, 2, 3, 2, 3}; 00698 00699 static GCLReal gAlpha = 0.0; 00700 static Int gLinks0 = 0; 00701 00702 Void HierRad::DumpStats() 00703 { 00704 Int i, m = tBasisOrder[gRadControl->basis]; 00705 GCLReal mem, linkMem, patchMem, volClusMem; 00706 HRStats stats; 00707 00708 stats.Init(); 00709 for (i = 0; i < numTrees; i++) 00710 trees[i]->CalcStats(&stats); 00711 00712 // Calculate projected memory use 00713 #ifdef RAD_THEORY_MEM 00714 linkMem = sizeof(Void*) * 2 + sizeof(GCLReal) + sizeof(Colour) * 00715 sqr(sqr(m)); 00716 patchMem = sizeof(Void*) * 5 + sizeof(Colour) * sqr(m) * 2; 00717 // 4 children, one link list pointer, m colour coefficients * 2. 00718 faceClusMem = sizeof(Void*) * 2 + sizeof(Colour) * 6; 00719 // 2 children, 3 colour coeffs * 2 00720 volClusMem = sizeof(Void*) * 8 + sizeof(Colour) * 2; 00721 // 8 children, 1 HRElem pointer, 1 colour coeffs * 2 00722 #else 00723 linkMem = sizeof(GenLink); 00724 patchMem = sizeof(HRMeshElem); 00725 volClusMem = sizeof(Cluster); 00726 #endif 00727 00728 mem = linkMem * stats.numLinks 00729 + patchMem * stats.numPatches 00730 + volClusMem * stats.numVolClusters 00731 ; 00732 00733 00734 mem /= 1024.0; 00735 00736 if (gAlpha <= 0.0) 00737 gLinks0 = stats.numLinks; 00738 00739 if (gAlpha < 0.0) 00740 gAlpha = stats.numLinks / sqr(gRadControl->numPolys); 00741 00742 cout << dumpID 00743 << ' ' << totTime 00744 << ' ' << gRadControl->stage 00745 << ' ' << iterations 00746 << ' ' << stats.numPatches 00747 << ' ' << stats.numVolClusters 00748 << ' ' << stats.numLinks 00749 << ' ' << linksCreated 00750 << ' ' << gAlpha 00751 << ' ' << stats.numLinks - gLinks0 00752 00753 << ' ' << error 00754 << ' ' << gRadControl->rays 00755 << ' ' << mem 00756 << ' ' << grid->MemoryUsage() 00757 << ' ' << TotalMemoryUse() 00758 << endl; 00759 00760 DumpScene(); 00761 } 00762 00763 static Char *gSolverNames[] = 00764 { 00765 "twoStage", 00766 "interleaved", 00767 "scheduled", 00768 0 00769 }; 00770 00771 Int HierRad::Stage(Int stage) 00772 { 00773 if (CheckTime()) return(1); 00774 00775 gRadControl->stage = stage; 00776 00777 switch (stage) 00778 { 00779 case 2: 00780 cout << "method hier " << tBasis[gRadControl->basis] << endl; 00781 if (gRadControl->cluster) cout << "clustering" << endl; 00782 cout << "solver " << gSolverNames[gRadControl->solver] << endl; 00783 00784 cout << "tErr " << gRadControl->error << endl; 00785 cout << "fErr " << gRadControl->kFError << endl; 00786 cout << "aErr " << gRadControl->kAError << endl; 00787 cout << "dErr " << gRadControl->dFError << endl; 00788 cout << "vErr " << gRadControl->visError << endl; 00789 cout << "scene " << sceneName << endl; 00790 cout << "polys " << gRadControl->numPolys << endl; 00791 cout << "srcPatches " << numTrees << endl; 00792 // must match with list in DumpStats 00793 cout << "format " 00794 << "ID " 00795 << "time " 00796 << "stage " 00797 << "iterations " 00798 << "patches " 00799 << "volClusters " 00800 << "links " 00801 << "totLinks " 00802 << "sparsity " 00803 << "newLinks " 00804 << "resErr " 00805 << "rays " 00806 << "mem " 00807 << "rtMem " 00808 << "rss " 00809 << endl; 00810 cout << "----------------------------------------" 00811 << "---------------------------------------" << endl; 00812 00813 iterations = 0; 00814 error = 0; 00815 gRadControl->finalPass = false; 00816 DumpStats(); 00817 break; 00818 00819 case 4: 00820 // At this point the first-pass linking has been done. 00821 gAlpha = -1.0; // signal the DumpStats procedure 00822 DumpStats(); 00823 break; 00824 00825 case 13: 00826 if (gRadControl->dumpTree) 00827 { 00828 ofstream s; 00829 cerr << "Saving final hierarchy as " << (gRadControl->outFile) + ".hier" << endl; 00830 s.open(StrConst(gRadControl->outFile) + ".hier"); 00831 HRElem::out = &s; 00832 s << "# hierarchy dump for " << sceneName << endl; 00833 s << "# e <ID> <childID1> <childID2>... -> define element" << endl; 00834 s << "# l <fromID> <toID> -> define link" << endl; 00835 for (Int i = 0; i < numTrees; i++) 00836 trees[i]->DumpHierarchy(0); 00837 s.close(); 00838 HRElem::out = &cout; 00839 } 00840 gRadControl->finalPass = true; 00841 DumpStats(); 00842 timer.ContTimer(); 00843 GetElements(); // final pass gets performed here. 00844 timer.StopTimer(); 00845 totTime = timer.GetTimer(); 00846 gRadControl->stage++; 00847 DumpStats(); 00848 00849 break; 00850 } 00851 00852 if (Idle()) return(0); 00853 timer.ContTimer(); 00854 return(0); 00855 } 00856 00857 #endif 00858 00859 RadElem *HierRad::NewMesh() 00860 { 00861 RadElem *elem; 00862 00863 if (gRadControl->basis == kHaar) 00864 elem = new HaarElem(); 00865 else 00866 _Error("(HierRad::NewMesh) Unhandled basis"); 00867 00868 return(elem); 00869 } 00870 00871 Void HierRad::ColourVertices() 00872 { 00873 Int i, j, oldRays; 00874 ProgramTimer timer; 00875 // colour underlying mesh & models 00876 00877 oldRays = gRadControl->rays; 00878 if (gRadControl->finalPass) 00879 { 00880 if (gRadControl->shotDisplay) 00881 gRadControl->showRays = true; 00882 timer.StartTimer(); 00883 00884 } 00885 00886 // colour leaves 00887 if (gRadControl->finalPass && gRadControl->bestPass) 00888 for (i = 0; i < numTrees; i++) 00889 { 00890 ShadeInfo shadeInfo; 00891 00892 trees[i]->DistributeColoursBest(shadeInfo); 00893 } 00894 else 00895 for (i = 0; i < numTrees; i++) 00896 trees[i]->DistributeColours(); 00897 00898 for (i = 0; i < baseElems.NumItems(); i++) 00899 ((HRMeshElem*) baseElems[i])->HRCorrectLeaves(); 00900 00901 00902 if (gRadControl->finalPass) 00903 { 00904 DBG_COUT << "Done doing final distribute : " << timer.GetTimer() << "s" << endl; 00905 DBG_COUT << "Cast " << gRadControl->rays - oldRays << " more rays." << endl; 00906 } 00907 00908 // for meshes, as before... 00909 00910 RadMethod::ColourVertices(); 00911 } 00912 00913 00914 PatchList *HierRad::GetElements() 00915 { 00916 if (!leaves) 00917 { 00918 Int i, j, n, numSubElems, numSplitElems = 0; 00919 HierElemPtr subElems[5]; 00920 00921 ColourVertices(); 00922 00923 00924 leaves = new PatchList; 00925 for (i = 0; i < baseElems.NumItems(); i++) 00926 ((HierElemPtr) baseElems[i])->CollectLeaves(*leaves); 00927 00928 if (gRadControl->anchor) 00929 { 00930 n = leaves->NumItems(); 00931 00932 for (i = 0; i < n; i++) 00933 { 00934 ((HierElemPtr) leaves->Item(i))->SplitElement(numSubElems, subElems); 00935 00936 if (numSubElems > 0) 00937 { 00938 numSplitElems++; 00939 00940 leaves->Item(i) = subElems[0]; 00941 for (j = 1; j < numSubElems; j++) 00942 leaves->Append(subElems[j]); 00943 } 00944 } 00945 } 00946 } 00947 00948 return(leaves); 00949 } 00950 00951 Void HierRad::PrintCmds(ostream &s) const 00952 { 00953 Int i; 00954 00955 RadMethod::PrintCmds(s); 00956 00957 } 00958 00959 Bool HierRad::ParseCmd(StrConst str, istream &s) 00960 { 00961 // XXX broken at the mo' 00962 return(RadMethod::ParseCmd(str, s)); 00963 } 00964 00965 00966 HRElem *HierRad::ClosestHRIntersection(Point &start, Point &dir, Point &p) 00967 { 00968 #ifdef RAD_VIS 00969 if (grid) 00970 { 00971 if (grid->ClosestIntersection(start, dir)) 00972 { 00973 p = grid->hitT * dir + start; 00974 00975 if (grid->hitPrim->object->id == 0) 00976 { 00977 if (rtElemPtrs.NumItems() > 0) 00978 return(dynamic_cast<HRMeshElem*>(rtElemPtrs[grid->hitPrim->id])); 00979 } 00980 } 00981 } 00982 #endif 00983 00984 return(0); 00985 }