示例#1
0
TraversalState BVH::Traverse(TraversalState state, const SlimRay& ray, HitRecord* nearest,
 function<bool (uint32_t index, const SlimRay& ray, HitRecord* hit, bool* request_suspend)> intersector,
 bool resume) {
    // Precompute the inverse direction of the ray.
    vec3 inv_dir(1.0f / ray.direction.x,
                 1.0f / ray.direction.y,
                 1.0f / ray.direction.z);

    // Initialize traversal based on passed state.
    TraversalState traversal = state;
    bool request_suspend = false;

    if (resume) {
        if (traversal.state == TraversalState::State::FROM_PARENT) {
            goto resume_parent;
        } else if (traversal.state == TraversalState::State::FROM_SIBLING) {
            goto resume_sibling;
        } else {
            TERRLN("Must be in FROM_PARENT or FROM_SIBLING state to resume traversal!");
        }
    }

    while (true) {
        switch (traversal.state) {
            case TraversalState::State::FROM_PARENT:
                if (!BoundingHit(_nodes[traversal.current].bounds, ray, inv_dir, nearest->t)) {
                    // Ray missed the near child, try the far child.
                    traversal.current = Sibling(traversal.current);
                    traversal.state = TraversalState::State::FROM_SIBLING;
                } else if (_nodes[traversal.current].leaf) {
                    // Ray hit the near child and it's a leaf node.
                    request_suspend = false;
                    traversal.hit = intersector(_nodes[traversal.current].index, ray, nearest, &request_suspend) || traversal.hit;
                    if (request_suspend) goto suspend_traversal;
resume_parent:      traversal.current = Sibling(traversal.current);
                    traversal.state = TraversalState::State::FROM_SIBLING;
                } else {
                    // Ray hit the near child and it's an interior node.
                    traversal.current = NearChild(traversal.current, ray.direction);
                    traversal.state = TraversalState::State::FROM_PARENT;
                }
                break;

            case TraversalState::State::FROM_SIBLING:
                if (!BoundingHit(_nodes[traversal.current].bounds, ray, inv_dir, nearest->t)) {
                    // Ray missed the far child, backtrack to the parent.
                    traversal.current = _nodes[traversal.current].parent;
                    traversal.state = TraversalState::State::FROM_CHILD;
                } else if (_nodes[traversal.current].leaf) {
                    // Ray hit the far child and it's a leaf node.
                    request_suspend = false;
                    traversal.hit = intersector(_nodes[traversal.current].index, ray, nearest, &request_suspend) || traversal.hit;
                    if (request_suspend) goto suspend_traversal;
resume_sibling:     traversal.current = _nodes[traversal.current].parent;
                    traversal.state = TraversalState::State::FROM_CHILD;
                } else {
                    // Ray hit the far child and it's an interior node.
                    traversal.current = NearChild(traversal.current, ray.direction);
                    traversal.state = TraversalState::State::FROM_PARENT;
                }
                break;

            case TraversalState::State::FROM_CHILD:
                if (traversal.current == 0) {
                    // Traversal has finished.
                    return traversal;
                }
                if (traversal.current == NearChild(_nodes[traversal.current].parent, ray.direction)) {
                    // Coming back up through the near child, so traverse
                    // to the far child.
                    traversal.current = Sibling(traversal.current);
                    traversal.state = TraversalState::State::FROM_SIBLING;
                } else {
                    // Coming back up through the far child, so continue
                    // backtracking through the parent.
                    traversal.current = _nodes[traversal.current].parent;
                    traversal.state = TraversalState::State::FROM_CHILD;
                }
                break;

            default:
                TERRLN("BVH traversal in unknown state!");
                exit(EXIT_FAILURE);
                break;
        }
    }

    /// Shouldn't ever get here...
    TERRLN("Unexpected exit path in BVH traversal.");
    return TraversalState();

suspend_traversal:
    return traversal;
}
示例#2
0
bool BoundingBox::IntersectP(const Ray & ray)
{
	//shadow ray and reflected ray returns false mistakenly
	//probably because they are in the box


	Vector3f pos(ray.getStartPosition());
	Vector3f inv_dir(ray.getInvDirection());


	float tx1 = (min_pos.x() - pos.x())*inv_dir.x();
	float tx2 = (max_pos.x() - pos.x())*inv_dir.x();

	float tmin = min(tx1, tx2);
	float tmax = max(tx1, tx2);

	float ty1 = (min_pos.y() - pos.y())*inv_dir.y();
	float ty2 = (max_pos.y() - pos.y())*inv_dir.y();

	tmin = max(tmin, min(ty1, ty2));
	tmax = min(tmax, max(ty1, ty2));


	//TODO, t should >0

	if (tmax >= tmin)
	{
		float tz1 = (min_pos.z() - pos.z())*inv_dir.z();
		float tz2 = (max_pos.z() - pos.z())*inv_dir.z();

		tmin = max(tmin, min(tz1, tz2));
		tmax = min(tmax, max(tz1, tz2));


		//To confirm?? tmax>0
		if(tmax >= tmin && tmax > 0)
		{
			//the line of ray will intersect
			//but maybe the t < 0

			

			return true;
		}
	}



	return false;






	
	//Vector3f dir(ray.getDirection());
	//Vector3f inv_dir(ray.getInvDirection());


	//float tx1 = (min_pos.x() - dir.x())*inv_dir.x();
	//float tx2 = (max_pos.x() - dir.x())*inv_dir.x();

	//float tmin = min(tx1, tx2);
	//float tmax = max(tx1, tx2);

	//float ty1 = (min_pos.y() - dir.y())*inv_dir.y();
	//float ty2 = (max_pos.y() - dir.y())*inv_dir.y();

	//tmin = max(tmin, min(ty1, ty2));
	//tmax = min(tmax, max(ty1, ty2));


	////TODO, t should >0

	//if (tmax >= tmin)
	//{
	//	float tz1 = (min_pos.z() - dir.z())*inv_dir.z();
	//	float tz2 = (max_pos.z() - dir.z())*inv_dir.z();

	//	tmin = max(tmin, min(tz1, tz2));
	//	tmax = min(tmax, max(tz1, tz2));


	//	if(tmax >= tmin)
	//	{
	//		//the line of ray will intersect
	//		//but maybe the t < 0

	//		//TODO
	//		return true;
	//	}
	//}



	//return false;



}