diff --git a/primitive/box.cpp b/primitive/box.cpp index 83a2c75..9780b85 100644 --- a/primitive/box.cpp +++ b/primitive/box.cpp @@ -10,22 +10,84 @@ Box::Box(std::shared_ptr const &shader) : Primitive(shader), size(Vector Box::Box(Vector3d const ¢er, Vector3d const &size, std::shared_ptr const &shader) : Primitive(shader), center(center), size(size) {} +// Helper functions ///////////////////////////////////////////////////////// + +float intersectionParameterDimension(Vector3d bounds, Ray &ray, int dimension) +{ + return (bounds[dimension] - ray.origin[dimension]) / ray.direction[dimension]; +} + +Vector3d intersectionParameter(Vector3d bounds, Ray &ray) +{ + return Vector3d(intersectionParameterDimension(bounds, ray, 0), + intersectionParameterDimension(bounds, ray, 1), + intersectionParameterDimension(bounds, ray, 2)); +} + // Primitive functions ///////////////////////////////////////////////////////// -bool Box::intersect(Ray &ray) const { - // IMPLEMENT ME! +bool Box::intersect(Ray &ray) const +{ + // IMPLEMENT ME! - // Determine whether the ray intersects the box + // Determine whether the ray intersects the box - // Test whether this is the foremost primitive in front of the camera + Vector3d minBounds(this->minimumBounds(0), this->minimumBounds(1), this->minimumBounds(2)); + Vector3d maxBounds(this->maximumBounds(0), this->maximumBounds(1), this->maximumBounds(2)); - // (Optional for now) Calculate the normal + Vector3d tMin = intersectionParameter(minBounds, ray); + Vector3d tMax = intersectionParameter(maxBounds, ray); - // (Optional for now) Calculate the surface position + Vector3d tInAll = Vector3d(std::min(tMin[0], tMax[0]), std::min(tMin[1], tMax[1]), std::min(tMin[2], tMax[2])); + Vector3d tOutAll = Vector3d(std::max(tMin[0], tMax[0]), std::max(tMin[1], tMax[1]), std::max(tMin[2], tMax[2])); - // Set the new length and the current primitive + float tIn = std::max(std::max(tInAll[0], tInAll[1]), tInAll[2]); + float tOut = std::min(std::min(tOutAll[0], tOutAll[1]), tOutAll[2]); - return false; + if (tIn > tOut || tOut < 0) + { + return false; + } + + float t = tIn; + + // Test whether this is the foremost primitive in front of the camera + if (t >= ray.length) + { + return false; + } + + // (Optional for now) Calculate the normal + // On what side of the box did the ray hit? + Vector3d normal; + if (tInAll[0] == tIn) + { + normal = Vector3d(1, 0, 0); + } + else if (tInAll[1] == tIn) + { + normal = Vector3d(0, 1, 0); + } + else // tInAll[2] == tIn + { + normal = Vector3d(0, 0, 1); + } + + // Make sure sign is correct + if (dotProduct(ray.direction, normal) > 0) + { + normal = -normal; + } + + ray.normal = normalized(normal); + + // (Optional for now) Calculate the surface position + + // Set the new length and the current primitive + ray.length = t; + ray.primitive = this; + + return false; } // Bounding box ////////////////////////////////////////////////////////////////