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 }