/*] Copyright (c) 2009-2011, Charles McGarvey [***************************** **] All rights reserved. * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * *****************************************************************************/ #ifndef _MOOF_PLANE_HH_ #define _MOOF_PLANE_HH_ #include #include /** * \file plane.hh * Classes and functions related to planes. */ namespace moof { // forward declarations template class aabb; template class sphere; /** * A plane in 3-space defined by the equation Ax + By + Cz = D, where [A, B, * C] is normal to the plane. */ struct plane : public shape<3> { vector3 normal; scalar d; enum halfspace { negative = -1, intersecting = 0, positive = 1 }; plane() {} plane(const vector3& vector, scalar scalar) : normal(vector), d(scalar) {} plane(scalar a, scalar b, scalar c, scalar scalar) : normal(a, b, c), d(scalar) {} bool intersect_ray(const ray3& ray, ray3::contact& hit) { // solve: [(ray.point + t*ray.direction) dot normal] + d = 0 scalar denom = dot(ray.direction, normal); // check for parallel condition if (denom == SCALAR(0.0)) { if (is_equal(dot(ray.point, normal), -d)) { // the ray lies on the plane hit.distance = SCALAR(0.0); hit.normal.set(0.0, 0.0, 0.0); return true; } // no solution return false; } scalar numer = dot(ray.point, normal) + d; hit.distance = -numer / denom; if (hit.distance < SCALAR(0.0)) return false; if (numer >= 0.0) hit.normal = normal; else hit.normal = -normal; return true; } /* Causes the normal of the plane to become normalized. The scalar may * also be changed to keep the equation true. Word to the wise: don't * normalize a plane if the normal is the zero vector. */ void normalize() { scalar mag = normal.length(); normal /= mag; d /= mag; } /** * Determine the shortest distance between a point and the plane. */ scalar distance_to_point(const vector3& point) const { return dot(point, normal) + d; } halfspace intersects(const vector3& point) const { scalar distance = distance_to_point(point); if (is_equal(distance, 0.0)) return intersecting; else if (distance < 0.0) return negative; return positive; } halfspace intersects(const aabb<3>& aabb) const; halfspace intersects(const sphere<3>& sphere) const; }; } // namespace moof #endif // _MOOF_PLANE_HH_