Panda3D
boundingPlane.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file boundingPlane.cxx
10  * @author drose
11  * @date 2005-08-19
12  */
13 
14 #include "boundingPlane.h"
15 #include "boundingSphere.h"
16 #include "boundingBox.h"
17 #include "boundingHexahedron.h"
18 #include "config_mathutil.h"
19 
20 TypeHandle BoundingPlane::_type_handle;
21 
22 /**
23  *
24  */
25 BoundingVolume *BoundingPlane::
26 make_copy() const {
27  return new BoundingPlane(*this);
28 }
29 
30 /**
31  *
32  */
33 LPoint3 BoundingPlane::
34 get_approx_center() const {
35  nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
36  nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f));
37  return _plane.get_point();
38 }
39 
40 /**
41  *
42  */
43 void BoundingPlane::
44 xform(const LMatrix4 &mat) {
45  nassertv(!mat.is_nan());
46 
47  if (!is_empty() && !is_infinite()) {
48  _plane.xform(mat);
49  }
50 }
51 
52 /**
53  *
54  */
55 void BoundingPlane::
56 output(std::ostream &out) const {
57  if (is_empty()) {
58  out << "bplane, empty";
59  } else if (is_infinite()) {
60  out << "bplane, infinite";
61  } else {
62  out << "bplane: " << _plane;
63  }
64 }
65 
66 /**
67  * Virtual downcast method. Returns this object as a pointer of the indicated
68  * type, if it is in fact that type. Returns NULL if it is not that type.
69  */
72  return this;
73 }
74 
75 /**
76  *
77  */
78 bool BoundingPlane::
79 extend_other(BoundingVolume *other) const {
80  return other->extend_by_plane(this);
81 }
82 
83 /**
84  *
85  */
86 bool BoundingPlane::
87 around_other(BoundingVolume *other,
88  const BoundingVolume **first,
89  const BoundingVolume **last) const {
90  return other->around_planes(first, last);
91 }
92 
93 /**
94  *
95  */
96 int BoundingPlane::
97 contains_other(const BoundingVolume *other) const {
98  return other->contains_plane(this);
99 }
100 
101 /**
102  *
103  */
104 bool BoundingPlane::
105 extend_by_plane(const BoundingPlane *plane) {
106  nassertr(!plane->is_empty() && !plane->is_infinite(), false);
107  nassertr(!is_infinite(), false);
108 
109  if (is_empty()) {
110  _plane = plane->get_plane();
111  _flags = 0;
112  } else {
113  _flags = F_infinite;
114  }
115  return true;
116 }
117 
118 /**
119  *
120  */
121 int BoundingPlane::
122 contains_sphere(const BoundingSphere *sphere) const {
123  nassertr(!is_empty() && !is_infinite(), 0);
124  nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0);
125 
126  PN_stdfloat r = sphere->get_radius();
127  PN_stdfloat d = _plane.dist_to_plane(sphere->get_center());
128 
129  if (d <= -r) {
130  // The sphere is completely behind the plane.
131  return IF_all | IF_possible | IF_some;
132 
133  } else if (d <= r) {
134  // The sphere is intersecting with the plane itself.
135  return IF_possible | IF_some;
136 
137  } else {
138  // The sphere is completely in front of the plane.
139  return IF_no_intersection;
140  }
141 }
142 
143 /**
144  *
145  */
146 int BoundingPlane::
147 contains_box(const BoundingBox *box) const {
148  nassertr(!is_empty() && !is_infinite(), 0);
149  nassertr(!box->is_empty() && !box->is_infinite(), 0);
150 
151  // Put the box inside a sphere for the purpose of this test.
152  const LPoint3 &min = box->get_minq();
153  const LPoint3 &max = box->get_maxq();
154  LPoint3 center = (min + max) * 0.5f;
155  PN_stdfloat radius2 = (max - center).length_squared();
156 
157  int result = IF_possible | IF_some | IF_all;
158 
159  PN_stdfloat dist = _plane.dist_to_plane(center);
160  PN_stdfloat dist2 = dist * dist;
161 
162  if (dist2 <= radius2) {
163  // The sphere is not completely behind this plane, but some of it is.
164 
165  // Look a little closer.
166  bool all_in = true;
167  bool all_out = true;
168  for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
169  if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) {
170  // This point is inside the plane.
171  all_out = false;
172  } else {
173  // This point is outside the plane.
174  all_in = false;
175  }
176  }
177 
178  if (all_out) {
179  return IF_no_intersection;
180  } else if (!all_in) {
181  result &= ~IF_all;
182  }
183 
184  } else if (dist >= 0.0f) {
185  // The sphere is completely in front of this plane.
186  return IF_no_intersection;
187  }
188 
189  return result;
190 }
191 
192 /**
193  *
194  */
195 int BoundingPlane::
196 contains_line(const BoundingLine *line) const {
197  return IF_possible;
198 }
199 
200 /**
201  *
202  */
203 int BoundingPlane::
204 contains_plane(const BoundingPlane *plane) const {
205  // We assume the plane normals are normalized.
206  LPlane other_plane = plane->get_plane();
207  PN_stdfloat dot = _plane.get_normal().dot(other_plane.get_normal());
208  if (dot >= 1.0) {
209  // The planes are parallel, with the same normal.
210  if (_plane.get_w() <= other_plane.get_w()) {
211  return IF_possible | IF_some | IF_all;
212  } else {
213  return IF_possible | IF_some;
214  }
215 
216  } else if (dot <= -1.0) {
217  // The planes are opposing.
218  if (_plane.get_w() >= -other_plane.get_w()) {
219  return IF_no_intersection;
220  } else {
221  return IF_possible | IF_some;
222  }
223 
224  } else {
225  // The planes are not parallel, so they inevitably intersect.
226  return IF_possible | IF_some;
227  }
228 }
229 
230 /**
231  * Double-dispatch support: called by contains_other() when the type we're
232  * testing for intersection is known to be a hexahedron.
233  */
234 int BoundingPlane::
235 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
236  nassertr(!is_empty() && !is_infinite(), 0);
237  nassertr(!hexahedron->is_empty() && !hexahedron->is_infinite(), 0);
238 
239  int result = IF_possible | IF_some | IF_all;
240 
241  bool all_in = true;
242  bool all_out = true;
243  for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
244  if (_plane.dist_to_plane(hexahedron->get_point(i)) < 0.0f) {
245  // This point is inside the plane.
246  all_out = false;
247  } else {
248  // This point is outside the plane.
249  all_in = false;
250  }
251  }
252 
253  if (all_out) {
254  return IF_no_intersection;
255  } else if (!all_in) {
256  result &= ~IF_all;
257  }
258 
259  return result;
260 }
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
get_point
Returns the nth vertex of the rectangular solid.
Definition: boundingBox.h:51
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_empty() const
Any kind of volume might be empty.
This defines a bounding sphere, consisting of a center and a radius.
bool is_infinite() const
The other side of the empty coin is an infinite volume.
virtual const BoundingPlane * as_bounding_plane() const
Virtual downcast method.
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
Definition: boundingPlane.h:28
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const LPoint3 & get_maxq() const
An inline accessor for the maximum value.
Definition: boundingBox.I:52
BoundingPlane()
Constructs an empty "plane" that has no intersections.
Definition: boundingPlane.I:18
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_point
Returns the nth vertex of the hexahedron.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This defines a bounding convex hexahedron.
This funny bounding volume is an infinite line with no thickness and extending to infinity in both di...
Definition: boundingLine.h:29
const LPoint3 & get_minq() const
An inline accessor for the minimum value.
Definition: boundingBox.I:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.