00001 /*
00002 File: MatRad.cc
00003
00004 Function: See header file
00005
00006 Author(s): Andrew Willmott
00007
00008 Copyright: (c) 1997-2000, Andrew Willmott
00009
00010 Notes:
00011
00012 */
00013
00014 #include "MatRad.h"
00015 #include "cl/Timer.h"
00016 #include "gcl/Draw.h"
00017 #include <fstream.h>
00018 #include <stdio.h>
00019
00020 Matd MatRad::EmissionVectors(PatchList &patches)
00021 {
00022 Matd result(3, patches.NumItems());
00023 Int i, j;
00024
00025 for (i = 0; i < patches.NumItems(); i++)
00026 for (j = 0; j < 3; j++)
00027 result[j][i] = patches[i]->Emittance()[j];
00028
00029 return(result);
00030 }
00031
00032 SparseVecd MatRad::FormFactorToVector(Int j, PatchList &patches)
00033 // Find the vector of patch factors to patch j
00034 {
00035 const GCLReal epsilon = 1e-6;
00036 SparseVecd result(patches.NumItems());
00037 Int i;
00038 GCLReal vis;
00039
00040 #ifdef RAD_VIS
00041 if (gRadControl->showRays && gRadControl->visibility == vis_1)
00042 display->Clear().Draw(GetScene());
00043 #endif
00044
00045 if (len(patches[j]->Reflectance()) <= 1e-6)
00046 result.MakeUnit(j);
00047 else
00048 {
00049 result.Begin();
00050 for (i = 0; i < patches.NumItems(); i++)
00051 if (i != j)
00052 {
00053 vis = patches[i]->Visibility(patches[j]);
00054
00055 if (vis > 0.0)
00056 result.AddElt(i, patches[i]->EstFormFactor(patches[j])
00057 * vis);
00058 }
00059 result.End();
00060 }
00061
00062 #ifdef RAD_VIS
00063 if (gRadControl->showRays && gRadControl->visibility == vis_1)
00064 {
00065 display->Show();
00066 Pause();
00067 }
00068 #endif
00069
00070 return(result);
00071 }
00072
00073 Bool MatRad::Render()
00074 // Returns true if no interruptions.
00075 {
00076 Int i, j;
00077 Vec3d error;
00078 Int numPolys = patches.NumItems();
00079 Colour c;
00080
00081 RadMethod::Render();
00082 SparseVecd::SetFuzz(1e-10);
00083
00084 SparseVecd FFRow(numPolys); // Row of form factors
00085
00086 for (i = 0; i < 3; i++)
00087 A[i].SetSize(numPolys, numPolys);
00088
00089 E.SetSize(3, numPolys);
00090 B.SetSize(3, numPolys);
00091
00092 numPatches = 0;
00093
00094 // Flat colour scene according to current reflectances
00095 ColourMeshInitial();
00096
00097 if (Stage(1)) return(0);
00098
00099 E = EmissionVectors(patches);
00100
00101 if (Stage(2)) return(0);
00102
00103 // Initialise A's to unit matrices
00104 for (j = 0; j < 3; j++)
00105 A[j] = vl_I;
00106
00107 if (Stage(3)) return(0);
00108
00109 // Calculate solution matrices
00110 for (i = 0; i < patches.NumItems(); i++)
00111 {
00112 numPatches++;
00113 // find form factors to this patch
00114 FFRow = FormFactorToVector(i, patches);
00115
00116 for (j = 0; j < 3; j++)
00117 {
00118 A[j][i] -= FFRow * patches[i]->Reflectance()[j];
00119
00120 c[j] = patches[i]->Emittance()[j] +
00121 patches[i]->Reflectance()[j] * dot(FFRow, E[j]);
00122 }
00123 patches[i]->SetColour(c);
00124
00125 if (Stage(4)) return(0);
00126 }
00127
00128 if (Stage(5)) return(0);
00129
00130 error = vl_1;
00131
00132 while (len(error) > 0.001)
00133 {
00134 if (!gRadControl->useConjGrad)
00135 {
00136 for (i = 0; i < 3; i++) // Solve one more iteration
00137 error[i] = SolveOverRelax(A[i], B[i], E[i], 1e-6,
00138 gRadControl->alpha);
00139 }
00140 else
00141 for (i = 0; i < 3; i++) // Solve one more iteration
00142 error[i] = SolveConjGrad(A[i], B[i], E[i], 1e-6);
00143
00144 if (Stage(6)) return(0);
00145 }
00146
00147 if (Stage(7)) return(0);
00148
00149 return(1);
00150 }
00151
00152 #ifdef RAD_VIS
00153
00154 Void MatRad::DumpStats() {}
00155
00156 Int MatRad::Stage(Int stage)
00157 {
00158 Bool animate = gRadControl->animate || gRadControl->pause;
00159 Int i, j;
00160 Colour c;
00161
00162 switch (stage)
00163 {
00164 case 1: // pre setup
00165 Field(out3) << patches.NumItems() << " patches." << show;
00166 Field(out1) << "Forming emission vector E..." << show;
00167 break;
00168
00169 case 2: // post setup
00170 Field(out1) << "Flat-colouring scene..." << show;
00171
00172 for (i = 0; i < patches.NumItems(); i++) // distribute colour
00173 {
00174 for (j = 0; j < 3; j++)
00175 c[j] = patches[i]->Reflectance()[j]
00176 * Max((double) 0.2, E[j][i]);
00177
00178 patches[i]->SetColour(c);
00179 }
00180
00181 ColourVertices();
00182 display->Redraw(); // draw
00183
00184 Field(out1) << "1. Initialise F matrices..." << show;
00185 break;
00186
00187 case 3:
00188 Field(out1) << "2. Calculate F matrices..." << show;
00189 StartUpdate();
00190 break;
00191
00192 case 4: // After patch setup
00193 doUpdate = animate || Update();
00194
00195 if (doUpdate)
00196 {
00197 if (gRadControl->animate && numPatches < patches.NumItems())
00198 patches[numPatches]->SetHighlight(1);
00199 ColourVertices();
00200 display->Redraw();
00201 if (gRadControl->animate && numPatches < patches.NumItems())
00202 patches[numPatches]->SetHighlight(0);
00203
00204 RenderMatrix();
00205 Field(out3) << numPatches << " / "
00206 << patches.NumItems() << " patches." << show;
00207
00208 UpdateCont();
00209 }
00210 break;
00211
00212 case 5: // After FF calculation
00213 ColourVertices();
00214 display->Redraw();
00215 RenderMatrix();
00216 Field(out1) << "3. Solve equations..." << show;
00217 StartUpdate();
00218 solverIterations = 0;
00219 break;
00220
00221 case 6: // Middle of solve loop.
00222 solverIterations++;
00223 if (animate || Update())
00224 {
00225 // Colour scene according to current B vector
00226 for (i = 0; i < patches.NumItems(); i++)
00227 {
00228 for (j = 0; j < 3; j++)
00229 c[j] = B[j][i];
00230
00231 patches[i]->SetColour(c);
00232 }
00233
00234 ColourVertices();
00235 display->Redraw(); // Draw!
00236 Field(out3) << solverIterations << " iterations" << show;
00237 UpdateCont();
00238 }
00239 break;
00240
00241 case 7:
00242 ColourVertices();
00243 display->Redraw();
00244
00245 Field(out3) << "Solving the matrix took "
00246 << solverIterations << " iterations" << show;
00247 Field(out1) << "Finished!" << show;
00248 break;
00249 }
00250
00251 if (Idle()) return(1);
00252
00253 return(Pause());
00254 }
00255
00256 #else
00257
00258 Void MatRad::DumpMatrix()
00259 {
00260 Int i, j, k;
00261 Char *rgb = "rgb";
00262 String temp;
00263 FILE *file;
00264
00265 for (k = 0; k < 3; k++)
00266 {
00267 temp.Printf("%s.%c.mlab", gRadControl->outFile, rgb[k]);
00268 file = fopen(temp, "w");
00269 fprintf(file, "[\n");
00270 for (i = 0; i < A[k].Rows(); i++)
00271 {
00272 for (j = 0; j < A[k].Cols() - 1; j++)
00273 fprintf(file, "%.18g, ", A[k][i][j]);
00274 fprintf(file, "%.18g\n", A[k][i][j]);
00275 }
00276
00277 fprintf(file, "]\n");
00278 fclose(file);
00279 }
00280
00281 temp.Printf("%s.stats", gRadControl->outFile);
00282 file = fopen(temp, "w");
00283 fprintf(file, "minArea %.18g\n", stats.minArea);
00284 fprintf(file, "maxArea %.18g\n", stats.maxArea);
00285 fprintf(file, "minRefl [%.18g %.18g %.18g]\n",
00286 stats.minRefl[0], stats.minRefl[1], stats.minRefl[2]);
00287 fprintf(file, "maxRefl [%.18g %.18g %.18g]\n",
00288 stats.maxRefl[0], stats.maxRefl[1], stats.maxRefl[2]);
00289 fclose(file);
00290 }
00291
00292 Void MatRad::DumpStats()
00293 {
00294 GCLReal density, mem;
00295 Int i, j;
00296
00297 density = 0;
00298 for (i = 0; i < 3; i++)
00299 for (j = 0; j < A[i].Rows(); j++)
00300 density += A[i][j].NumItems();
00301
00302 mem = (density * (sizeof(GCLReal) + sizeof(Int))) +
00303 sizeof(GCLReal) * E.Rows() * E.Cols() +
00304 sizeof(GCLReal) * B.Rows() * B.Cols();
00305 mem /= 1024.0;
00306
00307 density /= 3 * A[0].Rows() * A[0].Cols();
00308
00309 cout << dumpID
00310 << ' ' << totTime
00311 << ' ' << gRadControl->stage
00312 << ' ' << numPatches
00313 << ' ' << patches.NumItems()
00314 << ' ' << gRadControl->rays
00315 << ' ' << density
00316 << ' ' << mem
00317 << ' ' << grid->MemoryUsage()
00318 << ' ' << TotalMemoryUse()
00319 << endl;
00320
00321 DumpScene();
00322 }
00323
00324 Int MatRad::Stage(Int stage)
00325 {
00326 Colour c;
00327
00328 if (CheckTime()) return(1);
00329 // CheckTime calls DumpStats if enough time has passed, and
00330 // also stops the clock.
00331
00332 gRadControl->stage = stage;
00333
00334 switch (stage)
00335 {
00336 case 1: // pre setup
00337 cout << "method mat" << endl;
00338 if (!gRadControl->useConjGrad)
00339 cout << "solver overrelaxation" << endl;
00340 else
00341 cout << "solver conjugate-gradient" << endl;
00342
00343 cout << "sub " << gRadControl->patchSubdivs << endl;
00344 cout << "alpha " << gRadControl->alpha << endl;
00345 cout << "scene " << sceneName << endl;
00346 cout << "polys " << gRadControl->numPolys << endl;
00347 cout << "format "
00348 << "ID "
00349 << "time "
00350 << "stage "
00351 << "procPatches "
00352 << "patches "
00353 << "rays "
00354 << "density "
00355 << "mem "
00356 << "rtMem "
00357 << "rss "
00358 << endl;
00359 cout << "----------------------------------------------------------"
00360 << endl;
00361
00362 DumpStats();
00363 break;
00364
00365 case 5: // Finished calculating A[k]
00366 if (gRadControl->drawMatrix)
00367 DumpMatrix();
00368 break;
00369
00370 case 6: // Middle of solve loop.
00371 #ifndef RAD_BEST_TIMING
00372 Int i, j;
00373
00374 // Colour scene according to current B vector
00375 for (i = 0; i < patches.NumItems(); i++)
00376 {
00377 for (j = 0; j < 3; j++)
00378 c[j] = B[j][i];
00379
00380 patches[i]->SetColour(c);
00381 }
00382 #endif
00383 break;
00384
00385 case 7:
00386 DumpStats();
00387 break;
00388 }
00389
00390 if (Idle()) return(0);
00391 timer.ContTimer();
00392 return(0);
00393 }
00394
00395 #endif
00396
00397 Void MatRad::RemoveDirect()
00398 {
00399 Int i;
00400
00401 }
00402
00403 Void MatRad::DrawMatrix(Renderer &r)
00404 {
00405 #ifdef RAD_VIS
00406 SVIterd iter0, iter1, iter2;
00407
00408 if (!gRadControl->drawMatrix || gRadControl->stop)
00409 return;
00410
00411 Int i, j, n;
00412 GCLReal x1, x2, y1, y2, w;
00413
00414 w = 2.0 / A[0].Cols();
00415
00416 y1 = 1 - w;
00417 y2 = 1;
00418 n = Min(A[0].Rows(), (Int) numPatches);
00419
00420 for (i = 0; i < n; i++)
00421 {
00422 x1 = -1;
00423 x2 = w - 1;
00424
00425 iter0.Begin(A[0][i]);
00426 iter1.Begin(A[1][i]);
00427 iter2.Begin(A[2][i]);
00428
00429 for (j = 0; j < A[0].Cols(); j++)
00430 {
00431 iter0.Inc(j);
00432 iter1.Inc(j);
00433 iter2.Inc(j);
00434
00435 if (patches[i]->highlight == 2 && patches[j]->highlight == 3)
00436 r.C(cPurple);
00437 else if (patches[i]->highlight == 2)
00438 r.C(cYellow);
00439 else if (patches[j]->highlight == 3)
00440 r.C(cGreen);
00441 else if (i == j)
00442 r.C(cBlack);
00443 else
00444 {
00445 Colour mClr = cBlack;
00446
00447 if (iter0.Exists(j)) mClr[0] = -iter0.Data();
00448 if (iter1.Exists(j)) mClr[1] = -iter1.Data();
00449 if (iter2.Exists(j)) mClr[2] = -iter2.Data();
00450
00451 r.C(A[0].Cols() * mClr);
00452 }
00453
00454 PaintRect(r, Coord(x1, y1), Coord(x2, y2));
00455
00456 x1 += w;
00457 x2 += w;
00458 }
00459
00460 y1 -= w;
00461 y2 -= w;
00462 }
00463 #endif
00464 }
00465
00466 RadElem *MatRad::NewMesh()
00467 {
00468 return(new RadGrid());
00469 }