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

HRElem.cc

Go to the documentation of this file.
00001 /*
00002     File:       HRElem.cc
00003 
00004     Function:   Defines the element type used by the various hierarchical
00005                 radiosity methods.
00006 
00007     Author:     Andrew Willmott
00008 
00009     Notes:      
00010 */
00011 
00012 #include "HRElem.h"
00013 #include "RadMethod.h"
00014 #include "gcl/SceneLang.h"
00015 #include "gcl/GLRenderer.h"
00016 
00017 #ifdef RAD_VIS
00018 #include "gcl/ScenePane.h"
00019 #endif
00020 
00021 // --- HRElem methods ---------------------------------------------------------
00022 
00023 UInt32 HRElem::gID = 0;
00024 
00025 HRElem::HRElem() :
00026 #ifdef RAD_VIS
00027     eltParent(0),
00028     eltHighlight(0),
00029 #endif
00030     id(gID++),
00031     flags()
00032 {
00033 }   
00034 
00035 HRElem::~HRElem()
00036 {
00037     Reset();
00038 }
00039 
00040 Void HRElem::Reset()
00041 {
00042     links.Free();
00043 }
00044 
00045 Void HRElem::DrawElem(Renderer &r)
00046 {
00047     DrawNodeElem(r);
00048 }
00049 
00050 // XXX shift?
00051 
00052 Void DrawArrow(Renderer &r, Point start, Point end)
00053 {
00054     static scPrimitive  *sCone = 0;
00055     static scPrimitive  *sShaft = 0;
00056     const Double        ac = 0.1;
00057     const Double        as = ac / 5.0;
00058 
00059     GCLReal             al = len(end - start);
00060     GLRenderer          &glr = (GLRenderer &) r;
00061     Transform           trans;
00062     
00063     if (al < 1e-15)
00064         return;
00065 
00066     if (!sCone)
00067     {
00068         sCone = slGetLibrary()->Member("cone");
00069         sShaft = slGetLibrary()->Member("cylinder");
00070     }
00071     
00072     glr.SetHeadlight(true);
00073 
00074 #ifdef OFF
00075     r.C(cYellow).Begin(renLines);
00076     r.P(start).P(end);
00077     r.End();
00078 #endif
00079 
00080     r.C(cWhite);
00081     r.Push();
00082     trans = Shift(end) * AlignToDir(end - start);
00083     r.SetTransform(trans);
00084 
00085     r.Push();
00086     trans = Shift(-ac * Vector(vl_y)) * Scale(Vector(as, al - ac, as)) * Shift(-0.5 * Vector(vl_y));
00087     r.SetTransform(trans);
00088     sShaft->Draw(r);
00089     r.Pop();
00090 
00091     r.Push();
00092     trans = Scalef(ac) * Shift(-Vector(vl_y));
00093     r.SetTransform(trans);
00094     sCone->Draw(r);
00095     r.Pop();
00096     
00097     r.Pop();
00098     glr.SetHeadlight(false);
00099 }
00100 
00101 Void HRElem::DrawContributors(Renderer &r)
00102 {
00103     HRLinkIter iter;
00104 
00105     for (iter.Begin(links); !iter.AtEnd(); iter.Inc())
00106         DrawArrow(r, iter.Data().from->EltCentre(), iter.Data().to->EltCentre());
00107 
00108     for (iter.Begin(links); !iter.AtEnd(); iter.Inc())
00109     {
00110         iter.Data().from->DrawLeafElem(r);
00111         iter.Data().from->flags.Set(hrMark);
00112     }
00113 }
00114 
00115 Void HRElem::DrawContributorsRec(Void *r)
00116 {
00117     Int i;
00118     
00119     DrawContributors(*(Renderer*) r);
00120     ApplyToChildren(&HRElem::DrawContributorsRec, r);
00121 }
00122 
00123 Void HRElem::DrawMatrix(Renderer &r, Int baseNum)
00124 {
00125     DMInfo  info;
00126 
00127     info.r = &r;
00128     info.baseNum = baseNum;
00129     DrawMatrixRec(&info);
00130 }
00131 
00132 Void HRElem::DrawMatrixRec(Void *dmi)
00133 {
00134 }
00135 
00136 Void HRElem::DistributeColours()
00137 {
00138 }
00139 
00140 Void HRElem::DistributeColoursBest(ShadeInfo &shadeInfo)
00141 {
00142 }
00143 
00144 // --- Link Refinement --------------------------------------------------------
00145 
00146 //#define RAD_VIS_LINKS
00147 // doesn't seem to have turned out to be all that useful?
00148 
00149 Bool HRElem::RefineLink(HRLink *link, Int levels)
00152 {
00153     Int         i, j, which;
00154     GCLReal     factor, visibility;
00155 
00156     // CreateSubLink() returns null if the link carries no energy, so
00157     // return if that's the case.
00158     if (link == 0)
00159         return(false);
00160 
00161     if (levels-- == 0)
00162     {
00163         links.Prepend(link);
00164         return(false);
00165     }
00166     
00167     which = link->RefineOracle();
00168     
00169 #ifdef RAD_VIS_LINKS
00170     if (gRadControl->showLinks)
00171     {
00172         RM_DISPLAY_START;
00173         gRadControl->radObject->display->Begin(renLines);
00174     }
00175 #endif
00176         
00177     if (which == kSubNone)          // Form link here.
00178     {
00179         links.Prepend(link);
00180         
00181 #ifdef RAD_VIS_LINKS
00182         if (gRadControl->showLinks)
00183         {
00184             gRadControl->radObject->display->
00185                 C(cRed).P(EltCentre()).P(link->from->EltCentre()).End();
00186             RM_DISPLAY_END;
00187             RM_OUT1("Forming link here.");
00188             if (RM_PAUSE) return(false);
00189         }
00190 #endif
00191         return(false);
00192     }
00193     else if (which == kSubTo)       // Subdivide 'to' patch (this one!)
00194     {
00195 #ifdef RAD_VIS_LINKS
00196         if (gRadControl->showLinks)
00197         {
00198             gRadControl->radObject->display->
00199                 C(cGreen).P(EltCentre()).P(link->from->EltCentre());
00200             RM_DISPLAY_END;
00201             RM_OUT1("Pushing link down to children of receiver");
00202             if (RM_PAUSE) return(false);
00203         }
00204 #endif      
00205         MakeChildLinks(link->from, link, which, levels);
00206     }
00207     else if (which == kSubFrom)     // Subdivide 'from' patch
00208     {
00209 #ifdef RAD_VIS_LINKS
00210         if (gRadControl->showLinks)
00211         {
00212             gRadControl->radObject->display->
00213                 C(cBlue).P(EltCentre()).P(link->from->EltCentre()).End();
00214             RM_DISPLAY_END;
00215             RM_OUT1("Pushing link down to children of source");
00216             if (RM_PAUSE) return(false);
00217         }
00218 #endif
00219         link->from->MakeChildLinks(this, link, which, levels);
00220     }       
00221     else if (which == kSubBoth)     // Subdivide both patches
00222     {
00223 #ifdef RAD_VIS_LINKS
00224         if (gRadControl->showLinks)
00225         {
00226             gRadControl->radObject->display->
00227                 C(cYellow).P(EltCentre()).P(link->from->EltCentre()).End();
00228             RM_DISPLAY_END;
00229             RM_OUT1("Pushing link down to children of source & dest");
00230             if (RM_PAUSE) return(false);
00231         }
00232 #endif
00233         MakeChildLinks(link->from, link, which, levels);
00234     }       
00235 
00236     link->FreeLink(link);
00237 
00238     return(true);
00239 }
00240 
00241 Bool HRElem::Refine()
00244 {
00245     Bool result = false;
00246     RefineFurther(&result);
00247     return(result);
00248 }
00249 
00250 Void HRElem::RefineFurther(Void *result)
00251 {
00252     HRLinkIter  i;
00253     Int         j, which;
00254     Bool        split;
00255     HRLinkList  oldLinks;
00256     HRLink      *tempLink, *rlink;
00257     
00258     // bottom-up traversal to avoid refining a link more than once.
00259     ApplyToChildren(&HRElem::RefineFurther, result);
00260     
00261     rlink = (HRLink*) links.first;
00262     links.first = 0;
00263 
00264     // Step through links, see whether any should be pushed down the hierarchy.
00265     while (rlink)
00266     {
00267         tempLink = rlink;
00268         rlink = (HRLink*) rlink->next;
00269         if (RefineLink(tempLink, gRadControl->refineLevels))
00270             *(Bool*) result = true;
00271     }
00272 }
00273 
00274 Void HRStats::Init()
00275 {
00276     numLinks = 0;
00277     numPatches = 0;
00278     numVolClusters = 0;
00279     numFaceClusters = 0;
00280     numAliens = 0;
00281 }
00282 
00283 Void HRElem::CalcStats(Void *statsIn)
00284 {
00285     HRLinkIter  i;
00286     HRStats     *stats = (HRStats*) statsIn;
00287 
00288     for (i.Begin(links); !i.AtEnd(); i.Inc())
00289         stats->numLinks++;
00290     
00291     if (IsPatch())
00292         stats->numPatches++; 
00293     else if (IsCluster())
00294         stats->numVolClusters++;
00295     else if (IsFaceClus())
00296         stats->numFaceClusters++;
00297     else
00298         stats->numAliens++;
00299         
00300     ApplyToChildren(&HRElem::CalcStats, statsIn);
00301 }
00302 
00303 ostream *HRElem::out = &cout;
00304 
00305 Void HRElem::DumpHierarchy(Void *v)
00306 // dump the element hierarchy 
00307 {
00308     if (v)
00309     {
00310         // just printing a list of child IDs
00311         *out << id << ' ';
00312         return;
00313     }
00314 
00315     // dump from leaves to root
00316     ApplyToChildren(&HRElem::DumpHierarchy);    
00317 
00318     HRLinkIter i;
00319     // elt. format: e ID [childID1 childID2...]
00320     *out << "e " << id << ' ';
00321     ApplyToChildren(&HRElem::DumpHierarchy, this);
00322     *out << endl;
00323     // link format: L toEltID fromEltID transferCoeff
00324     for (i.Begin(links); !i.AtEnd(); i.Inc())
00325         *out << "L " << id << " " << i.Data().from->id 
00326             << ' ' << i.Data().Strength() << endl;
00327 }
00328 
00329 Void HRElem::Gather()
00330 {
00331     HRLinkIter i;
00332     
00333     ClearR();
00334 
00335     for (i.Begin(links); !i.AtEnd(); i.Inc())
00336     {
00337         i.Data().Gather();
00338         
00339 #ifdef RAD_VIS_LINKS
00340         // YYY replace with arrow sometime?
00341         if (gRadControl->showLinks)
00342             gRadControl->radObject->display->Begin(renLines)
00343                 .C(cRed).P(EltCentre()).P(i.Data().from->EltCentre())
00344                 .End();
00345 #endif
00346     }
00347 }
00348 
00349 Void HRElem::GatherAll(Void *)
00350 {
00351     ApplyToChildren(&HRElem::GatherAll);
00352     Gather();    // Gather radiosity across all links to this patch into R
00353 }
00354 
00355 #ifdef RAD_VIS
00356 
00357 Void HRElem::PushPull(Void *)
00358 {
00359     Int     i;
00360                 
00361     if (gRadControl->animate)
00362     {
00363         SetHighlight(0);
00364         if (RM_PAUSE) return;
00365     }
00366     
00367     Add();
00368 
00369     if (gRadControl->animate)
00370         RM_DISPLAY_SCENE;
00371 
00372     if (!IsLeaf())
00373     {
00374         if (gRadControl->animate)
00375         {
00376             if (RM_PAUSE) return;
00377         }
00378                 
00379         Push();
00380         
00381         ApplyToChildren(&HRElem::PushPull);
00382         
00383         if (gRadControl->animate)
00384         {
00385             SetHighlight(1);
00386             SetHighlight(0);
00387 
00388             if (RM_PAUSE) return;
00389         }
00390 
00391         Pull();
00392 
00393         if (gRadControl->animate)
00394             RM_DISPLAY_SCENE;
00395     }
00396     else
00397         CalcLeafRadiosity();
00398 }
00399 
00400 #else
00401 
00402 Void HRElem::PushPull(Void *)
00403 {
00404     Int     i;
00405             
00406     // Add R in to B: accumulated radiosity from this and higher levels
00407     Add();       
00408     
00409     if (!IsLeaf())
00410     {               
00411         // Push B down to children's B's
00412         Push();  
00413         // recurse
00414         ApplyToChildren(&HRElem::PushPull);
00415         // Pull radiosity back up
00416         Pull();
00417     }
00418     else
00419         CalcLeafRadiosity();
00420 }
00421 #endif
00422 
00423 GCLReal HRElem::EltVisToPoint(Point &p)
00424 {
00425     Int         i, misses;
00426     Point       srcPoint[16];
00427     Bool        hit;
00428 
00429     if (gRadControl->visibility == vis_none)
00430         return(1.0);
00431             
00432     misses = 0;
00433     EltSetVisPoints(0, srcPoint);
00434     
00435 #ifdef RAD_VIS
00436     if (gRadControl->showRays)
00437         RM_DISPLAY_START;
00438 #endif
00439 
00440     gRadControl->rays += 16;
00441     
00442     for (i = 0; i < 16; i++)
00443     {
00444         hit = gRadControl->radObject->IntersectsWithRay(srcPoint[i], p);
00445         
00446         if (hit)
00447             misses++;
00448 
00449 #ifdef RAD_VIS
00450         if (gRadControl->showRays)
00451         {
00452             if (hit)
00453                 gRadControl->radObject->display->Begin(renLines).C(cRed).P(srcPoint[i]).
00454                     P(p).End();
00455             else
00456                 gRadControl->radObject->display->Begin(renLines).C(cGreen).P(srcPoint[i]).
00457                     P(p).End();
00458         }
00459 #endif
00460     }
00461         
00462 #ifdef RAD_VIS
00463     if (gRadControl->showRays)
00464     {
00465         RM_DISPLAY_END;
00466         RM_OUT1("Visibility: " << GCLReal(16 - misses) * 1.0 / 16.0);
00467         if (RM_PAUSE) return(0);
00468     }
00469 #endif
00470         
00471     return((16 - misses) * (1.0 / 16.0));
00472 }
00473 
00474 GCLReal HRElem::EltVis(HRElem *to)
00475 {
00476     Int         i, misses;
00477     Point       srcPoint[16], dstPoint[16];
00478     Bool        hit;
00479 
00480     if (gRadControl->visibility == vis_none || to == this)
00481         return(1.0);
00482             
00483     misses = 0;
00484     EltSetVisPoints(to, srcPoint);
00485     to->EltSetVisPoints(this, dstPoint);
00486     
00487 #ifdef RAD_VIS
00488     if (gRadControl->showRays)
00489         RM_DISPLAY_START;
00490 #endif
00491 
00492     gRadControl->rays += 16;
00493     
00494     for (i = 0; i < 16; i++)
00495     {
00496         hit = gRadControl->radObject->IntersectsWithRay(srcPoint[i], dstPoint[i]);
00497         
00498         if (hit)
00499             misses++;
00500 
00501 #ifdef RAD_VIS
00502         if (gRadControl->showRays)
00503         {
00504             if (hit)
00505                 gRadControl->radObject->display->Begin(renLines).C(cRed).P(srcPoint[i]).
00506                     P(dstPoint[i]).End();
00507             else
00508                 gRadControl->radObject->display->Begin(renLines).C(cGreen).P(srcPoint[i]).
00509                     P(dstPoint[i]).End();
00510         }
00511 #endif
00512     }
00513         
00514 #ifdef RAD_VIS
00515     if (gRadControl->showRays)
00516     {
00517         RM_DISPLAY_END;
00518         RM_OUT1("Visibility: " << GCLReal(16 - misses) * 1.0 / 16.0);
00519         if (RM_PAUSE) return(0);
00520     }
00521 #endif
00522         
00523     return((16 - misses) * (1.0 / 16.0));
00524 }
00525 
00526 Colour HRElem::EltBA()
00528 {
00529     return(B_Coeffs()[0] * EltArea());
00530 }
00531 
00532 Void HRElem::InitRad()
00533 {
00534     ClearB();
00535     CalcLeafRadiosity();
00536 }
00537 
00538 Void HRElem::AddChanIrradiance(const Colour &E, Int chan)
00539 {
00540     Colour  c(vl_0);
00541     Vector  m;
00542 
00543     c[chan] = 1.0;
00544     ConvertVec(E, m);
00545 
00546     AddIrradiance(c, m);
00547 }
00548 
00549 GCLReal HRElem::EltMaxProjArea(const Vector &v)
00550 {
00551     return(EltProjArea(v));
00552 }
00553 
00554 Void HRElem::DebugInfo()
00555 {
00556     HRLinkIter i;
00557 
00558     cout << "radiosity = " << B_Coeffs()[0] << endl;
00559     cout << "rho = " << EltRho() << endl;
00560     cout << "flags = " << flags << endl;
00561     for (i.Begin(links); !i.AtEnd(); i.Inc())
00562         i.Data().DebugInfo();
00563 }
00564 
00565 
00566 GCLReal VecError(const SubVecd &v)
00567 {
00568     GCLReal     min, max;
00569     Int         i;
00570 
00571     if (v[0] < v[1])
00572     {
00573         min = v[0];
00574         max = v[1];
00575     }
00576     else
00577     {
00578         min = v[1];
00579         max = v[0];
00580     }
00581 
00582     for (i = 2; i < v.Elts(); i++)
00583         if (v[i] < min)
00584             min = v[i];
00585         else if (v[i] > max)
00586             max = v[i];
00587 
00588     return(max - min);
00589 }
00590 
00591 
00592 ShadeInfo::ShadeInfo() : linkStack(), level(0), data(0)
00593 {
00594 }
00595 

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