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 }