Panda3D
Loading...
Searching...
No Matches
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
20TypeHandle BoundingPlane::_type_handle;
21
22/**
23 *
24 */
25BoundingVolume *BoundingPlane::
26make_copy() const {
27 return new BoundingPlane(*this);
28}
29
30/**
31 *
32 */
33LPoint3 BoundingPlane::
34get_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 */
43void BoundingPlane::
44xform(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 */
55void BoundingPlane::
56output(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 */
71as_bounding_plane() const {
72 return this;
73}
74
75/**
76 *
77 */
78bool BoundingPlane::
79extend_other(BoundingVolume *other) const {
80 return other->extend_by_plane(this);
81}
82
83/**
84 *
85 */
86bool BoundingPlane::
87around_other(BoundingVolume *other,
88 const BoundingVolume **first,
89 const BoundingVolume **last) const {
90 return other->around_planes(first, last);
91}
92
93/**
94 *
95 */
96int BoundingPlane::
97contains_other(const BoundingVolume *other) const {
98 return other->contains_plane(this);
99}
100
101/**
102 *
103 */
104bool BoundingPlane::
105extend_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 */
121int BoundingPlane::
122contains_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 */
146int BoundingPlane::
147contains_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 */
195int BoundingPlane::
196contains_line(const BoundingLine *line) const {
197 return IF_possible;
198}
199
200/**
201 *
202 */
203int BoundingPlane::
204contains_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 */
234int BoundingPlane::
235contains_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}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition boundingBox.h:29
const LPoint3 & get_minq() const
An inline accessor for the minimum value.
Definition boundingBox.I:41
get_point
Returns the nth vertex of the rectangular solid.
Definition boundingBox.h:51
const LPoint3 & get_maxq() const
An inline accessor for the maximum value.
Definition boundingBox.I:52
This defines a bounding convex hexahedron.
get_point
Returns the nth vertex of the hexahedron.
This funny bounding volume is an infinite line with no thickness and extending to infinity in both di...
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
virtual const BoundingPlane * as_bounding_plane() const
Virtual downcast method.
BoundingPlane()
Constructs an empty "plane" that has no intersections.
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
bool is_empty() const
Any kind of volume might be empty.
bool is_infinite() const
The other side of the empty coin is an infinite volume.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.