bool Mesh::intersectKD(KDTree& node, const BBox& box, const FastRay& ray, IntersectionInfo& info) const
{
	if (node.axis == AXIS_NONE) {
		vector<int>& trios = *node.data.triangles;
		double foundlambda2 = 0, foundlambda3 = 0, dist = INF;
		int foundIdx = -1;
		for (int i = 0; i < (int) trios.size(); i++) {
			const Triangle& t = triangles[trios[i]];
			double l2, l3;
			if (intersectTriangleFast(ray, vertices[t.v[0]], t, l2, l3, dist)) {
				foundIdx = trios[i];
				foundlambda2 = l2;
				foundlambda3 = l3;
			}
		}
		if (foundIdx != -1) {
			Vector ip = ray.start + ray.dir * dist;
			if (box.inside(ip)) {
				fillInfo(ray, info, foundIdx, foundlambda2, foundlambda3, dist);
				return true;
			}
		}
		return false;
	} else {
		BBox boxChild[2];
		box.split(node.axis, node.sp, boxChild[0], boxChild[1]);
		int order[2] = { 0, 1 };
		if (ray.start[node.axis] > node.sp) swap(order[0], order[1]);
		// if the ray intersects the common wall between the two sub-boxes, then it invariably
		// intersects both boxes (we can skip the testIntersect() checks):
		// (see http://raytracing-bg.net/?q=node/68 )
		if (box.intersectWall(node.axis, node.sp, ray)) {
			if (intersectKD(node.data.children[order[0]], boxChild[order[0]], ray, info)) return true;
			return intersectKD(node.data.children[order[1]], boxChild[order[1]], ray, info);
		} else {
			// if the wall isn't hit, then we intersect exclusively one of the sub-boxes;
			// test one, if the test fails, then it's in the other:
			if (boxChild[order[0]].testIntersect(ray))
				return intersectKD(node.data.children[order[0]], boxChild[order[0]], ray, info);
			else
				return intersectKD(node.data.children[order[1]], boxChild[order[1]], ray, info);
		}
	}
	return false;
}
Exemple #2
0
bool Mesh::intersectKD(KDTreeNode& node, const BBox& bbox, const Ray& ray, IntersectionData& data)
{
	if (node.axis == AXIS_NONE) {
		// leaf node; try intersecting with the triangle list:
		bool found = false;
		for (size_t i = 0; i < node.triangles->size(); i++) {
			int triIdx = (*node.triangles)[i];
			if (intersectTriangle(ray, data, triangles[triIdx])) {
				found = true;
			}
		}
		// the found intersection has to be inside "our" BBox, otherwise we can miss a triangle,
		// as explained in the presentations:
		if (found && bbox.inside(data.p)) return true;
		return false;
	} else {
		// a in-node; intersect with the two children, starting with the closer one first:
		int childOrder[2] = { 0, 1 };
		if (ray.start[node.axis] > node.splitPos)
			swap(childOrder[0], childOrder[1]);
		//
		BBox childBB[2];
		bbox.split(node.axis, node.splitPos, childBB[0], childBB[1]);
		// name the children bboxen:
		BBox& firstBB = childBB[childOrder[0]];
		BBox& secondBB = childBB[childOrder[1]];
		KDTreeNode& firstChild = node.children[childOrder[0]];
		KDTreeNode& secondChild = node.children[childOrder[1]];
		// if the ray intersects the common wall between the two sub-boxes, then it invariably
		// intersects both boxes (we can skip the testIntersect() checks):
		// (see http://raytracing-bg.net/?q=node/68 )
		if (bbox.intersectWall(node.axis, node.splitPos, ray)) {
			if (intersectKD(firstChild, firstBB, ray, data)) return true;
			return intersectKD(secondChild, secondBB, ray, data);
		} else {
			// if the wall isn't hit, then we intersect exclusively one of the sub-boxes;
			// test one, if the test fails, then it's in the other:
			if (firstBB.testIntersect(ray))
				return intersectKD(firstChild, firstBB, ray, data);
			else
				return intersectKD(secondChild, secondBB, ray, data);
		}
	}
}