// GridAccel Method Definitions GridAccel::GridAccel(const vector<Reference<Primitive> > &p, bool forRefined, bool refineImmediately) : gridForRefined(forRefined) { // Initialize _prims_ with primitives for grid vector<Reference<Primitive> > prims; if (refineImmediately) for (u_int i = 0; i < p.size(); ++i) p[i]->FullyRefine(prims); else prims = p; // Initialize mailboxes for grid nMailboxes = prims.size(); mailboxes = (MailboxPrim *)AllocAligned(nMailboxes * sizeof(MailboxPrim)); for (u_int i = 0; i < nMailboxes; ++i) new (&mailboxes[i]) MailboxPrim(prims[i]); // Compute bounds and choose grid resolution for (u_int i = 0; i < prims.size(); ++i) bounds = Union(bounds, prims[i]->WorldBound()); Vector delta = bounds.pMax - bounds.pMin; // Find _voxelsPerUnitDist_ for grid int maxAxis = bounds.MaximumExtent(); float invMaxWidth = 1.f / delta[maxAxis]; Assert(invMaxWidth > 0.f); // NOBOOK float cubeRoot = 3.f * powf(float(prims.size()), 1.f/3.f); float voxelsPerUnitDist = cubeRoot * invMaxWidth; for (int axis = 0; axis < 3; ++axis) { NVoxels[axis] = Round2Int(delta[axis] * voxelsPerUnitDist); NVoxels[axis] = Clamp(NVoxels[axis], 1, 64); } // Compute voxel widths and allocate voxels for (int axis = 0; axis < 3; ++axis) { Width[axis] = delta[axis] / NVoxels[axis]; InvWidth[axis] = (Width[axis] == 0.f) ? 0.f : 1.f / Width[axis]; } int nVoxels = NVoxels[0] * NVoxels[1] * NVoxels[2]; voxels = (Voxel **)AllocAligned(nVoxels * sizeof(Voxel *)); memset(voxels, 0, nVoxels * sizeof(Voxel *)); // Add primitives to grid voxels for (u_int i = 0; i < prims.size(); ++i) { // Find voxel extent of primitive BBox pb = prims[i]->WorldBound(); int vmin[3], vmax[3]; for (int axis = 0; axis < 3; ++axis) { vmin[axis] = PosToVoxel(pb.pMin, axis); vmax[axis] = PosToVoxel(pb.pMax, axis); } // Add primitive to overlapping voxels for (int z = vmin[2]; z <= vmax[2]; ++z) for (int y = vmin[1]; y <= vmax[1]; ++y) for (int x = vmin[0]; x <= vmax[0]; ++x) { int offset = Offset(x, y, z); if (!voxels[offset]) { // Allocate new voxel and store primitive in it voxels[offset] = new (voxelArena) Voxel(&mailboxes[i]); } else { // Add primitive to already-allocated voxel voxels[offset]->AddPrimitive(&mailboxes[i]); } } static StatsRatio nPrimitiveVoxels("Grid Accelerator", // NOBOOK "Voxels covered vs # / primitives"); // NOBOOK nPrimitiveVoxels.Add((1 + vmax[0]-vmin[0]) * (1 + vmax[1]-vmin[1]) * // NOBOOK (1 + vmax[2]-vmin[2]), 1); // NOBOOK } // Update grid statistics static StatsPercentage nEmptyVoxels("Grid Accelerator", "Empty voxels"); static StatsRatio avgPrimsInVoxel("Grid Accelerator", "Average # of primitives in voxel"); static StatsCounter maxPrimsInVoxel("Grid Accelerator", "Max # of primitives in a grid voxel"); nEmptyVoxels.Add(0, NVoxels[0] * NVoxels[1] * NVoxels[2]); avgPrimsInVoxel.Add(0,NVoxels[0] * NVoxels[1] * NVoxels[2]); for (int z = 0; z < NVoxels[2]; ++z) for (int y = 0; y < NVoxels[1]; ++y) for (int x = 0; x < NVoxels[0]; ++x) { int offset = Offset(x, y, z); if (!voxels[offset]) nEmptyVoxels.Add(1, 0); else { int nPrims = voxels[offset]->nPrimitives; maxPrimsInVoxel.Max(nPrims); avgPrimsInVoxel.Add(nPrims, 0); } } }
void PBRT_KDTREE_CREATED_LEAF(int nprims, int depth) { ++kdTreeLeafNodes; kdTreeMaxPrims.Max(nprims); kdTreeMaxDepth.Max(depth); }