#include "Box.h" #include "util/Solver.h" #include #include using namespace std; #define FP_EQUAL(x,y) (fabs((x)-(y)) < 0.000001) Box::Box(refptr size) { m_size = *size; m_size[0] = fabs(m_size[0]) / 2.0; m_size[1] = fabs(m_size[1]) / 2.0; m_size[2] = fabs(m_size[2]) / 2.0; } Shape::IntersectionList Box::intersect(refptr _this, const Ray & ray) { Ray ray_inv = m_inverse.transform_ray(ray); IntersectionList res; /* * Ray equation: R = R0 + tRd * x = R0x + tRdx * y = R0y + tRdy * z = R0z + tRdz * Side equation: x - size_x = 0 * Combined: R0x + (t)Rdx - size_x = 0 */ for (int dim = 0; dim < 3; dim++) { for (int side = -1; side <= 1; side += 2) { LinearSolver solver(ray_inv.getDirection()[dim], ray_inv.getOrigin()[dim] + side * m_size[dim]); Solver::Result solutions = solver.solve(); for (int i = 0; i < solutions.numResults; i++) { if (solutions.results[i] >= 0.0) { Vector isect_point = ray_inv[solutions.results[i]]; if ( (dim == 0 || fabs(isect_point[0]) <= m_size[0]) && (dim == 1 || fabs(isect_point[1]) <= m_size[1]) && (dim == 2 || fabs(isect_point[2]) <= m_size[2]) ) { Vector normal(0, 0, -1); if ( FP_EQUAL(isect_point[0], m_size[0]) ) normal = Vector(1, 0, 0); else if ( FP_EQUAL(isect_point[0], -m_size[0]) ) normal = Vector(-1, 0, 0); else if ( FP_EQUAL(isect_point[1], m_size[1]) ) normal = Vector(0, 1, 0); else if ( FP_EQUAL(isect_point[1], -m_size[1]) ) normal = Vector(0, -1, 0); else if ( FP_EQUAL(isect_point[2], m_size[2]) ) normal = Vector(0, 0, 1); res.add(Intersection(_this, m_transform.transform_point(isect_point), m_transform.transform_normal(normal)) ); } } } } } return res; } refptr Box::clone() { return new Box(*this); }