3de87e4e3a8ac0bb5f41334321d2c04bfb98c980
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
12 #ifndef _MOOF_PLANE_HH_
13 #define _MOOF_PLANE_HH_
15 /**
16 * \file plane.hh
17 * Classes and functions related to planes.
18 */
20 #include <moof/math.hh>
21 #include <moof/shape.hh>
24 namespace moof {
27 template <int D> class aabb;
28 template <int D> class sphere;
31 /**
32 * A plane in 3-space defined by the equation Ax + By + Cz = D, where [A,
33 * B, C] is normal to the plane.
34 */
35 struct plane : public shape<3>
36 {
37 vector3 normal;
38 scalar d;
40 enum halfspace
41 {
42 negative = -1,
43 intersecting = 0,
44 positive = 1
45 };
47 plane() {}
48 plane(const vector3& vector, scalar scalar) :
49 normal(vector),
50 d(scalar) {}
51 plane(scalar a, scalar b, scalar c, scalar scalar) :
52 normal(a, b, c),
53 d(scalar) {}
56 bool intersect_ray(const ray<3>& ray, ray<3>::contact& hit)
57 {
58 // solve: [(ray.point + t*ray.direction) dot normal] + d = 0
60 scalar denom = dot(ray.direction, normal);
62 // check for parallel condition
63 if (denom == SCALAR(0.0))
64 {
65 if (is_equal(dot(ray.point, normal), -d))
66 {
67 // the ray lies on the plane
68 hit.distance = SCALAR(0.0);
69 hit.normal.set(0.0, 0.0, 0.0);
70 return true;
71 }
73 // no solution
74 return false;
75 }
77 scalar numer = dot(ray.point, normal) + d;
78 hit.distance = -numer / denom;
79 if (hit.distance < SCALAR(0.0)) return false;
81 if (numer >= 0.0) hit.normal = normal;
82 else hit.normal = -normal;
83 return true;
84 }
87 /* Causes the normal of the plane to become normalized. The scalar may
88 * also be changed to keep the equation true. Word to the wise: don't
89 * normalize a plane if the normal is the zero vector.
90 */
91 void normalize()
92 {
93 scalar mag = normal.length();
95 normal /= mag;
96 d /= mag;
97 }
99 /**
100 * Determine the shortest distance between a point and the plane.
101 */
102 scalar distance_to_point(const vector3& point) const
103 {
104 return dot(point, normal) + d;
105 }
107 halfspace intersects(const vector3& point) const
108 {
109 scalar distance = distance_to_point(point);
111 if (is_equal(distance, 0.0)) return intersecting;
112 else if (distance < 0.0) return negative;
113 else return positive;
114 }
116 halfspace intersects(const aabb<3>& aabb) const;
117 halfspace intersects(const sphere<3>& sphere) const;
118 };
121 } // namespace moof
123 #endif // _MOOF_PLANE_HH_