--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* 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_
+
+/**
+ * \file plane.hh
+ * Classes and functions related to planes.
+ */
+
+#include <moof/math.hh>
+#include <moof/shape.hh>
+
+
+namespace moof {
+
+
+template <int D> class aabb;
+template <int D> 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 ray<3>& ray, ray<3>::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;
+ else return positive;
+ }
+
+ halfspace intersects(const aabb<3>& aabb) const;
+ halfspace intersects(const sphere<3>& sphere) const;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_PLANE_HH_
+