Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

HierRad.cc

Go to the documentation of this file.
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 }

Generated at Sat Aug 5 00:26:51 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000