void PhotonProcess::operator()(const Photon &photon, float distSquared, float &maxDistSquared) const { static StatsPercentage discarded("Photon Map", "Discarded photons"); // NOBOOK discarded.Add(0, 1); // NOBOOK if (foundPhotons < nLookup) { // Add photon to unordered array of photons photons[foundPhotons++] = ClosePhoton(&photon, distSquared); if (foundPhotons == nLookup) { std::make_heap(&photons[0], &photons[nLookup]); maxDistSquared = photons[0].distanceSquared; } } else { // Remove most distant photon from heap and add new photon discarded.Add(1, 0); // NOBOOK std::pop_heap(&photons[0], &photons[nLookup]); photons[nLookup-1] = ClosePhoton(&photon, distSquared); std::push_heap(&photons[0], &photons[nLookup]); maxDistSquared = photons[0].distanceSquared; } }
bool Triangle::Intersect(const Ray *ray, float *tHit, Intersection *isect) const { // Initialize triangle intersection statistics static StatsPercentage triangleHits("Geometry", "Triangle Ray Intersections"); // Update triangle tests count triangleHits.Add(0, 1); // Compute $\VEC{s}_1$ // Get triangle vertices in _p1_, _p2_, and _p3_ const Point &p1 = mesh->p[v[0]]; const Point &p2 = mesh->p[v[1]]; const Point &p3 = mesh->p[v[2]]; Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = Cross(ray->d, e2); float divisor = Dot(s1, e1); if (divisor == 0.) return false; float invDivisor = 1.f / divisor; // Compute first barycentric coordinate Vector d = ray->o - p1; float b1 = Dot(d, s1) * invDivisor; if (b1 < 0. || b1 > 1.) return false; // Compute second barycentric coordinate Vector s2 = Cross(d, e1); float b2 = Dot(ray->d, s2) * invDivisor; if (b2 < 0. || b1 + b2 > 1.) return false; // Compute _t_ to intersection point float t = Dot(e2, s2) * invDivisor; if (t < ray->mint || t > ray->maxt) return false; *tHit = t; return true; }
bool IrradianceCache::InterpolateIrradiance(const Scene *scene, const Point &p, const Normal &n, Spectrum *E) const { if (!octree) return false; IrradProcess proc(n, maxError); octree->Lookup(p, proc); // Update irradiance cache lookup statistics static StatsPercentage nSuccessfulLookups("Irradiance Cache", "Successful irradiance cache lookups"); static StatsRatio nSamplesFound("Irradiance Cache", "Irradiance samples found per successful lookup"); static StatsRatio nSamplesChecked("Irradiance Cache", "Irradiance samples checked per lookup"); nSuccessfulLookups.Add(proc.Successful() ? 1 : 0, 1); nSamplesFound.Add(proc.nFound, 1); nSamplesChecked.Add(proc.samplesChecked, 1); if (!proc.Successful()) return false; *E = proc.GetIrradiance(); return true; }
// 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_RAY_TRIANGLE_INTERSECTIONP_HIT(const Ray *, float t) { rayTriIntersectionPs.Add(1, 0); }
void PBRT_RAY_TRIANGLE_INTERSECTIONP_TEST(const Ray *, const Triangle *) { rayTriIntersectionPs.Add(0, 1); }