#include "common/ray.h" #include "primitive/box.h" #include #include // Constructor ///////////////////////////////////////////////////////////////// Box::Box(std::shared_ptr const &shader) : Primitive(shader), size(Vector3d(1, 1, 1)) {} 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! // Determine whether the ray intersects the box Vector3d minBounds(this->minimumBounds(0), this->minimumBounds(1), this->minimumBounds(2)); Vector3d maxBounds(this->maximumBounds(0), this->maximumBounds(1), this->maximumBounds(2)); Vector3d tMin = intersectionParameter(minBounds, ray); Vector3d tMax = intersectionParameter(maxBounds, ray); 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])); float tIn = std::max(std::max(tInAll[0], tInAll[1]), tInAll[2]); float tOut = std::min(std::min(tOutAll[0], tOutAll[1]), tOutAll[2]); 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 //////////////////////////////////////////////////////////////// float Box::minimumBounds(int dimension) const { return this->center[dimension] - this->size[dimension] / 2; } float Box::maximumBounds(int dimension) const { return this->center[dimension] + this->size[dimension] / 2; }