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

HProgRad.cc

Go to the documentation of this file.
00001 /*
00002     File:           HProgRad.cc
00003 
00004     Function:       See header file
00005 
00006     Author(s):      Andrew Willmott
00007 
00008     Copyright:      (c) 1999-2000, Andrew Willmott
00009 
00010     Notes:          
00011 
00012     Change History:
00013 */
00014 
00015 #include "HProgRad.h"
00016 #include "HierMesh.h"
00017 #include "gcl/Draw.h"
00018 
00019 
00020 Void HProgRad::ResetOptions()
00021 {
00022     Int     i;
00023     
00024     CreatePatches();
00025 
00026     elements.Clear();
00027     eltParents.Clear();
00028 
00029     for (i = 0; i < patches.NumItems(); i++)
00030         ((HierElem *) patches[i])->CreateElements(elements, eltParents, i);  
00031 
00032     ColourMeshInitial();
00033     ColourVertices();
00034 
00035 #ifdef RAD_VIS
00036     Field(out1) << patches.NumItems() << " patches, " << 
00037         elements.NumItems() << " elements." << show;
00038 #endif
00039 }
00040 
00041 static Colour SingleFormFactor(RadElem *fromPatch, RadElem *toPatch)
00042 {
00043     GCLReal     visibility;
00044     GCLReal     factor;
00045     Colour      result;
00046         
00047     if (len(toPatch->Reflectance()) < 0.0001)
00048     {
00049         result.MakeZero();
00050         return(result);
00051     }
00052 
00053     visibility = fromPatch->Visibility(toPatch);
00054         
00055     if (visibility > 0.0)
00056     {
00057         factor = fromPatch->EstFormFactor(toPatch);
00058         result = toPatch->Reflectance();
00059         result *= factor * visibility;
00060     }
00061     else
00062         result.MakeZero();
00063         
00064     return(result);
00065 }
00066 
00067 
00068 Bool HProgRad::Render()
00069 {
00070     Int         i, j;
00071     Colour      c;
00072     Colour      deltaRad;
00073     Colour      radToShoot;
00074     Bool        subdivided;
00075     Int         numElts = elements.NumItems();
00076     Int         numPatches = patches.NumItems();
00077     GCLReal     power, envArea;
00078     Colour      envPower, envRefl;
00079     Bool        finished = false; 
00080     RadElem     *shootPatch;
00081     ColourList  *theFFRow;
00082     
00083     RadMethod::Render();
00084     
00085     iterations = 0;
00086     error = 1.0;
00087     origShoot = 0;
00088     
00089     B.SetSize(numElts);         // Radiosity vectors for R, G, B
00090     S.SetSize(numPatches);      // Unshot radiosity vectors for R, G, B
00091     
00092     for (i = 0; i < patches.NumItems(); i++)
00093         S[i] = patches[i]->Emittance();
00094     
00095     for (i = 0; i < numElts; i++)
00096         B[i] = S[eltParents[i]];
00097 
00098     envRad = vl_1;
00099 
00100     if (Stage(1)) return(0);
00101     
00102     //  Setup for the ambient term
00103 
00104     envRefl.MakeZero();
00105     envArea = 0;
00106     envPower.MakeZero();
00107      
00108     for (i = 0; i < numPatches; i++)
00109     {
00110         envRefl += patches[i]->area * patches[i]->Reflectance();
00111         envArea += patches[i]->area;    
00112         envPower += S[i] * patches[i]->area;
00113     }
00114     
00115     envPower /= envArea;
00116 
00117     //  R = 1 / (1 - avgReflectance)
00118     
00119     for (i = 0; i < 3; i++)
00120         envRefl[i] = 1.0 / (1.0 - envRefl[i] / envArea);
00121                 
00122     //  Now, run the algorithm...
00123                         
00124     while (!finished)
00125     {   
00126         if (Stage(2)) return(0);
00127         
00128         iterations++;
00129                 
00130         //  Find the patch with the max power to shoot...
00131                 
00132         maxPower = 0;
00133         maxPowerIndex = 0;
00134         envPower.MakeZero();
00135         
00136         for (i = 0; i < numPatches; i++)                        
00137         {
00138             c = S[i] * patches[i]->area;            
00139             power = dot(c, kRadRGBToLum);
00140             
00141             if (maxPower < power)
00142             {
00143                 maxPower = power;
00144                 maxPowerIndex = i;
00145             }
00146         }
00147         
00148         radToShoot = S[maxPowerIndex];
00149         radToShoot *= gRadControl->alpha;
00150         shootPatch = patches[maxPowerIndex];
00151 
00152         if (Stage(3)) return(0);
00153 
00154         // Find initial form factors
00155 #ifdef RAD_VIS
00156         if (gRadControl->drawMatrix)
00157         {
00158             if (maxPowerIndex >= FFElts.NumItems())
00159                 FFElts.SetSize(maxPowerIndex + 1);
00160             FFElts[maxPowerIndex] = elements;
00161 
00162             theFFRow = &FFRows[maxPowerIndex];
00163         }
00164         else
00165 #endif
00166         theFFRow = &FFRow;
00167         MakeFormFactorFromVector(*shootPatch, elements, *theFFRow);
00168 
00169         if (Stage(4)) return(0);            
00170     
00171         //  Shoot radiosity, updating S and B as necessary          
00172         error = 0;
00173         S[maxPowerIndex] -= radToShoot;
00174             
00175         for (i = 0; i < numElts; i++)
00176         {
00177             deltaRad = (*theFFRow)[i] * radToShoot;
00178             B[i] += deltaRad;
00179                                         
00180             // Push radiosity delta to the parent...                    
00181             S[eltParents[i]] += deltaRad * (elements[i]->area 
00182                                             / patches[eltParents[i]]->area);
00183             error += sqrlen(deltaRad);
00184         }
00185     
00186         error = sqrt(error);
00187 
00188         // Calculate ambient light in scene...
00189     
00190         if (gRadControl->ambient)
00191         {
00192             envPower = vl_0;
00193             for (i = 0; i < numPatches; i++)
00194                 envPower += S[i] * patches[i]->area;
00195             
00196             envPower /= envArea;
00197             envRad = envRefl * envPower;
00198         }
00199         else
00200             envRad.MakeZero();
00201 
00202         if (true)   // was multigrid option???
00203             do 
00204             {                       
00205                 Colour      oldFF, f0, f1, f2, f3, temp;
00206 
00207                 // Subdivide receiving elements as necessary...
00208                 
00209                 subdivided = false;
00210                 
00211                 // Distribute radiosity to vertices so we can measure error
00212                 for (i = 0; i < numElts; i++)
00213                     ((HierElem *) elements[i])->SetColour(
00214                         B[i] + envRad * elements[i]->Reflectance());
00215                 ColourVertices();
00216                 
00217                 if (Stage(5)) return(0);
00218 
00219                 for (i = 0; i < numElts; i++)
00220                 {
00221                     HierElem *old = (HierElem *) elements[i];
00222                 
00223                     if (old->area >= gRadControl->kAError &&
00224                             old->RadError() > gRadControl->kFError)
00225                     {
00226                         // We need to subdivide
00227                                                 
00228                         if (!old->HasChildren())
00229                             old->Subdivide();
00230 
00231                         // Replace elt with its subdivisions...
00232                         elements[i] = old->child[0];                            
00233                         elements.Append(old->child[1]);
00234                         elements.Append(old->child[2]);
00235                         elements.Append(old->child[3]);
00236                         
00237                         j = eltParents[i];
00238                         eltParents.Append(j);
00239                         eltParents.Append(j);
00240                         eltParents.Append(j);
00241                                                                         
00242                         // Generate new form factors to the children...
00243                         f0 = SingleFormFactor(shootPatch, old->child[0]);
00244                         f1 = SingleFormFactor(shootPatch, old->child[1]);
00245                         f2 = SingleFormFactor(shootPatch, old->child[2]);
00246                         f3 = SingleFormFactor(shootPatch, old->child[3]);
00247                         oldFF = (*theFFRow)[i];
00248                         
00249                         theFFRow->Item(i) = f0;
00250                         theFFRow->Append(f1);
00251                         theFFRow->Append(f2);
00252                         theFFRow->Append(f3);
00253                         
00254                         // update contribution to parent...     
00255                         temp = f0 * old->child[0]->area 
00256                             + f1 * old->child[1]->area 
00257                             + f2 * old->child[2]->area 
00258                             + f3 * old->child[3]->area 
00259                             - oldFF * old->area;
00260                         S[j] += radToShoot * (temp / patches[j]->area);
00261 
00262                         // update child radiosities...                  
00263                         B.Append(B[i] + radToShoot * (f1 - oldFF));
00264                         B.Append(B[i] + radToShoot * (f2 - oldFF));
00265                         B.Append(B[i] + radToShoot * (f3 - oldFF));
00266                         B[i] += radToShoot * (f0 - oldFF);
00267 
00268                         subdivided = true;
00269                     }   
00270                 }
00271                 numElts = elements.NumItems();
00272 #ifdef RAD_VIS
00273                 if (maxPowerIndex >= FFElts.NumItems())
00274                     FFElts.SetSize(maxPowerIndex + 1);
00275                 FFElts[maxPowerIndex] = elements;
00276 #endif                                          
00277                 
00278                 Stage(6);
00279             } 
00280             while (subdivided);
00281     
00282         // Stop us before we shoot again
00283 
00284         if (iterations == 1)
00285             origShoot = maxPower;
00286         else
00287             finished = 
00288                 (gRadControl->maxShots > 0 && iterations > gRadControl->maxShots)
00289                 || (maxPower < gRadControl->error * origShoot);
00290         
00291         if (Stage(7)) return(0);
00292     }   
00293     
00294     if (Stage(8)) return(0);
00295 
00296     return(1);
00297 }
00298 
00299 
00300 #ifdef RAD_VIS
00301 
00302 Void HProgRad::DumpStats(){}
00303 
00304 Int HProgRad::Stage(Int stage)
00305 {
00306     Int     i, j;
00307     Bool    animate = gRadControl->animate || gRadControl->pause;
00308  
00309     switch (stage)
00310     {
00311     case 1:     // pre setup
00312         Field(out3) << patches.NumItems() << " patches, " 
00313                     << elements.NumItems() << " elements." << show;
00314         Field(out1) << "Forming emission vector E..." << show;
00315         FFRow.Clear();
00316         FFElts.Clear();
00317         if (gRadControl->drawMatrix)
00318         {
00319             FFRows.SetSize(patches.NumItems());
00320             FFElts.SetSize(patches.NumItems());
00321 //          FFRows.ClearTo(ColourList());
00322 //          FFElts.ClearTo(PatchList());
00323         }
00324         StartUpdate();
00325         break;
00326         
00327     case 2:     // post setup
00328         ColourVertices();
00329         display->Redraw();
00330 
00331         doUpdate = animate || Update();
00332 
00333         if (animate)
00334             Field(out1) << "Finding patch to shoot..." << show;
00335         else if (doUpdate)
00336         {
00337             Char *plural;
00338             if (iterations == 1)
00339                 plural = "";
00340             else
00341                 plural = "es";
00342             Field(out1) << iterations << " patch" << plural << " shot" << show;
00343             
00344         }           
00345         break;
00346         
00347     case 3:     
00348         if (doUpdate)
00349         {
00350             if (animate)
00351             {
00352                 Field(out1) << "Finding factors for patch " << maxPowerIndex 
00353                             << show;
00354                 
00355             // flash shooting patch red
00356                 patches[maxPowerIndex]->SetHighlight(1);
00357             }
00358 
00359             ColourVertices();
00360             display->Redraw();      
00361         }
00362         break;
00363         
00364     case 4:
00365         if (doUpdate)
00366         {
00367             if (animate)
00368                 Field(out1) << "Shooting patch " << maxPowerIndex << show;
00369             RenderMatrix();
00370             display->Redraw();      
00371         }
00372         break;
00373         
00374     case 5:         
00375         if (animate)
00376             Field(out1) << "Looking for elements to subdivide..." << show;
00377         if (doUpdate)
00378             display->Redraw();
00379         break;
00380         
00381     case 6: 
00382         if (doUpdate)
00383         {
00384             display->Redraw();
00385             UpdateCont();
00386         }
00387         if (animate)
00388             Field(out1) << "Re-shooting Patch " << maxPowerIndex << show;
00389         Field(out2) << "error = " << maxPower / origShoot 
00390                     << ", RMS Error = " << error << show;
00391         Field(out3) << patches.NumItems() << " patches, " 
00392                     << elements.NumItems() << " elements." << show;
00393         break;
00394         
00395     case 7:     // Middle of solve loop.
00396         if (doUpdate)
00397         {
00398             Colour c;
00399         
00400             patches[maxPowerIndex]->SetHighlight(0);
00401 
00402             if (gRadControl->shotDisplay)
00403                 // Colour the elements according to S...
00404                 for (i = 0; i < elements.NumItems(); i++)
00405                     ((HierElem*) elements[i])->SetColour(S[eltParents[i]]);
00406             else
00407                 // Colour the elements according to B...
00408                 for (i = 0; i < elements.NumItems(); i++)
00409                     ((HierElem*) elements[i])->
00410                         SetColour(B[i] + envRad * elements[i]->Reflectance());
00411         
00412             ColourVertices();
00413             display->Redraw();
00414         
00415             if (animate)
00416             {
00417                 Field(out1) << "Done with shooting " << show;
00418                 Field(out3) << patches.NumItems() << " patches, " 
00419                             << elements.NumItems() << " elements." << show;
00420         
00421                 Field(out2) << "error = " << maxPower / origShoot 
00422                             << ", RMS Error = " << error << show;
00423             }
00424             UpdateCont();
00425         }
00426         break;
00427         
00428     case 8:
00429         Field(out1) << "Finished: " << iterations << " patches shot" << show;
00430         
00431         // Colour the elements according to B...
00432         for (i = 0; i < elements.NumItems(); i++)
00433             ((HierElem*) elements[i])->SetColour(B[i] + envRad 
00434                                                  * elements[i]->Reflectance());
00435         ColourVertices();
00436         break;
00437     }
00438     
00439     return(Pause());
00440 }
00441 
00442 #else
00443 
00444 Void HProgRad::DumpStats()
00445 {
00446     Int     i, j;
00447     Colour  c;
00448     GCLReal shotErr, mem;
00449 
00450     if (origShoot == 0.0)
00451         shotErr = 1.0;
00452     else
00453         shotErr = maxPower / origShoot;
00454     
00455     mem = sizeof(Colour) * (B.NumItems() + S.NumItems() + FFRow.NumItems()
00456               + elements.NumItems()) + sizeof(Int) * eltParents.NumItems();
00457     mem /= 1024.0;
00458     
00459     cout << dumpID
00460         << ' ' << totTime
00461         << ' ' << gRadControl->stage
00462         << ' ' << patches.NumItems()
00463         << ' ' << elements.NumItems()
00464 
00465         << ' ' << shotErr
00466         << ' ' << error
00467         << ' ' << gRadControl->rays
00468         << ' ' << iterations
00469         << ' ' << mem
00470         << ' ' << grid->MemoryUsage()
00471         << ' ' << TotalMemoryUse()
00472         << endl;
00473 
00474     for (i = 0; i < elements.NumItems(); i++)       // Colour the elements...
00475         ((HierElem*) elements[i])->SetColour(B[i] + 
00476                               envRad * elements[i]->Reflectance());
00477 
00478     DumpScene();
00479 #ifdef RAD_MEM_USE
00480     DumpMemoryUse();
00481 #endif
00482 }
00483 
00484 Int HProgRad::Stage(Int stage)
00485 {
00486     if (CheckTime()) return(1);
00487 
00488     gRadControl->stage = stage;
00489 
00490     switch (stage)
00491     {
00492     case 1:     // pre setup
00493         cout << "method hprog " << endl;
00494         cout << "sub " << gRadControl->patchSubdivs << endl;
00495         cout << "esub " << gRadControl->eltSubdivs << endl;
00496         cout << "tErr " << gRadControl->error << endl;
00497         cout << "fErr " << gRadControl->kFError << endl;
00498         cout << "aErr " << gRadControl->kAError << endl;
00499         cout << "scene " << sceneName << endl;
00500         cout << "polys " << gRadControl->numPolys << endl;
00501         cout << "srcPatches " << patches.NumItems() << endl;
00502         cout << "format "
00503              << "ID "
00504              << "time "
00505              << "stage "
00506              << "srcPatches "
00507              << "patches "
00508              << "shootErr "
00509              << "resErr "
00510              << "rays "
00511              << "iterations "
00512              << "mem "
00513              << "rtMem "
00514              << "rss "
00515              << endl;
00516  
00517         cout << "----------------------------------------------"
00518              << "---------------------------------" << endl;
00519     
00520         DumpStats();
00521         break;
00522                 
00523     case 8:
00524         DumpStats();
00525         break;
00526     }
00527     
00528     if (Idle()) return(1);
00529     timer.ContTimer();
00530     return(0);
00531 }
00532 
00533 #endif
00534 
00535 Void HProgRad::DrawMatrix(Renderer &r)
00536 {
00537     if (!gRadControl->drawMatrix || gRadControl->stop)
00538         return;
00539         
00540 #ifdef RAD_VIS
00541     Int         i, j;
00542     GCLReal     x1, x2, y1, y2, wx, wy, m;
00543     HierElem    *hq;
00544     
00545     wx = 2.0 / FFRows.NumItems();
00546     
00547     x1 = -1;
00548     x2 = wx - 1;
00549     
00550     for (i = 0; i < FFRows.NumItems(); i++)
00551     {
00552         y2 = 1;
00553         
00554         // Draw a column
00555         
00556         for (j = 0; j < FFRows[i].NumItems(); j++)
00557         {
00558             hq = (HierElem*) FFElts[i][j];
00559             y2 = 1 - 2 * GCLReal(eltParents[j]) / GCLReal(patches.NumItems());
00560 
00561             wy = 2.0 / GCLReal(patches.NumItems());
00562             m = GCLReal(1 << (2 * hq->level));
00563             wy /= m;
00564     
00565             y2 -= GCLReal(hq->treeCode) * wy;   
00566             y1 = y2 - wy;
00567         
00568             if (hq->highlight == 2 && patches[i]->highlight == 3)
00569                 r.C(cPurple);
00570             else if (hq->highlight == 2)
00571                 r.C(cYellow);
00572             else if (patches[i]->highlight == 3)
00573                 r.C(cGreen);
00574             else    
00575                 r.C(FFRows.NumItems() * FFRows[i][j]);
00576 
00577             PaintRect(r, Coord(x1, y1), Coord(x2, y2)); 
00578 
00579             y2 = y1;
00580         }
00581         
00582         x1 += wx;
00583         x2 += wx;
00584     }
00585 #endif
00586 }
00587 
00588 RadElem *HProgRad::NewMesh()
00589 {
00590     if (gRadControl->noGridMesh)
00591         return(new HierElem());
00592     else
00593         return(new HierGrid());
00594 }
00595 
00596 Void HProgRad::ColourVertices()
00597 {
00598     Int     i;
00599 
00600     for (i = 0; i < elements.NumItems(); i++)
00601         ((HierElem*) elements[i])->CorrectLeaves();
00602 
00603     RadMethod::ColourVertices();
00604 }
00605 
00606 PatchList *HProgRad::GetElements()
00607 {
00608     Int             i, j, n, numElems, numSplitElems = 0;
00609     HierElemPtr     subElems[5];
00610     
00611     // Make the mesh compliant, if it's been tesselated.
00612 
00613     ColourVertices();
00614 
00615     if (gRadControl->anchor)
00616     {
00617         n = elements.NumItems();
00618         for (i = 0; i < n; i++)
00619         {
00620             ((HierElemPtr) elements[i])->SplitElement(numElems, subElems);
00621 
00622             if (numElems > 0)
00623             {
00624                 numSplitElems++;
00625 
00626                 
00627                 elements[i] = subElems[0];
00628                 for (j = 1; j < numElems; j++)
00629                     elements.Append(subElems[j]);
00630             }
00631         }
00632 
00633     }
00634 
00635     return(&elements);
00636 }
00637 
00638 Void HProgRad::DumpMemoryUse()
00639 {
00640     Float   propmem, bmem, bpmem, pmem, emem, semem, epmem, total;
00641     Float   ptmem, clrmem, rtmem;
00642     Int     i;
00643     Char    *fmt = "%+10s %10.1f\n";
00644     
00645     propmem = sizeof(RadProps) * numProps / 1024.0;
00646     ptmem = sizeof(Point) * points->NumItems() / 1024.0;
00647     clrmem = sizeof(Colour) * colours->NumItems() / 1024.0;
00648 
00649     bmem = sizeof(RadElem*) * baseElems.NumItems() / 1024.0;
00650     bpmem = 0;
00651     RadElem::sGridMem = 0;
00652     RadElem::sGridChildMem = 0;
00653     for (i = 0; i < baseElems.NumItems(); i++)
00654         bpmem += baseElems[i]->MemoryUse();
00655     bpmem /= 1024.0;
00656     
00657     pmem = sizeof(RadElem*) * patches.NumItems() / 1024.0;
00658     emem = sizeof(RadElem*) * elements.NumItems() / 1024.0;
00659     epmem = sizeof(Int) * eltParents.NumItems() / 1024.0;
00660     rtmem = grid->MemoryUsage();
00661     
00662     printf(fmt, "propmem", propmem);
00663     printf(fmt, "points", ptmem);
00664     printf(fmt, "colours", clrmem);
00665     printf(fmt, "bmem", bmem);
00666     printf(fmt, "bpmem", bpmem);
00667     printf(fmt, "  grid", RadElem::sGridMem / 1024.0);
00668     printf(fmt, "  gridCh", RadElem::sGridChildMem / 1024.0);
00669     printf(fmt, "pmem", pmem);
00670     printf(fmt, "emem", emem);
00671     printf(fmt, "semem", semem);
00672     printf(fmt, "epmem", epmem);
00673     printf(fmt, "rtmem", rtmem);
00674 
00675     total = propmem + bmem + bpmem + pmem + emem + semem + epmem
00676          + clrmem + ptmem + rtmem;
00677 
00678     printf(fmt, "total", total);
00679     grid->DumpMemoryUsage();
00680 }

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