bool GridAccel::IntersectP(const Ray &ray) const { if (!gridForRefined) { // NOBOOK rayTests.Add(0, 1); // NOBOOK rayHits.Add(0, 1); // NOBOOK } // NOBOOK int rayId = ++curMailboxId; // 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); // 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 grid for shadow ray for (;;) { int offset = Offset(Pos[0], Pos[1], Pos[2]); Voxel *voxel = voxels[offset]; if (voxel && voxel->IntersectP(ray, rayId)) return true; // 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 false; }
bool ShapeBezierSurface::Intersect(const Ray& objectRay, double* tHit, DifferentialGeometry* dg) const { double tHitInitial = objectRay.maxt; double tHitShape = objectRay.maxt; DifferentialGeometry dgShape; //int surface = 0; for( int surface = 0; surface < m_surfacesVector.size(); ++surface ) { //Check if the ray intersects with the patch BoundingBox BBox bbox = m_surfacesVector[surface]->GetComputeBBox(); bool intersectBBox = bbox.IntersectP( objectRay ); if( intersectBBox ) { double tHitPatch; DifferentialGeometry dgPatch; bool intersected = m_surfacesVector[surface]->Intersect( objectRay, &tHitPatch, &dgPatch ); if( intersected && tHitShape > tHitPatch ) { tHitShape = tHitPatch; dgShape = dgPatch; } } } if( tHitShape < tHitInitial ) { dgShape.pShape = this; *tHit = tHitShape; *dg = dgShape; return true; } return false; }
bool KdTreeAccel::IntersectP(const Ray &ray) const { // Compute initial parametric range of ray inside kd-tree extent float tmin, tmax; if (!bounds.IntersectP(ray, &tmin, &tmax)) return false; // Prepare to traverse kd-tree for ray int rayId = curMailboxId++; Vector invDir(1.f/ray.d.x, 1.f/ray.d.y, 1.f/ray.d.z); #define MAX_TODO 64 KdToDo todo[MAX_TODO]; int todoPos = 0; const KdAccelNode *node = &nodes[0]; while (node != NULL) { // Update kd-tree shadow ray traversal statistics //static StatsCounter nodesTraversed("Kd-Tree Accelerator", // "Number of kd-tree nodes traversed by shadow rays"); //++nodesTraversed; if (node->IsLeaf()) { // Check for shadow ray intersections inside leaf node u_int nPrimitives = node->nPrimitives(); if (nPrimitives == 1) { MailboxPrim *mp = node->onePrimitive; if (mp->lastMailboxId != rayId) { mp->lastMailboxId = rayId; if (mp->primitive->IntersectP(ray)) return true; } } else { MailboxPrim **prims = node->primitives; for (u_int i = 0; i < nPrimitives; ++i) { MailboxPrim *mp = prims[i]; if (mp->lastMailboxId != rayId) { mp->lastMailboxId = rayId; if (mp->primitive->IntersectP(ray)) return true; } } } // Grab next node to process from todo list if (todoPos > 0) { --todoPos; node = todo[todoPos].node; tmin = todo[todoPos].tmin; tmax = todo[todoPos].tmax; } else break; } else { // Process kd-tree interior node // Compute parametric distance along ray to split plane int axis = node->SplitAxis(); float tplane = (node->SplitPos() - ray.o[axis]) * invDir[axis]; // Get node children pointers for ray const KdAccelNode *firstChild, *secondChild; int belowFirst = (ray.o[axis] < node->SplitPos()) || (ray.o[axis] == node->SplitPos() && ray.d[axis] >= 0); if (belowFirst) { firstChild = node + 1; secondChild = &nodes[node->aboveChild]; } else { firstChild = &nodes[node->aboveChild]; secondChild = node + 1; } // Advance to next child node, possibly enqueue other child if (tplane > tmax || tplane <= 0) node = firstChild; else if (tplane < tmin) node = secondChild; else { // Enqueue _secondChild_ in todo list todo[todoPos].node = secondChild; todo[todoPos].tmin = tplane; todo[todoPos].tmax = tmax; ++todoPos; node = firstChild; tmax = tplane; } } } return false; }