bool GridAccel::Intersect(const Ray &ray, Intersection *isect) const { if (!gridForRefined) { // NOBOOK rayTests.Add(0, 1); // NOBOOK rayHits.Add(0, 1); // NOBOOK } // NOBOOK // Check ray against overall grid bounds float rayT; if (bounds.Inside(ray(ray.mint))) rayT = ray.mint; else if (!bounds.IntersectP(ray, &rayT)) return false; Point gridIntersect = ray(rayT); // Get ray mailbox id int rayId = ++curMailboxId; // Set up 3D DDA for ray float NextCrossingT[3], DeltaT[3]; int Step[3], Out[3], Pos[3]; for (int axis = 0; axis < 3; ++axis) { // Compute current voxel for axis Pos[axis] = PosToVoxel(gridIntersect, axis); if (ray.d[axis] >= 0) { // Handle ray with positive direction for voxel stepping NextCrossingT[axis] = rayT + (VoxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = Width[axis] / ray.d[axis]; Step[axis] = 1; Out[axis] = NVoxels[axis]; } else { // Handle ray with negative direction for voxel stepping NextCrossingT[axis] = rayT + (VoxelToPos(Pos[axis], axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = -Width[axis] / ray.d[axis]; Step[axis] = -1; Out[axis] = -1; } } // Walk ray through voxel grid bool hitSomething = false; for (;;) { Voxel *voxel = voxels[Offset(Pos[0], Pos[1], Pos[2])]; if (voxel != NULL) hitSomething |= voxel->Intersect(ray, isect, rayId); // Advance to next voxel // Find _stepAxis_ for stepping to next voxel int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) + ((NextCrossingT[0] < NextCrossingT[2]) << 1) + ((NextCrossingT[1] < NextCrossingT[2])); const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 }; int stepAxis = cmpToAxis[bits]; if (ray.maxt < NextCrossingT[stepAxis]) break; Pos[stepAxis] += Step[stepAxis]; if (Pos[stepAxis] == Out[stepAxis]) break; NextCrossingT[stepAxis] += DeltaT[stepAxis]; } return hitSomething; }
bool GridAccel::Intersect(const Ray &ray, Intersection *isect) const { PBRT_GRID_INTERSECTION_TEST(const_cast<GridAccel *>(this), const_cast<Ray *>(&ray)); // Check ray against overall grid bounds float rayT; if (bounds.Inside(ray(ray.mint))) rayT = ray.mint; else if (!bounds.IntersectP(ray, &rayT)) { PBRT_GRID_RAY_MISSED_BOUNDS(); return false; } Point gridIntersect = ray(rayT); // Set up 3D DDA for ray float NextCrossingT[3], DeltaT[3]; int Step[3], Out[3], Pos[3]; for (int axis = 0; axis < 3; ++axis) { // Compute current voxel for axis Pos[axis] = posToVoxel(gridIntersect, axis); if (ray.d[axis] >= 0) { // Handle ray with positive direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = Width[axis] / ray.d[axis]; Step[axis] = 1; Out[axis] = NVoxels[axis]; } else { // Handle ray with negative direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis], axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = -Width[axis] / ray.d[axis]; Step[axis] = -1; Out[axis] = -1; } } // Walk ray through voxel grid // Acquire reader mutex for grid traversal RWMutexLock lock(*rwMutex, READ); bool hitSomething = false; for (;;) { // Check for intersection in current voxel and advance to next Voxel *voxel = voxels[offset(Pos[0], Pos[1], Pos[2])]; PBRT_GRID_RAY_TRAVERSED_VOXEL(Pos, voxel ? voxel->size() : 0); if (voxel != NULL) hitSomething |= voxel->Intersect(ray, isect, lock); // Advance to next voxel // Find _stepAxis_ for stepping to next voxel int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) + ((NextCrossingT[0] < NextCrossingT[2]) << 1) + ((NextCrossingT[1] < NextCrossingT[2])); const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 }; int stepAxis = cmpToAxis[bits]; if (ray.maxt < NextCrossingT[stepAxis]) break; Pos[stepAxis] += Step[stepAxis]; if (Pos[stepAxis] == Out[stepAxis]) break; NextCrossingT[stepAxis] += DeltaT[stepAxis]; } return hitSomething; }