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