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 }