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 }