Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

RT_Grid.cc

Go to the documentation of this file.
00001 /*
00002     File:       RT_Grid.cc
00003 
00004     Function:   Defines a hierarchical grid class for ray-tracing 
00005                 optimisation
00006 
00007     Author:     Andrew Willmott, ajw+@cs.cmu.edu
00008 */
00009 
00060 #include "RT_Grid.h"
00061 #include "RT_RayStats.h"
00062 #include "FCompare.h"
00063 #ifdef RT_VIS
00064 #include "gcl/Renderer.h"
00065 #endif
00066 
00067 #define RT_SetLock(x) 
00068 #define RT_UnsetLock(x)
00069 #define RT_Lock Int
00070 
00071 #define DBG_COUT if (0) cerr
00072 
00073 
00074 // --- Globals ----------------------------------------------------------------
00075 
00076 
00077 Int     RT_Grid::sStamp = 1;
00078 Int     RT_Grid::sTag = 0x00000001;     
00079                                 // By default, the first group is enabled.
00080 Int     RT_Grid::sMem = 0;
00081 Int     RT_Grid::sTriMem = 0;
00082 Int     RT_Grid::sGenMem = 0;
00083 Int     RT_Grid::sPointMem = 0;
00084 Int     RT_Grid::sMemLimit = 0;
00085 
00086 Int     RT_Grid::sMaxCells      = 40;   
00087                                 // Maximum cells along one side of a side
00088 Int     RT_Grid::sMaxCellPrims  = RT_Grid::sMaxCells;
00089                                 // Need this many prims in a cell before
00090                                 // considering them as subgrid candidates.
00091 
00092 GCLReal RT_Grid::sPushSizeLimit = 0.05;
00093                                 // A primitive must be smaller than this 
00094                                 // fraction of a cell for it to be a subgrid
00095                                 // candidate.
00096 GCLReal RT_Grid::sMaxCellRatio  = 0.20;
00097                                 // A subgrid's cell size must be this much
00098                                 // smaller than its parent's.
00099 GCLReal RT_Grid::sMinDensity    = 0.05;
00100                                 // A grid must have at least this primitive
00101                                 // density to be considered worthwhile creating
00102                                 // it.
00103 GCLReal RT_Grid::sMaxExpand     = 3.00;
00104                                 // The maximum amount to expand a subgrid in
00105                                 // order to merge it with another.
00106 GCLReal RT_Grid::sEpsilon       = 1e-15;
00107                                 // Nearness epsilon. For intersection 
00108                                 // tests where a casting primitive isn't
00109                                 // provided, this helps avoid self-shadowing /
00110                                 // intersection.
00111 
00112 
00113 // --- Internal data structures -----------------------------------------------
00114 
00115 
00116 struct PrimEntry
00117 {
00118     union
00119     {
00120     RT_Prim*    prim;
00121     RT_Grid*    grid;
00122     };
00123     PrimEntry*  next;
00124 };
00125 
00126 typedef PrimEntry* PrimEntryPtr;
00127 
00128 // We assume no memory is malloc'd at $8.
00129 
00130 const PrimEntryPtr      PRIM_GRID_TAG = (PrimEntry*) 0x8;   
00131 
00132 struct PrimListEntry
00133 {
00134     PrimEntry**     list;
00135     PrimListEntry*  next;
00136 };
00137 
00138 
00139 // --- GridStore methods ------------------------------------------------------
00140 
00141 
00142 Void GridStore::Init(Int size)
00143 {
00144     Int     spill;
00145     Int     i;
00146     
00147     spill = size & PAGE_PTR_MASK;   // size of last page
00148     if (spill == 0)
00149         spill = PAGE_PTR_SIZE;
00150         
00151     numPages = ((size - 1) >> PAGE_PTR_BITS) + 1;
00152     pages = RT_ArrayAlloc(PrimEntry**, numPages);
00153     mem = sizeof(PrimEntry**) * numPages;
00154     
00155     for (i = 0; i < numPages - 1; i++)
00156     {
00157         pages[i] = RT_ArrayAllocClr(PrimEntry*, PAGE_PTR_SIZE);
00158         Assert(pages[i] != 0, "Out of memory");
00159         mem += sizeof(PrimEntry*) * PAGE_PTR_SIZE;
00160     }
00161     
00162     pages[numPages - 1] = RT_ArrayAllocClr(PrimEntry*, spill);
00163     mem += sizeof(PrimEntry*) * spill;
00164 }
00165 
00166 Void GridStore::Free()
00167 {
00168     Int     i;
00169     
00170     if (pages)
00171     {
00172         for (i = 0; i < numPages; i++)
00173             RT_ArrayFree(pages[i]);
00174         
00175         RT_ArrayFree(pages);
00176     }
00177 }
00178 
00179 // --- Useful #defines --------------------------------------------------------
00180 
00181 
00182 #ifdef RT_USE_FC
00183 #define FEQG(a,b) F_EQG10(a,b)
00184 #define FSGN(x) ((F_EQ10((x), 0)) ? 0 : (((x) < 0) ? -1 : 1))
00185 #else
00186 #define FEQG(a, b) (b >= a)
00187 // the epsilon is necessary here so that planes that just touch grid cells
00188 // get added to them... old old bug.
00189 #define FSGN(x) (((x) > sEpsilon ) ? 1 : (((x) < -sEpsilon) ? -1 : 0))
00190 #endif
00191 
00192 // --- RT_Grid methods --------------------------------------------------------
00193 
00194 
00195 Void RT_Grid::MasterInit()
00196 {
00197     sMem = 0;
00198     sTriMem = 0;
00199     sGenMem = 0;
00200     sPointMem = 0;
00201     Init();
00202 }
00203 
00204 Void RT_Grid::Init()
00205 {
00206     totalPrims = 0;
00207     dirty = false;
00208     level = 0;
00209 
00210     max.MakeBlock(-vl_inf);
00211     min.MakeBlock(vl_inf);
00212 
00213     totalCells = 0;
00214     addPrims = 0;
00215     addObjs = 0;
00216     addedObjs = 0;
00217     subGrids = 0;
00218     next = 0;
00219     hitPrim = 0;
00220     hitT = 0.0;
00221     stamp = 0;
00222     parent = 0;
00223 
00224     sMem += sizeof(RT_Grid);
00225 }
00226 
00227 Void RT_Grid::Free()
00228 // Delete subfields of the grid.
00229 {
00230     RT_Grid         *subGrid, *nextGrid = 0;
00231     Int             i;
00232     PrimEntry       *entry, *nextEntry = 0;
00233     PrimListEntry   *tlEntry, *tlNextEntry = 0;
00234     ObjEntry        *objEntry, *objNextEntry = 0;
00235     
00236     // Delete subgrids
00237         
00238     for (subGrid = subGrids; subGrid; subGrid = nextGrid)
00239     {
00240         nextGrid = subGrid->next;
00241         subGrid->Free();
00242         RT_Free(subGrid);
00243     }
00244 
00245     // Delete the grid storage
00246 
00247     if (totalCells > 0)
00248     {
00249         for (i = 0; i < totalCells; i++)
00250             for (entry = grid[i]; entry && entry != PRIM_GRID_TAG; 
00251                  entry = nextEntry)
00252             {
00253                 nextEntry = entry->next;
00254                 RT_Free(entry);
00255             }
00256              
00257         grid.Free();
00258     }
00259     
00260     for (tlEntry = addPrims; tlEntry; tlEntry = tlNextEntry)
00261     {
00262         tlNextEntry = tlEntry->next;
00263         RT_Free(tlEntry);
00264     }
00265     
00266     for (objEntry = addObjs; objEntry; objEntry = objNextEntry)
00267     {
00268         objNextEntry = objEntry->next;
00269         RT_Free(objEntry);
00270     }   
00271 
00272     for (objEntry = addedObjs; objEntry; objEntry = objNextEntry)
00273     {
00274         objNextEntry = objEntry->next;
00275         RT_Free(objEntry);
00276     }   
00277 }
00278 
00279 Void RT_Grid::AddObject(RT_Object *object)
00280 {
00281     ObjEntry*   newEntry;
00282         
00283     UpdateBounds(object);
00284 
00285     newEntry = RT_Alloc(ObjEntry);
00286     sMem += sizeof(ObjEntry);
00287     
00288     newEntry->object = object;
00289     newEntry->next = addObjs;
00290     addObjs = newEntry;
00291     
00292     dirty = true;
00293 }
00294 
00295 RT_Lock *gGridLock = 0;
00296 
00297 Void RT_Grid::PrepareGrid()
00298 // Prepare grid for raytracing.
00299 {
00300     ObjEntry    *entry, *nextEntry;
00301     Int         j;
00302     
00303     if (gGridLock)
00304         RT_SetLock(*gGridLock);
00305 
00306     if (!dirty)
00307     {
00308         // Another process has Prepare()'d this grid while we were
00309         // waiting for the lock...
00310         
00311         if (gGridLock)
00312             RT_UnsetLock(*gGridLock);
00313         return; 
00314     }
00315     
00316     if (addObjs)
00317     {
00318         RT_Tri*     tri;
00319         RT_GenPtr*  gen;
00320 
00321         SetupGrid();
00322 
00323         // Add object triangles
00324         
00325         for (entry = addObjs; entry; entry = nextEntry)
00326         {
00327             nextEntry = entry->next;    
00328 
00329             tri = entry->object->tris;
00330             for (j = 0; j < entry->object->numTris; j++, tri++)
00331                 AddTriangle(tri);
00332             totalPrims += entry->object->numTris;
00333         
00334             gen = entry->object->gens;
00335             for (j = 0; j < entry->object->numGens; j++, gen++)
00336                 AddGeneric(*gen);
00337             totalPrims += entry->object->numGens;
00338         
00339             sTriMem += sizeof(RT_Tri) * entry->object->numTris;
00340             sGenMem += sizeof(RT_GenPtr) * entry->object->numGens;
00341             sPointMem += entry->object->numPoints * sizeof(Point);
00342             
00343             if (nextEntry == 0)
00344                 entry->next = addedObjs;
00345         }
00346 
00347         // transfer objects to the added objects list
00348 
00349         addedObjs = addObjs;
00350         addObjs = 0;
00351     }
00352                 
00353     // Now, create nested grids.
00354     
00355     dirty = false;
00356 
00357     if (sMemLimit && sMem >= sMemLimit)
00358     {
00359         cerr << "*** out of memory: aborting grid creation... >" 
00360              << level << endl;
00361         cerr << "*** memory = " << sMem << " bytes." << endl;
00362         if (gGridLock)
00363             RT_UnsetLock(*gGridLock);
00364         return;
00365     }
00366     
00367     CreateNestedGrids();
00368 
00369     if (gGridLock)
00370         RT_UnsetLock(*gGridLock);
00371 }
00372 
00373 
00374 Void RT_Grid::UpdateBounds(Point& cellMin, Point& cellMax)
00375 {
00376     FindMinElts(cellMin, min, min);
00377     FindMaxElts(cellMax, max, max);
00378 }
00379 
00380 Void RT_Grid::UpdateBounds(RT_Object *object)
00381 {
00382     Int     i;
00383     Point*  points = object->points;
00384             
00385     for (i = 0; i < object->numPoints; i++)
00386 		::UpdateBounds(points[i], min, max);
00387     
00388     for (i = 0; i < object->numGens; i++)
00389         object->gens[i]->UpdateBounds(min, max);
00390 }
00391 
00392 Void RT_Grid::SetupGrid()
00393 {
00394     GCLReal maxSpan;
00395     Vector  centre, span;
00396     Int     i;
00397 
00398     // Calculate the boundaries for the grid.  We already know
00399     // the world-space boundaries for the object.
00400 
00401     // XXX fix more elegantly
00402     // expand the box a little so we don't suffer from numerical
00403     // problems for surfaces lying along one of the sides of the grid
00404     const GCLReal   kGridFudge = 1e-15;
00405     Vector          fudge;
00406 
00407     max += fudge.MakeBlock(kGridFudge);
00408     min -= fudge;
00409 
00410     span = max - min;
00411     maxSpan = MaxElt(span);
00412     cellSize = maxSpan / sMaxCells;
00413     areaLimit = sPushSizeLimit * sqr(cellSize);     
00414     
00415     // Calculate how many grid cells the object will have in each 
00416     // direction.  We've already assigned the widest direction a 
00417     // preset number of grid cells and the narrower directions fewer 
00418     // cells.
00419     
00420     for (i = 0; i < 3; i++)
00421     {
00422         numCells[i] = (Int) ceil(sMaxCells * span[i] / maxSpan);
00423 
00424         // Ensure at least 1 cell in all directions
00425         if (numCells[i] == 0)       
00426             numCells[i] = 1;
00427         
00428         max[i] = min[i] + numCells[i] * cellSize;
00429     }
00430 
00431     // Allocate a one-dimensional array for the grid.
00432 
00433     totalCells = numCells[0] * numCells[1] * numCells[2];
00434     xSpan = numCells[1] * numCells[2];
00435     ySpan = numCells[2];
00436 
00437     grid.Init(totalCells);
00438     sMem += (Int) grid.MemoryUsage();
00439 }
00440 
00441 
00442 Void RT_Grid::AddGeneric(RT_GenPtr gen)
00443 // Add a generic object to this grid.
00444 {
00445     Vector      tMin, tMax;
00446     Vector      cellMin, vertex;
00447     Int         i;
00448     Int         x, y, z, cellNum, cellsAdded;
00449     PrimEntry   **last, *entry, *newEntry;
00450     Int         start[3], end[3];
00451     
00452     // We want to enter the polygon into all of the grid cells 
00453     // it intersects.  We first limit our test of grid cells to 
00454     // those in which the polygon's bounding box resides.
00455 
00456     gen->FindBounds(tMin, tMax);
00457             
00458     // Find the equivalent cell bounds
00459 
00460     for (i = 0; i < 3; i++)
00461     {
00462         start[i] = (Int) ((tMin[i] - min[i]) / cellSize);
00463         end[i]   = (Int) ((tMax[i] - min[i]) / cellSize);
00464 
00465         // Crop to the grid
00466 
00467         if (end[i] >= numCells[i])
00468             end[i] = numCells[i] - 1;
00469         else if (end[i] < 0)
00470             end[i] = 0;
00471             
00472         if (start[i] >= numCells[i])
00473             start[i] = numCells[i] - 1;
00474         else if (start[i] < 0)
00475             start[i] = 0;
00476     }
00477         
00478     // Finally, the generic is added to every grid cell in its bounding box
00479 
00480     cellsAdded = 0;
00481     for (x = start[0]; x <= end[0]; x++)
00482         for (y = start[1]; y <= end[1]; y++)
00483             for (z = start[2]; z <= end[2]; z++)
00484             {
00485                 cellsAdded++;
00486                 newEntry = RT_Alloc(PrimEntry);
00487                 sMem += sizeof(PrimEntry);
00488                 cellNum = x * xSpan + y * ySpan + z;
00489                 
00490                 newEntry->prim = gen;
00491 
00492                 // Insert gen in order of (equivalent) area...
00493                 
00494                 last = &(grid[cellNum]);    // the last entry we looked at
00495                 
00496                 for (entry = *last; entry; entry = entry->next)
00497                 {
00498                     // Only bother sorting prims < areaLimit
00499                     
00500                     if (entry->prim->area <= gen->area || 
00501                         entry->prim->area < areaLimit) 
00502                         break;
00503                         
00504                     last = &(entry->next);
00505                 }
00506                 
00507                 *last = newEntry;
00508                 newEntry->next = entry;
00509             }
00510 
00511 #ifdef RT_OPAC
00512     gen->cells = cellsAdded;
00513 #endif
00514 }
00515 
00516 
00517 Void RT_Grid::AddTriangle(RT_Tri *tri)
00518 // Add a triangle to this grid.
00519 {
00520     Vector      tMin, tMax;
00521     Vector      cellMin, vertex;
00522     Point       *p1, *p2, *p3;
00523     Int         i;
00524     Int         x, y, z, sign, cellNum, cellsAdded;
00525     PrimEntry   **last, *entry, *newEntry;
00526     Point*      points = tri->object->points;
00527     Int         start[3], end[3];
00528     GCLReal     temp;
00529     
00530     // We want to enter the polygon into all of the grid cells 
00531     // it intersects.  We first limit our test of grid cells to 
00532     // those in which the polygon's bounding box resides.
00533 
00534     dirty = true;
00535     p1 = points + tri->v[0];
00536     p2 = points + tri->v[1];
00537     p3 = points + tri->v[2];
00538 
00539     FindMaxElts(*p1, *p2, tMax);
00540     FindMaxElts(*p3, tMax, tMax);
00541     
00542     FindMinElts(*p1, *p2, tMin);
00543     FindMinElts(*p3, tMin, tMin);
00544         
00545     // Find the equivalent cell bounds
00546 
00547     for (i = 0; i < 3; i++)
00548     {
00549         start[i] = (Int) ((tMin[i] - min[i]) / cellSize);
00550         end[i]   = (Int) ((tMax[i] - min[i]) / cellSize);
00551 
00552         // Crop to the grid
00553 
00554         if (end[i] >= numCells[i])
00555             end[i] = numCells[i] - 1;
00556         else if (end[i] < 0)
00557             end[i] = 0;
00558             
00559         if (start[i] >= numCells[i])
00560             start[i] = numCells[i] - 1;
00561         else if (start[i] < 0)
00562             start[i] = 0;
00563     }
00564     
00565     // Finally, the triangle is added to every grid cell in the bounding box
00566     // which straddles the plane of the triangle. 
00567 
00568     cellsAdded = 0;
00569     for (x = start[0]; x <= end[0]; x++)
00570         for (y = start[1]; y <= end[1]; y++)
00571             for (z = start[2]; z <= end[2]; z++)
00572             {
00573                 // We test each vertex of the cell by plugging it into the
00574                 // triangle's plane equation. If a vertex has a different
00575                 // sign from the preceeding vertices, we know the plane
00576                 // straddles this cube, and we add the triangle to the
00577                 // cell. A result of zero means the plane touches the vertex, 
00578                 // which is also grounds for adding the triangle. 
00579                 
00580                 cellMin = min + Vector(x, y, z) * cellSize;
00581                 cellNum = x * xSpan + y * ySpan + z;
00582                 temp = dot(tri->normal, cellMin) + tri->d;
00583                 sign = FSGN(temp);
00584                 
00585                 if (sign == 0)  // The first sign is zero: we can stop.
00586                     i = 1;
00587                 else
00588                     for (i = 1; i < 8; i++) 
00589                     {
00590                         vertex = cellMin;
00591                         
00592                         if (i & 1) vertex[0] += cellSize;
00593                         if (i & 2) vertex[1] += cellSize;
00594                         if (i & 4) vertex[2] += cellSize;
00595                         
00596                         temp = dot(tri->normal, vertex) + tri->d;
00597 
00598                         if (sign != FSGN(temp))
00599                             break;
00600                     }
00601 
00602                 // Add the triangle if we have a straddle
00603 
00604                 if (i < 8)
00605                 {
00606                     cellsAdded++;
00607                     newEntry = RT_Alloc(PrimEntry);
00608                     sMem += sizeof(PrimEntry);
00609                     
00610                     newEntry->prim = tri;
00611 
00612                     // Insert tri in order of area...
00613                     
00614                     last = &(grid[cellNum]);    // the last entry we looked at
00615                     
00616                     for (entry = *last; entry; entry = entry->next)
00617                     {
00618                         // Only bother sorting tris < areaLimit
00619                         
00620                         if (entry->prim->area <= tri->area || 
00621                             entry->prim->area < areaLimit) 
00622                             break;
00623                             
00624                         last = &(entry->next);
00625                     }
00626                     
00627                     *last = newEntry;
00628                     newEntry->next = entry;
00629                 }
00630             }
00631 
00632 #ifdef RT_OPAC
00633     tri->cells = cellsAdded;
00634 #endif
00635 }
00636 
00637 Void RT_Grid::RayClampEntryPoint(Int index, Bool backEntry[3],
00638                                         Vector& gridPoint, Int cell[3])
00639 {
00640     if (backEntry[index])
00641     {
00642         // If we're entering from the back end, we're entering the 
00643         // largest numbered cell in this direction. 
00644 
00645         cell[index] = numCells[index] - 1;
00646         gridPoint[index] = (GCLReal) numCells[index];
00647     }
00648     else
00649     {
00650         // From the front, it's the smallest, which is conveniently zero.
00651 
00652         cell[index] = 0;
00653         gridPoint[index] = 0.0;
00654     }
00655 }  
00656 
00657 
00658 Bool RT_Grid::FindGridStart(
00659 
00660     const Point&    start,
00661     const Vector&   direction,
00662     Int             cell[3],
00663     Int             increment[3],
00664     Int             limit[3], 
00665     GCLReal&        tRay,       
00666                     // start of ray in grid 
00667     Vector&         tDelta,     
00668                     // delta t for a step of size cellSize in each direction
00669     Vector&         tMax 
00670                     // delta t to the next grid wall in each direction
00671     )
00672 {
00673     Int     i;
00674     Vector  gridPoint;
00675     Vector  in, out;
00676     Bool    backEntry[3];
00677     Point   point;
00678                 
00679     gridPoint = (start - min) / cellSize;
00680 
00681     if (0.0 <= gridPoint[0] && gridPoint[0] <= numCells[0] &&
00682         0.0 <= gridPoint[1] && gridPoint[1] <= numCells[1] &&
00683         0.0 <= gridPoint[2] && gridPoint[2] <= numCells[2])
00684     {
00685         // We are starting inside the grid: find which cell
00686         
00687         tRay = 0.0;
00688         
00689         for (i = 0; i < 3; i++)
00690         {
00691             cell[i] = (Int) floor(gridPoint[i]);
00692 
00693             if (cell[i] == numCells[i])
00694                 cell[i]--;
00695         }
00696     }
00697     else
00698     {
00699         // Otherwise, we have to compute the entry point
00700         // into the grid.
00701 
00702         for (i = 0; i < 3; i++)
00703         {
00704             // Avoid the divide by zero.  This would occur if the ray
00705             // has no component in one or two directions.
00706     
00707             if (abs(direction[i]) > (GCLReal) 0.0)
00708             {
00709                 in[i]     = (min[i] - start[i]) / direction[i];
00710                 out[i]    = (max[i] - start[i]) / direction[i];
00711             }
00712             else
00713             {
00714                 in[i]     = -vl_inf;
00715                 out[i]    =  vl_inf;
00716             }
00717 
00718             // We're really concerned only with the entry point of the ray 
00719             // into the grid.  Thus, if we've got our entry and exit points
00720             // backwards, then correct the entry point.
00721     
00722             if (backEntry[i] = (in[i] > out[i]))
00723                 in[i] = out[i];
00724         }
00725 
00726         // The actual entry point into the grid occurs at the maximum of the
00727         // just-computed entry values (i.e., we enter the grid when we've
00728         // crossed the X _and_ the Y _and_ the Z planes of the Fujimoto 
00729         // grid.
00730 
00731         tRay = MaxElt(in);          
00732         point = start + tRay * direction;
00733     
00734         // Compute the entry point in terms of grid space.  (I.e., in
00735         // what cell do we enter the grid?)
00736         
00737         gridPoint = (point - min) / cellSize;
00738         
00739         for (i = 0; i < 3; i++)
00740             cell[i] = (Int) floor(gridPoint[i]);
00741         
00742         // the cell direction corresponding to the maximum component(s)
00743         // of 'in' will lie along the boundary of the grid. To 
00744         // prevent spilling over the boundary due to round-off error, we clamp
00745         // the direction(s) back to the grid boundary.
00746         
00747         if (in[0] > in[1])  
00748         {
00749             if (in[0] >= in[2]) 
00750             {
00751                 RayClampEntryPoint(0, backEntry, gridPoint, cell);
00752     
00753                 if (in[0] == in[2]) 
00754                     RayClampEntryPoint(2, backEntry, gridPoint, cell);
00755             }
00756             else
00757                 RayClampEntryPoint(2, backEntry, gridPoint, cell);
00758         }
00759         else if (in[0] == in[1])
00760         {
00761             if (in[2] >= in[0])
00762             {
00763                 RayClampEntryPoint(2, backEntry, gridPoint, cell);
00764     
00765                 if (in[2] == in[0])
00766                 {
00767                     RayClampEntryPoint(0, backEntry, gridPoint, cell);
00768                     RayClampEntryPoint(1, backEntry, gridPoint, cell);
00769                 }
00770             }
00771             else
00772             {
00773                 RayClampEntryPoint(0, backEntry, gridPoint, cell);
00774                 RayClampEntryPoint(1, backEntry, gridPoint, cell);
00775             }
00776         }
00777         else
00778         {
00779             if (in[1] >= in[2])
00780             {
00781                 RayClampEntryPoint(1, backEntry, gridPoint, cell);
00782     
00783                 if (in[1] == in[2])
00784                     RayClampEntryPoint(2, backEntry, gridPoint, cell);
00785             }
00786             else
00787                 RayClampEntryPoint(2, backEntry, gridPoint, cell);
00788         }
00789         
00790         // If the ray completely misses the Fujimoto grid, then we 
00791         // of course didn't hit anything.
00792 
00793         for (i = 0; i < 3; i++)
00794             if (cell[i] < 0 || numCells[i] <= cell[i])
00795                 return(false);
00796     }
00797     
00798     // Calculate auxillary info used for traversing the grid
00799     
00800     for (i = 0; i < 3; i++)
00801     {
00802         GCLReal scale = cellSize;
00803     
00804         // The ray that goes through the Fujimoto grid is parameterized,
00805         // i.e., the ray is of the form start + t * direction, where t is
00806         // the parameter.  For any given direction (i.e. X, Y, or Z),
00807         // the amount that t changes as the ray crosses to the next cell
00808         // in the same direction is fixed.  Calculate what that change in
00809         // t is and store the information.  We're going to use this 
00810         // information to help us traverse the grid.
00811 
00812         tDelta[i] = (abs(direction[i]) == (GCLReal) 0.0) ?
00813             0.0 : scale / abs(direction[i]);
00814     
00815         // Note the sign of the direction vector of the ray.
00816 
00817         increment[i] = FSGN(direction[i]);
00818         limit[i] = (increment[i] < 0) ? -1 : numCells[i];
00819 
00820         // Make a note of what the value of the ray parameter t will
00821         // be when we cross over the next orthogonal plane in this 
00822         // direction.  (Of course, if the direction vector has no 
00823         // component in this direction, then we'll _never_ reach the 
00824         // next grid cell in this direction.)
00825 
00826         if (increment[i] == 0)
00827             tMax[i] = vl_inf;
00828         else if (increment[i] == 1)
00829             tMax[i] = tRay + tDelta[i] * (cell[i] + 1 - gridPoint[i]);
00830         else
00831         {
00832             // The the grid point is integral, i.e. if it lies exactly on
00833             // one of the orthogonal planes, then the next movement will
00834             // cross the entire cell.
00835         
00836             if (gridPoint[i] == floor(gridPoint[i]))
00837                 tMax[i] = tRay + tDelta[i]; 
00838             else
00839                 tMax[i] = tRay + tDelta[i] * 
00840                     (gridPoint[i] - floor(gridPoint[i]));
00841         }
00842     }
00843     
00844     return(tDelta[0] != 0.0 || tDelta[1] != 0.0 || tDelta[2] != 0);
00845 }
00846 
00847 
00848 // --- Intersection methods ---------------------------------------------------
00849 
00850 
00851 Bool RT_Grid::IntersectionExists(
00852         const Point&    start,
00853         const Point&    end,
00854         RT_Prim*        origPrim,
00855         RayStats*       stats
00856     )
00857 // Finds out if any intersection occurs between start and end. Ignores 
00858 // intersections with origPrim, if it is not nil.
00859 {
00860     Vector      direction = end - start;
00861     Vector      reflectPoint;
00862     GCLReal     t, tRay;
00863     Int         i, increment[3], limit[3];  
00864     Vector      tDelta, tMax;
00865     Int         nextCellDir;
00866     Int         cell[3];
00867     PrimEntry*  entry;
00868     
00869     if (stats) stats->rays++;
00870 
00871     if (sqrlen(direction) < 1e-15)
00872         return(false);
00873 
00874     if (dirty)
00875         PrepareGrid();
00876 
00877     if (level == 0)         
00878     {
00879         // just starting off: ignore all previously stamped subgrids.
00880         RT_Grid::IncTime();
00881         RT_Prim::IncTime();
00882     }
00883     else if (IsStamped())
00884     {
00885         // return cached result
00886         if (stats) stats->d2++;
00887         return(hitPrim != 0);
00888     }
00889     else
00890     {
00891 #ifdef RT_GRID_CACHE
00892         // ensure result is cached
00893         Stamp();
00894 #endif
00895     }
00896     
00897     if (stats) stats->grids++;
00898     hitPrim = 0;
00899 
00900     // Figure out grid parameters, and return if we completely miss the grid
00901     if (!FindGridStart(start, direction, cell, increment, limit, tRay,
00902                        tDelta, tMax))
00903         return(false);
00904             
00905     // Traverse the grid...
00906 
00907     for (i = 0; i < 256; i++)
00908     {
00909         // We are only after a hit, not the closest hit, so as soon as we get
00910         // one, we can return.
00911         if (stats) stats->voxels++;
00912 
00913         entry = grid[cell[0] * xSpan + cell[1] * ySpan + cell[2]];
00914 
00915         for (; entry; entry = entry->next)
00916         {
00917             if (stats) stats->polysTested++;
00918 
00919             if (entry->next == PRIM_GRID_TAG)
00920             {
00921                 // If this is a subgrid entry, call the subgrid...
00922 
00923                 if (entry->grid->IntersectionExists(start, end,
00924                                                     origPrim, stats))
00925                 {
00926                     hitPrim = entry->grid->hitPrim;
00927                     hitT = entry->grid->hitT;
00928                     return(true);
00929                 }
00930                 
00931                 break;  // a grid entry is always last.
00932             }
00933             
00934             if (entry->prim == origPrim)
00935                 continue;
00936             if ((entry->prim->flags & TRI_INACTIVE) || !(sTag & entry->prim->object->tag))
00937                 continue;
00938 #ifdef RT_SUPPORT_GENS
00939             if (entry->prim->primType == rt_gen)
00940             {
00941                 RT_GenPtr gen = *(RT_GenPtr*) entry->prim;
00942                                 
00943                 if (!gen->IsStamped())
00944                     gen->Intersect(start, direction, 0, 1);
00945                 
00946                 if (gen->IsTrue(GEN_HIT))
00947                 {
00948                     hitPrim = gen;
00949                     hitT = gen->hitT;
00950                     DBG_COUT << "hit generic at " << hitT << endl;
00951                     return(true);
00952                 }
00953             }
00954             else if (entry->prim->primType == rt_triangle)
00955 #else
00956             if(1)
00957 #endif
00958             {
00959                 RT_Tri*     thisTri = (RT_Tri*) entry->prim;
00960                     
00961                 // Find ray intersection with tri's plane. Bail if there 
00962                 // isn't one.
00963                 GCLReal normDotDirection = dot(thisTri->normal, direction);
00964     
00965                 if (thisTri->flags & TRI_2SIDED_V)
00966                 {
00967                     if (normDotDirection == 0.0)
00968                         continue;
00969                 }
00970                 else
00971                     if (normDotDirection >= 0.0)
00972                         continue;
00973 
00974                 t = (thisTri->d + dot(thisTri->normal, start)) / 
00975                     -normDotDirection;
00976 
00977                 // Bail if the intersection occurs before 'start' or after
00978                 // 'end'. the epsilon here accounts for self-shadowing.
00979                 if (t <= sEpsilon || t >= (1.0 - sEpsilon))
00980                     continue;
00981 
00982                 // Okay, let's do the actual test. If we've hit the tri 
00983                 // itself, we can return.
00984 
00985                 if (stats) stats->intersections++;
00986 
00987                 reflectPoint = start + t * direction;
00988                 thisTri->PointIsInside(reflectPoint);
00989                         
00990                 if (thisTri->IsTrue(TRI_HIT))
00991                 {
00992                     if (stats) stats->goodHits++;
00993                     hitPrim = thisTri;
00994                     hitT = t;
00995                     return(true);
00996                 }
00997             }
00998             else
00999                 DBG_COUT << "unknown primitive type: " << 
01000                     entry->prim->primType << endl;
01001         }   
01002 
01003         nextCellDir = MinEltIndex(tMax);
01004         cell[nextCellDir] += increment[nextCellDir];
01005 
01006         // If we've exited the grid, then bail -- we didn't find any
01007         // intersections.
01008         if (cell[nextCellDir] == limit[nextCellDir])
01009             return(false);
01010         else
01011             tMax[nextCellDir] += tDelta[nextCellDir];
01012     }
01013 
01014 #ifdef DEBUG
01015     cerr << "*** STUCK IN GRID: tMax: " << tMax << tDelta << " for " << start << end << endl;
01016 #endif
01017 }
01018 
01019 RT_Prim *RT_Grid::ClosestIntersection(
01020         const Point&    start,              // Start of the ray
01021         const Vector&   direction,          // direction of the same
01022         RT_Prim*        origPrim,           // originating primitive
01023         RayStats*       stats               // ray statistics.
01024     )
01025 // Finds the closest intersection to the start point. Ignores 
01026 // intersections with origPrim, if it is not nil.
01027 {   
01028     Vector      reflectPoint;
01029     Int         increment[3],  limit[3];    
01030     GCLReal     tRayNext, tRayLast, t, tMin;
01031     Vector      tDelta, tMax;
01032     Int         nextCellDir;
01033     Int         cell[3];
01034     PrimEntry*  entry;
01035 
01036     if (stats) stats->rays++;
01037 
01038     if (dirty)
01039         PrepareGrid();
01040 
01041     if (level == 0)         
01042     {
01043         // just starting off: ignore all previously stamped subgrids + prims
01044         DBG_COUT << "clearing stamps" << endl;
01045         RT_Prim::IncTime();
01046         RT_Grid::IncTime();
01047     }
01048     else if (IsStamped())
01049     {
01050         // return cached result
01051         DBG_COUT << "returning cached result" << endl;
01052         if (stats) stats->d2++;
01053         return(hitPrim);
01054     }
01055     else
01056     {
01057 #ifdef RT_GRID_CACHE
01058         // ensure result is cached
01059         Stamp();
01060 #endif
01061     }
01062                 
01063     if (stats) stats->grids++;
01064     hitPrim = 0;
01065     
01066     // Figure out grid's parameters, and return if we completely miss its 
01067     // bounding box.
01068     if (!FindGridStart(start, direction, cell, increment, limit, tRayNext,
01069                        tDelta, tMax))
01070         return(hitPrim);
01071     
01072     // Traverse the grid & keep track of the closest intersection found so far.
01073     // tRayLast and tRayNext bracket the t values of the part of the ray that 
01074     // passes through the current cell. We're only interested in hits that
01075     // occur within these values.
01076     tRayLast = Max(sEpsilon, tRayNext);
01077 
01078     for (;;)
01079     {
01080         // We have to check all the triangles within this cell, since they
01081         // are in no particular order with respect to the ray.  
01082         if (stats) stats->voxels++;
01083 
01084         entry = grid[cell[0] * xSpan + cell[1] * ySpan + cell[2]];
01085         nextCellDir = MinEltIndex(tMax);    // the next cell after this...
01086         tRayNext = tMax[nextCellDir];       // t at which we leave this cell
01087 
01088         // Update record of delta t to the next cell in each direction.
01089         cell[nextCellDir] += increment[nextCellDir];
01090         tMax[nextCellDir] += tDelta[nextCellDir];
01091         
01092         // we're only interested in hits before tMin
01093         if (cell[nextCellDir] == limit[nextCellDir])
01094             tMin = vl_inf;
01095         else
01096             tMin = tRayNext;
01097 
01098         DBG_COUT << "searching " << tRayLast << " - " << tRayNext << endl;
01099 
01100         // Iterate through the primitives in this cell...
01101         for (; entry; entry = entry->next)
01102         {
01103             DBG_COUT << "checking cell prim" << endl;
01104             if (entry->next == PRIM_GRID_TAG)
01105             {
01106                 // If this is a subgrid entry 
01107                 if (entry->grid->ClosestIntersection(start, direction, 
01108                     origPrim, stats))
01109                 {
01110                     t = entry->grid->hitT;
01111 
01112                     if (FEQG(tRayLast, t) && FEQG(t, tMin))
01113                     {
01114                         hitPrim = entry->grid->hitPrim;
01115                         hitT = t;
01116                         tMin = t;
01117                         DBG_COUT << "hit grid at " << t << endl;
01118                     }
01119                 }
01120                 break;  // RT_Grid is always last.
01121             }
01122 
01123             if (entry->prim == origPrim)
01124                 continue;           
01125             if ((entry->prim->flags & TRI_INACTIVE) || !(sTag & entry->prim->object->tag))
01126                 continue;
01127 
01128             DBG_COUT << "intersecting" << endl;
01129 #ifdef RT_SUPPORT_GENS
01130             if (entry->prim->primType == rt_gen)
01131             {
01132                 RT_GenPtr gen = *(RT_GenPtr*) entry->prim;
01133                                 
01134                 if (!gen->IsStamped())
01135                     gen->Intersect(start, direction, tRayLast, tMin);
01136                 
01137                 if (gen->IsTrue(GEN_HIT))
01138                 {
01139                     tMin = gen->hitT;
01140                     hitT = tMin;
01141                     t = hitT;
01142                     hitPrim = gen;
01143                     if (stats) stats->hits++;
01144                     DBG_COUT << "hit gen at " << hitT << endl;
01145                 }
01146                 
01147             }
01148             else if (entry->prim->primType == rt_triangle)
01149 #else
01150             if(1)
01151 #endif
01152             {           
01153                 RT_Tri*     thisTri = (RT_Tri*) entry->prim;
01154                     
01155                 if (stats) stats->polysTested++;
01156                 
01157                 // Find ray intersection with tri's plane.
01158                 // Bail if there isn't one.
01159                 GCLReal normDotDirection = dot(thisTri->normal, direction);
01160     
01161                 if (thisTri->flags & TRI_2SIDED_R)
01162                 {
01163                     if (normDotDirection == 0.0)
01164                         continue;
01165                 }
01166                 else
01167                     if (normDotDirection >= 0.0)
01168                         continue;
01169 
01170                 t = (thisTri->d + dot(thisTri->normal, start)) / 
01171                     -normDotDirection;
01172                     
01173                 // Bail if it occurs before start of the cell, or after tMin
01174                 if ((!FEQG(tRayLast, t) || !FEQG(t, tMin)))
01175                 {
01176                     DBG_COUT << "hit outside cell" << endl;
01177                     continue;
01178                 }
01179                 // Okay, lets do the actual test. If we've hit the tri itself,
01180                 // we can return a hit after we've finished this voxel.
01181                 if (stats) stats->intersections++;
01182                 reflectPoint = start + t * direction;
01183                 
01184                 if (!thisTri->IsStamped())
01185                     thisTri->PointIsInside(reflectPoint);
01186                 
01187                 if (thisTri->IsTrue(TRI_HIT))
01188                 {
01189                     tMin = t;       
01190                     hitT = t;
01191 #ifdef RT_GRID_SHADE_DEBUG
01192                     thisTri->id = level;
01193 #endif
01194                     hitPrim = thisTri;  
01195                     if (stats) stats->hits++;
01196                     DBG_COUT << "hit tri at " << t << endl;
01197                 }
01198             }
01199             else
01200                 DBG_COUT << "unknown prim type: " << entry->prim->primType 
01201                          << endl;
01202         }
01203 
01204         if (hitPrim)
01205         {
01206             // We hit something inside this cell. Mission over, let's go home...
01207             if (stats) stats->goodHits++;
01208             return(hitPrim);
01209         }
01210 
01211         // If we've exited the grid, then bail--we didn't find any
01212         // intersections.
01213 
01214         if (cell[nextCellDir] == limit[nextCellDir])
01215             return(hitPrim);
01216 
01217         tRayLast = tRayNext;
01218     }
01219 }
01220 
01221 
01222 // --- Nested grid setup ------------------------------------------------------
01223 
01224 
01225 Void RT_Grid::CreateNestedGrids()
01226 // Finds cells with too many primitives in them, and creates new grids to hold
01227 // them.
01228 {
01229     Int             x, y, z, count;
01230     PrimEntry       *entry, *startEntry, **pushStart;
01231     RT_Grid         *subGrid, *bestGrid;
01232     PrimListEntry   *newPrimListEntry;
01233     Vector          cellMin, cellMax, bmin, bmax;
01234     GCLReal         newBVol, expRatio;
01235     GCLReal         minRatio;
01236     Vector          cellSpan, primsMin, primsMax, primsSpan;
01237 
01238     // Loop over the entire grid.
01239     
01240     for (x = 0; x < numCells[0]; x++)
01241         for (y = 0; y < numCells[1]; y++)
01242             for (z = 0; z < numCells[2]; z++)
01243             {
01244                 count = 0;
01245                 startEntry = grid[x * xSpan + y * ySpan + z];
01246                 
01247                 // + Don't push prims larger than areaLimit...
01248                 // This limit exists for two reasons: if a primitive is very
01249                 // large compared to its grid, it will create far too many 
01250                 // prim entries, plus there's also not much gain in pushing
01251                 // a primitive that's already on the order of the size 
01252                 // of a voxel.
01253                 
01254                 // find start of pushable prims (the entries are sorted
01255                 // by area)
01256                 pushStart = &(grid[x * xSpan + y * ySpan + z]);
01257                 for (entry = startEntry; entry; entry = entry->next)
01258                     if (entry->prim->area < areaLimit)
01259                         break;
01260                     else
01261                         pushStart = &(entry->next);
01262 
01263                 // Count pushable prims
01264                 for (entry = *pushStart; entry; entry = entry->next)
01265                     count++;
01266                                     
01267                 // Add this cell's prims to a subgrid if there are too many of
01268                 // them
01269                 if (count > sMaxCellPrims * (level + 1))
01270                 {
01271                     // Find the bounds of the prims
01272 
01273                     cellMin = min + Vector(x,  y,  z) * cellSize;
01274                     cellMax.MakeBlock(cellSize);
01275                     cellMax += cellMin;
01276                     primsMin.MakeBlock(+vl_inf);
01277                     primsMax.MakeBlock(-vl_inf);
01278                                         
01279                     for (entry = *pushStart; entry; entry = entry->next)
01280                     {
01281                         if (entry->prim->primType == rt_triangle)
01282                             ((RT_Tri*) entry->prim)->
01283                                 UpdateBounds(primsMin, primsMax);
01284                         else if (entry->prim->primType == rt_gen)
01285                             (*(RT_GenPtr*) entry->prim)->
01286                                 UpdateBounds(primsMin, primsMax);
01287                         else
01288                             DBG_COUT << "illegal prim type" << endl;
01289                     }
01290                     
01291                     // Trim the bounds to the boundaries of the cell
01292 
01293                     FindMaxElts(primsMin, cellMin, primsMin);
01294                     FindMinElts(primsMax, cellMax, primsMax);
01295                     
01296                     // We need a new grid. See whether we can merge with one of
01297                     // the already-created subgrids.
01298                     
01299                     minRatio = sMaxExpand;
01300                     bestGrid = 0;
01301                     primsSpan = primsMax - primsMin;
01302                     newBVol = primsSpan[0] * primsSpan[1] * primsSpan[2];
01303                     
01304                     for (subGrid = subGrids; subGrid; subGrid = subGrid->next)
01305                     {
01306                         GCLReal cellRatio;
01307                         
01308                         // Find the bounds of the putatative new grid.
01309                                                     
01310                         FindMinElts(subGrid->min, primsMin, bmin);
01311                         FindMaxElts(subGrid->max, primsMax, bmax);
01312 
01313                         // We want to ensure the cellSize of subgrids doesn't 
01314                         // get too large... so we find the ratio of the cell 
01315                         // size of the new grid to the parent (cellRatio)
01316                         // and the increase in volume over the old grid.
01317                         
01318                         cellRatio = MaxElt(bmax - bmin) / 
01319                             (sMaxCells * cellSize); 
01320                         expRatio = BoxVol(bmin,  bmax) /
01321                             (BoxVol(subGrid->min,  subGrid->max) + newBVol);
01322 
01323                         // If both are acceptable, this is our new best grid
01324 
01325                         if (expRatio < minRatio && cellRatio < sMaxCellRatio)
01326                         {
01327                             minRatio = expRatio;
01328                             bestGrid = subGrid;
01329                         }
01330                     }
01331                     
01332                     if (!bestGrid)
01333                     {
01334                         // We need a brand-spanking-new grid if we didn't 
01335                         // find one to merge with.
01336                     
01337                         bestGrid = RT_Alloc(RT_Grid);
01338                         
01339                         bestGrid->Init();
01340                         bestGrid->parent = this;
01341                         bestGrid->level = level + 1;
01342                         bestGrid->next = subGrids;
01343                         bestGrid->dirty = true; 
01344                         subGrids = bestGrid;
01345                     }
01346                     
01347                     // Add a pointer to the pushable prims to the prim list of
01348                     // the subgrid
01349                     
01350                     newPrimListEntry = RT_Alloc(PrimListEntry);
01351                     sMem += sizeof(PrimListEntry);
01352                     
01353                     newPrimListEntry->list = pushStart;
01354                     newPrimListEntry->next = bestGrid->addPrims;
01355                     bestGrid->addPrims = newPrimListEntry;
01356                                         
01357                     bestGrid->UpdateBounds(primsMin, primsMax);
01358                     bestGrid->totalPrims += count;
01359                 }   
01360             }
01361             
01362     CullSubGrids();
01363     PushPrimitives();
01364 }
01365 
01366 Void RT_Grid::CullSubGrids()
01367 // Cull subgrids that aren't worth the extra space.
01368 {
01369     GCLReal     r;
01370     Int         estCellTotal;
01371     Vector      span;
01372     RT_Grid*    subGrid;
01373     RT_Grid**   last;
01374         
01375     last = &subGrids;
01376     
01377     for (subGrid = *last; subGrid; subGrid = *last)
01378     {
01379         span = subGrid->max - subGrid->min;
01380         r = sMaxCells / MaxElt(span);
01381         estCellTotal = Int(r * r * r * GCLReal(span[0] * span[1] * span[2]));
01382         
01383         if (subGrid->totalPrims / GCLReal(estCellTotal) < 
01384             sMinDensity * (1 - level / 2.0))
01385         {
01386             // Delete the subgrid from the list.
01387             
01388             *last = subGrid->next;
01389             subGrid->Free();
01390             RT_Free(subGrid);
01391         }
01392         else
01393             last = &(subGrid->next);
01394     }
01395 }
01396 
01397 Void RT_Grid::PushPrimitives()
01398 // Shift primitives down to the grids created by CreateNestedGrids routine...
01399 {
01400     PrimEntry       *entry, *nextEntry;
01401     RT_Grid         *subGrid;
01402     PrimListEntry   *primList;
01403     
01404     for (subGrid = subGrids; subGrid; subGrid = subGrid->next)
01405     {
01406         // Create the grids!
01407         subGrid->SetupGrid();
01408         subGrid->dirty = true;  
01409         RT_Prim::IncTime();
01410                         
01411         // Push the primitives!
01412         for (primList = subGrid->addPrims; primList; primList = primList->next)
01413         {
01414             // Each primList is a list of primitives pushed to this grid
01415             // from a particular cell.
01416             
01417             for (entry = *(primList->list); entry; entry = nextEntry)
01418             {
01419                 nextEntry = entry->next;
01420                 
01421                 // Add primitives, avoiding duplicates
01422                 
01423                 if (!entry->prim->IsStamped())
01424                 {
01425                     if (entry->prim->primType == rt_triangle)
01426                         subGrid->AddTriangle((RT_Tri*) entry->prim);
01427                     else if (entry->prim->primType == rt_gen)
01428                         subGrid->AddGeneric(*(RT_GenPtr*) entry->prim);
01429                     else
01430                         DBG_COUT << "illegal prim type" << endl;
01431                         
01432                     entry->prim->Stamp();
01433                 }
01434                 else
01435                     totalPrims--;
01436 
01437                 RT_Free(entry);
01438                 sMem -= sizeof(PrimEntry);
01439             }
01440                         
01441             // Remove the pushed primitives from the cell list, and replace
01442             // them with a grid entry.
01443 
01444             *primList->list = RT_Alloc(PrimEntry);
01445             sMem += sizeof(PrimEntry);
01446             (*primList->list)->next = PRIM_GRID_TAG;
01447             (*primList->list)->grid = subGrid;
01448         }
01449         
01450         addPrims = 0;
01451     }
01452 }
01453 
01454 
01455 // --- Support routines -------------------------------------------------------
01456 
01457 
01458 static Void Indent(ostream &s, Int n)
01459 {
01460     Int i;
01461     
01462     for (i = 0; i < n; i++)
01463         s << ' ';
01464 }
01465 
01466 Void RT_Grid::HierPrint(ostream &s, Int indent)
01467 {
01468     RT_Grid*    subGrid;
01469     
01470     Indent(s, indent);
01471     s << totalPrims << " prims, bbox: " << min << ' ' << max << endl;
01472     
01473     for(subGrid = subGrids; subGrid; subGrid = subGrid->next)
01474         subGrid->HierPrint(s, indent + 2);
01475 }
01476 
01477 
01478 // --- Memory methods ---------------------------------------------------------
01479 
01480 
01481 Void RT_Grid::SetMemLimit(Int maxKbs)
01482 {
01483     sMemLimit = 1024 * maxKbs;
01484 }
01485 
01486 GCLReal RT_Grid::GridMemoryUsage()
01487 {
01488     return(sMem / 1024.0);
01489 }
01490 
01491 GCLReal RT_Grid::MemoryUsage()
01492 {
01493     return((sMem + sTriMem + sGenMem + sPointMem) / 1024.0);
01494 }
01495 
01496 Void RT_Grid::DumpMemoryUsage()
01497 {
01498     RT_Grid     *sgrid;
01499 
01500     Int numGrids = 0;
01501     for (sgrid = subGrids; sgrid; sgrid = sgrid->next)
01502         numGrids++;
01503     
01504     cout << "Sub grids:           " << numGrids << endl;
01505     cout << "Grid pages:          " << grid.NumPages() << endl;
01506     cout << "Grid memory usage:   " << GridMemoryUsage() << "k" << endl;
01507     cout << "Triangle memory:     " << sTriMem / 1024.0 << "k" << endl;
01508     cout << "Generic memory:      " << sGenMem / 1024.0 << "k" << endl;
01509     cout << "Points memory:       " << sPointMem / 1024.0 << "k" << endl;
01510 }
01511 
01512 #ifdef RT_VIS
01513 
01514 // --- Visualisation ----------------------------------------------------------
01515 
01516 #include "gcl/Draw.h"
01517 
01518 Void RT_Grid::Draw(Renderer &r, Int level)
01519 {
01520     r.C(Colour4(HSVCol(hsvYellow + 60 * level, 1, 1), 0.2));
01521     FrameBox(r, min, max);
01522     r.C(Colour4(HSVCol(hsvOrange + 60 * level, 1, 1), 0.2));
01523     
01524     Vector  d1, d2;
01525     Point   p;
01526     Int     x, y, z;
01527     
01528     d1 = max - min;
01529     d2 = d1;
01530     d2[0] /= numCells[0];
01531     d2[1] /= numCells[1];
01532     d2[2] /= numCells[2];
01533 
01534     for (x = 0; x < numCells[0]; x++)
01535         for (y = 0; y < numCells[1]; y++)
01536             for (z = 0; z < numCells[2]; z++)
01537             {
01538                 if (grid[x * xSpan + y * ySpan + z])
01539                 {
01540                     p = min + Vector(x, y, z) * d2;
01541                     FrameBox(r, p, p + d2);
01542                 }
01543             }
01544 
01545     // Draw subgrids.
01546     RT_Grid *sgrid;
01547     level++;
01548 
01549     for (sgrid = subGrids; sgrid; sgrid = sgrid->next)
01550         sgrid->Draw(r, level);
01551 }
01552 
01553 #endif

Generated at Sat Aug 5 00:26:54 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000