00001 /*
00002 File: ProgRad.cc
00003
00004 Function: See header file
00005
00006 Author: Andrew Willmott
00007
00008 Notes:
00009 */
00010
00011 #include "ProgRad.h"
00012 #include "gcl/Draw.h"
00013
00027 Void ProgRad::MakeFormFactorFromVector(RadElem &fromPatch,
00028 PatchList &patches, ColourList &result)
00029 // Find the vector of patch factors from patch j.
00030 // The factors are weighted by the reflectance of the patch they are to.
00031 {
00032 Int i, k;
00033 GCLReal visibility;
00034 GCLReal factor;
00035 RadElem *curPatch;
00036
00037 result.SetSize(patches.NumItems());
00038
00039 #ifdef RAD_VIS
00040 if (gRadControl->showRays)
00041 display->Clear().Draw(GetScene());
00042 #endif
00043
00044 for (i = 0; i < patches.NumItems(); i++)
00045 {
00046 GCLReal rho;
00047
00048 curPatch = patches[i];
00049
00050 rho = len(curPatch->Reflectance());
00051
00052 if (rho < 0.0001)
00053 {
00054 result[i] = vl_0;
00055 continue;
00056 }
00057
00058 factor = fromPatch.EstFormFactor(curPatch);
00059 #ifdef RAD_SPEEDY
00060 if (rho * factor < 1e-5)
00061 {
00062 result[i] = vl_0;
00063 continue;
00064 }
00065 #endif
00066
00067 visibility = fromPatch.Visibility(curPatch);
00068
00069 if (visibility > 0.0001)
00070 {
00071 result[i] = curPatch->Reflectance();
00072 result[i] *= factor * visibility;
00073 }
00074 else
00075 result[i] = vl_0;
00076 }
00077
00078 #ifdef RAD_VIS
00079 if (gRadControl->showRays)
00080 display->Show();
00081 #endif
00082 }
00083
00084 Bool ProgRad::Render()
00085 // Returns true if no interruptions.
00086 {
00087 Int numPatches = patches.NumItems();
00088 Int i, j;
00089
00090 Colour deltaRad;
00091 Colour radToShoot;
00092 GCLReal power, envArea;
00093 Colour envPower, envRefl;
00094 Bool finished = 0;
00095
00096 RadMethod::Render();
00097
00098 iterations = 0;
00099 error = 1.0;
00100 origShoot = 0;
00101
00102 B.SetSize(numPatches);
00103 S.SetSize(numPatches);
00104
00105 envRad = vl_1;
00106
00107 if (Stage(1)) return(0);
00108
00109 for (i = 0; i < patches.NumItems(); i++)
00110 S[i] = patches[i]->Emittance();
00111
00112 B = S;
00113
00114 // Setup for the ambient term
00115
00116 envRefl.MakeZero();
00117 envArea = 0;
00118
00119 for (i = 0; i < numPatches; i++)
00120 {
00121 envRefl += patches[i]->area * patches[i]->Reflectance();
00122 envArea += patches[i]->area;
00123 }
00124
00125 envRefl /= Colour(vl_1) / (Colour(vl_1) - envRefl / envArea);
00126 // R = 1 / (1 - avgReflectance)
00127
00128 // Now, run the algorithm...
00129
00130 while (!finished)
00131 {
00132 if (Stage(2)) return(0);
00133
00134 iterations++;
00135
00136 maxPower = 0;
00137 maxPowerIndex = 0;
00138 envPower.MakeZero();
00139
00140 for (i = 0; i < numPatches; i++)
00141 {
00142 power = dot(S[i] * patches[i]->area, kRadRGBToLum);
00143
00144 if (maxPower < power)
00145 {
00146 maxPower = power;
00147 maxPowerIndex = i;
00148 }
00149 }
00150
00151 if (Idle())
00152 return(0);
00153
00154 if (Stage(3)) return(0);
00155
00156 radToShoot = S[maxPowerIndex];
00157 radToShoot *= gRadControl->alpha;
00158 S[maxPowerIndex] -= radToShoot;
00159
00160 if (Stage(4)) return(0);
00161
00162 #ifdef RAD_VIS
00163 if (gRadControl->drawMatrix)
00164 MakeFormFactorFromVector(*patches[maxPowerIndex], patches,
00165 FFRows[maxPowerIndex]);
00166 else
00167 #else
00168 MakeFormFactorFromVector(*patches[maxPowerIndex], patches, FFRow);
00169 #endif
00170
00171 if (Stage(5)) return(0);
00172
00173 error = 0;
00174 envPower.MakeZero();
00175
00176 for (i = 0; i < numPatches; i++)
00177 {
00178 #ifdef RAD_VIS
00179 if (gRadControl->drawMatrix)
00180 deltaRad = FFRows[maxPowerIndex][i] * radToShoot;
00181 else
00182 #endif
00183 deltaRad = FFRow[i] * radToShoot;
00184 B[i] += deltaRad;
00185 S[i] += deltaRad;
00186 error += sqrlen(deltaRad);
00187
00188 envPower += S[i] * patches[i]->area;
00189 }
00190
00191 if (gRadControl->ambient)
00192 envRad = envRefl * envPower / envArea;
00193 else
00194 envRad.MakeZero();
00195
00196 error = sqrt(error);
00197
00198 if (iterations == 1)
00199 origShoot = maxPower;
00200 else if (maxPower < gRadControl->error * origShoot)
00201 finished = 1;
00202
00203 if (Stage(6)) return(0);
00204 }
00205
00206 if (Stage(7)) return(0);
00207
00208 return(1);
00209 }
00210
00211 #ifdef RAD_VIS
00212
00213 Void ProgRad::DumpStats(){}
00214
00215 Int ProgRad::Stage(Int stage)
00216 {
00217 Int i, j;
00218 Bool animate = gRadControl->animate || gRadControl->pause;
00219
00220 switch (stage)
00221 {
00222 case 1: // pre setup
00223 Field(out3) << patches.NumItems() << " patches" << show;
00224 Field(out1) << "Forming emission vector E..." << show;
00225 FFRows.Clear();
00226 if (gRadControl->drawMatrix)
00227 {
00228 FFRows.SetSize(patches.NumItems());
00229 // FFRows.ClearTo(ColourList());
00230 }
00231 StartUpdate();
00232 break;
00233 case 2: // post setup
00234 ColourVertices();
00235 display->Redraw();
00236
00237 doUpdate = animate || Update();
00238
00239 if (animate)
00240 Field(out1) << "Finding patch to shoot..." << show;
00241 else if (doUpdate)
00242 {
00243 Char *plural;
00244
00245 if (iterations == 1)
00246 plural = "";
00247 else
00248 plural = "es";
00249
00250 Field(out1) << iterations << " patch" << plural << " shot" << show;
00251
00252 RenderMatrix();
00253 }
00254 break;
00255
00256 case 3:
00257 if (animate)
00258 Field(out1) << "Patch " << maxPowerIndex << " next to shoot"
00259 << show;
00260 break;
00261
00262 case 4: // After patch setup
00263 if (doUpdate)
00264 {
00265 if (animate)
00266 {
00267 Field(out1) << "Calculating form factors..." << show;
00268 // flash shooting patch red
00269 patches[maxPowerIndex]->SetHighlight(1);
00270 }
00271
00272 ColourVertices();
00273
00274 display->Redraw();
00275 patches[maxPowerIndex]->SetHighlight(0);
00276 }
00277 break;
00278
00279 case 5:
00280 // Update our display matrix...
00281 if (doUpdate)
00282 {
00283 RenderMatrix();
00284 if (animate)
00285 Field(out1) << "Shooting Patch " << maxPowerIndex << show;
00286 }
00287 break;
00288
00289 case 6: // Middle of solve loop.
00290
00291 if (doUpdate)
00292 {
00293 // Colour the patches...
00294 for (i = 0; i < patches.NumItems(); i++)
00295 {
00296 // Show the shot vector or the radiosity vector?
00297
00298 if (gRadControl->shotDisplay)
00299 patches[i]->colour = S[i];
00300 else
00301 patches[i]->colour = B[i] + patches[i]->Reflectance()
00302 * envRad;
00303 }
00304
00305 ColourVertices();
00306 display->Redraw();
00307
00308 Field(out2) << "error = " << maxPower / origShoot
00309 << ", RMS Error = " << error << show;
00310 UpdateCont();
00311 }
00312 break;
00313
00314 case 7:
00315 // Colour the patches...
00316 for (i = 0; i < patches.NumItems(); i++)
00317 if (gRadControl->shotDisplay)
00318 patches[i]->colour = S[i];
00319 else
00320 patches[i]->colour = B[i] + patches[i]->Reflectance() * envRad;
00321
00322 ColourVertices();
00323 display->Redraw();
00324
00325 Field(out2) << "error = " << maxPower / origShoot << ", RMS Error = "
00326 << error << show;
00327 Field(out1) << "Finished: " << iterations << " patches shot" << show;
00328 break;
00329 }
00330 return(Pause());
00331 }
00332
00333 #else
00334
00335 Void ProgRad::DumpStats()
00336 {
00337 Int i;
00338 GCLReal shotErr, mem;
00339
00340 if (origShoot == 0.0)
00341 shotErr = 1.0;
00342 else
00343 shotErr = maxPower / origShoot;
00344
00345 mem = sizeof(Colour) * (B.NumItems() + S.NumItems() + FFRow.NumItems());
00346 mem /= 1024.0;
00347
00348 cout << dumpID
00349 << ' ' << totTime
00350 << ' ' << gRadControl->stage
00351 << ' ' << patches.NumItems()
00352 << ' ' << shotErr
00353 << ' ' << error
00354 << ' ' << gRadControl->rays
00355 << ' ' << iterations
00356 << ' ' << mem
00357 << ' ' << grid->MemoryUsage()
00358 << ' ' << TotalMemoryUse()
00359 << endl;
00360
00361 for (i = 0; i < patches.NumItems(); i++) // Colour the patches...
00362 {
00363 // Show the shot vector or the radiosity vector?
00364
00365 if (gRadControl->shotDisplay)
00366 patches[i]->colour = S[i];
00367 else
00368 patches[i]->colour = B[i] + patches[i]->Reflectance() * envRad;
00369 }
00370
00371 DumpScene();
00372 }
00373
00374 Int ProgRad::Stage(Int stage)
00375 {
00376 if (CheckTime()) return(1);
00377
00378 gRadControl->stage = stage;
00379
00380 switch (stage)
00381 {
00382 case 1: // pre setup
00383 cout << "method prog " << endl;
00384 cout << "sub " << gRadControl->patchSubdivs << endl;
00385 cout << "tErr " << gRadControl->error << endl;
00386 cout << "scene " << sceneName << endl;
00387 cout << "polys " << gRadControl->numPolys << endl;
00388 cout << "srcPatches " << patches.NumItems() << endl;
00389 cout << "format "
00390 << "ID "
00391 << "time "
00392 << "stage "
00393 << "patches "
00394 << "shootErr "
00395 << "resErr "
00396 << "rays "
00397 << "iterations "
00398 << "mem "
00399 << "rtMem "
00400 << "rss "
00401 << endl;
00402
00403 cout << "----------------------------------------------"
00404 << "---------------------------------" << endl;
00405
00406 DumpStats();
00407 break;
00408
00409 case 7:
00410 DumpStats();
00411 break;
00412 }
00413
00414 if (Idle()) return(0);
00415 timer.ContTimer();
00416 return(0);
00417 }
00418
00419 #endif
00420
00421 Void ProgRad::DrawMatrix(Renderer &r)
00422 {
00423 if (!gRadControl->drawMatrix || gRadControl->stop)
00424 return;
00425
00426 #ifdef RAD_VIS
00427 Int i, j;
00428 GCLReal x1, x2, y1, y2, wx, wy;
00429
00430 wx = 2.0 / FFRows.NumItems();
00431
00432 x1 = -1;
00433 x2 = wx - 1;
00434
00435 for (i = 0; i < FFRows.NumItems(); i++)
00436 {
00437 wy = 2.0 / FFRows[i].NumItems();
00438 y1 = 1 - wy;
00439 y2 = 1;
00440
00441 for (j = 0; j < FFRows[i].NumItems(); j++)
00442 {
00443 if (patches[j]->highlight == 2 && patches[i]->highlight == 3)
00444 r.C(cPurple);
00445 else if (patches[j]->highlight == 2)
00446 r.C(cYellow);
00447 else if (patches[i]->highlight == 3)
00448 r.C(cGreen);
00449 else
00450 r.SetColour(FFRows.NumItems() * FFRows[i][j]);
00451 PaintRect(r, Coord(x1, y1), Coord(x2, y2));
00452
00453 y1 -= wy;
00454 y2 -= wy;
00455 }
00456
00457 x1 += wx;
00458 x2 += wx;
00459 }
00460 #endif
00461 }
00462
00463
00464 RadElem *ProgRad::NewMesh()
00465 {
00466 return(new RadGrid());
00467 }