예제 #1
0
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;
}
예제 #2
0
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;

}
예제 #3
0
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;
}