Panda3D
|
00001 // Filename: boundingPlane.cxx 00002 // Created by: drose (19Aug05) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "boundingPlane.h" 00016 #include "boundingSphere.h" 00017 #include "config_mathutil.h" 00018 00019 TypeHandle BoundingPlane::_type_handle; 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: BoundingPlane::make_copy 00023 // Access: Public, Virtual 00024 // Description: 00025 //////////////////////////////////////////////////////////////////// 00026 BoundingVolume *BoundingPlane:: 00027 make_copy() const { 00028 return new BoundingPlane(*this); 00029 } 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: BoundingPlane::get_approx_center 00033 // Access: Public, Virtual 00034 // Description: 00035 //////////////////////////////////////////////////////////////////// 00036 LPoint3 BoundingPlane:: 00037 get_approx_center() const { 00038 nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f)); 00039 nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f)); 00040 return _plane.get_point(); 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: BoundingPlane::xform 00045 // Access: Public, Virtual 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 void BoundingPlane:: 00049 xform(const LMatrix4 &mat) { 00050 nassertv(!mat.is_nan()); 00051 00052 if (!is_empty() && !is_infinite()) { 00053 _plane.xform(mat); 00054 } 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: BoundingPlane::output 00059 // Access: Public, Virtual 00060 // Description: 00061 //////////////////////////////////////////////////////////////////// 00062 void BoundingPlane:: 00063 output(ostream &out) const { 00064 if (is_empty()) { 00065 out << "bplane, empty"; 00066 } else if (is_infinite()) { 00067 out << "bplane, infinite"; 00068 } else { 00069 out << "bplane: " << _plane; 00070 } 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: BoundingPlane::as_bounding_plane 00075 // Access: Public, Virtual 00076 // Description: Virtual downcast method. Returns this object as a 00077 // pointer of the indicated type, if it is in fact that 00078 // type. Returns NULL if it is not that type. 00079 //////////////////////////////////////////////////////////////////// 00080 const BoundingPlane *BoundingPlane:: 00081 as_bounding_plane() const { 00082 return this; 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function: BoundingPlane::extend_other 00087 // Access: Public, Virtual 00088 // Description: 00089 //////////////////////////////////////////////////////////////////// 00090 bool BoundingPlane:: 00091 extend_other(BoundingVolume *other) const { 00092 return other->extend_by_plane(this); 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: BoundingPlane::around_other 00097 // Access: Public, Virtual 00098 // Description: 00099 //////////////////////////////////////////////////////////////////// 00100 bool BoundingPlane:: 00101 around_other(BoundingVolume *other, 00102 const BoundingVolume **first, 00103 const BoundingVolume **last) const { 00104 return other->around_planes(first, last); 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: BoundingPlane::contains_other 00109 // Access: Public, Virtual 00110 // Description: 00111 //////////////////////////////////////////////////////////////////// 00112 int BoundingPlane:: 00113 contains_other(const BoundingVolume *other) const { 00114 return other->contains_plane(this); 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: BoundingPlane::extend_by_plane 00119 // Access: Public, Virtual 00120 // Description: 00121 //////////////////////////////////////////////////////////////////// 00122 bool BoundingPlane:: 00123 extend_by_plane(const BoundingPlane *plane) { 00124 nassertr(!plane->is_empty() && !plane->is_infinite(), false); 00125 nassertr(!is_infinite(), false); 00126 00127 if (is_empty()) { 00128 _plane = plane->get_plane(); 00129 _flags = 0; 00130 } else { 00131 _flags = F_infinite; 00132 } 00133 return true; 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: BoundingPlane::contains_sphere 00138 // Access: Public, Virtual 00139 // Description: 00140 //////////////////////////////////////////////////////////////////// 00141 int BoundingPlane:: 00142 contains_sphere(const BoundingSphere *sphere) const { 00143 nassertr(!is_empty() && !is_infinite(), 0); 00144 nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0); 00145 00146 PN_stdfloat r = sphere->get_radius(); 00147 PN_stdfloat d = _plane.dist_to_plane(sphere->get_center()); 00148 00149 if (d <= -r) { 00150 // The sphere is completely behind the plane. 00151 return IF_all | IF_possible | IF_some; 00152 00153 } else if (d <= r) { 00154 // The sphere is intersecting with the plane itself. 00155 return IF_possible | IF_some; 00156 00157 } else { 00158 // The sphere is completely in front of the plane. 00159 return IF_no_intersection; 00160 } 00161 } 00162 00163 //////////////////////////////////////////////////////////////////// 00164 // Function: BoundingPlane::contains_box 00165 // Access: Public, Virtual 00166 // Description: 00167 //////////////////////////////////////////////////////////////////// 00168 int BoundingPlane:: 00169 contains_box(const BoundingBox *box) const { 00170 nassertr(!is_empty() && !is_infinite(), 0); 00171 nassertr(!box->is_empty() && !box->is_infinite(), 0); 00172 00173 // Put the box inside a sphere for the purpose of this test. 00174 const LPoint3 &min = box->get_minq(); 00175 const LPoint3 &max = box->get_maxq(); 00176 LPoint3 center = (min + max) * 0.5f; 00177 PN_stdfloat radius2 = (max - center).length_squared(); 00178 00179 int result = IF_possible | IF_some | IF_all; 00180 00181 PN_stdfloat dist = _plane.dist_to_plane(center); 00182 PN_stdfloat dist2 = dist * dist; 00183 00184 if (dist2 <= radius2) { 00185 // The sphere is not completely behind this plane, but some of 00186 // it is. 00187 00188 // Look a little closer. 00189 bool all_in = true; 00190 bool all_out = true; 00191 for (int i = 0; i < 8 && (all_in || all_out) ; ++i) { 00192 if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) { 00193 // This point is inside the plane. 00194 all_out = false; 00195 } else { 00196 // This point is outside the plane. 00197 all_in = false; 00198 } 00199 } 00200 00201 if (all_out) { 00202 return IF_no_intersection; 00203 } else if (!all_in) { 00204 result &= ~IF_all; 00205 } 00206 00207 } else if (dist >= 0.0f) { 00208 // The sphere is completely in front of this plane. 00209 return IF_no_intersection; 00210 } 00211 00212 return result; 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: BoundingPlane::contains_line 00217 // Access: Public, Virtual 00218 // Description: 00219 //////////////////////////////////////////////////////////////////// 00220 int BoundingPlane:: 00221 contains_line(const BoundingLine *line) const { 00222 return IF_possible; 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: BoundingPlane::contains_plane 00227 // Access: Public, Virtual 00228 // Description: 00229 //////////////////////////////////////////////////////////////////// 00230 int BoundingPlane:: 00231 contains_plane(const BoundingPlane *plane) const { 00232 return IF_possible; 00233 } 00234 00235 //////////////////////////////////////////////////////////////////// 00236 // Function: BoundingPlane::contains_hexahedron 00237 // Access: Protected, Virtual 00238 // Description: Double-dispatch support: called by contains_other() 00239 // when the type we're testing for intersection is known 00240 // to be a hexahedron. 00241 //////////////////////////////////////////////////////////////////// 00242 int BoundingPlane:: 00243 contains_hexahedron(const BoundingHexahedron *hexahedron) const { 00244 nassertr(!is_empty() && !is_infinite(), 0); 00245 nassertr(!hexahedron->is_empty() && !hexahedron->is_infinite(), 0); 00246 00247 int result = IF_possible | IF_some | IF_all; 00248 00249 bool all_in = true; 00250 bool all_out = true; 00251 for (int i = 0; i < 8 && (all_in || all_out) ; ++i) { 00252 if (_plane.dist_to_plane(hexahedron->get_point(i)) < 0.0f) { 00253 // This point is inside the plane. 00254 all_out = false; 00255 } else { 00256 // This point is outside the plane. 00257 all_in = false; 00258 } 00259 } 00260 00261 if (all_out) { 00262 return IF_no_intersection; 00263 } else if (!all_in) { 00264 result &= ~IF_all; 00265 } 00266 00267 return result; 00268 }