00001 // Filename: collisionBox.I 00002 // Created by: amith tudur (31Jul09) 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 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: CollisionBox::Constructor 00018 // Access: Public 00019 // Description: Create the Box by giving a Center and distances of 00020 // of each of the sides of box from the Center. 00021 //////////////////////////////////////////////////////////////////// 00022 INLINE CollisionBox:: 00023 CollisionBox(const LPoint3 ¢er, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) : 00024 _center(center), _x(x), _y(y), _z(z) 00025 { 00026 _min = LPoint3(_center.get_x() - _x, _center.get_y() - _y, _center.get_z() - _z); 00027 _max = LPoint3(_center.get_x() + _x, _center.get_y() + _y, _center.get_z() + _z); 00028 _radius = sqrt(_x*_x + _y*_y + _z*_z); 00029 for(int v = 0; v < 8; v++) 00030 _vertex[v] = get_point_aabb(v); 00031 for(int p = 0; p < 6; p++) 00032 _planes[p] = set_plane(p); 00033 setup_box(); 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: CollisionBox::Constructor 00038 // Access: Public 00039 // Description: Create the Box by Specifying the Diagonal Points 00040 //////////////////////////////////////////////////////////////////// 00041 INLINE CollisionBox:: 00042 CollisionBox(const LPoint3 &min, const LPoint3 &max) : 00043 _min(min), _max(max) 00044 { 00045 _center = (_min + _max) / 2; 00046 _x = _center.get_x() - _min.get_x(); 00047 _y = _center.get_y() - _min.get_y(); 00048 _z = _center.get_z() - _min.get_z(); 00049 _radius = sqrt(_x*_x + _y*_y + _z*_z); 00050 for(int v = 0; v < 8; v++) 00051 _vertex[v] = get_point_aabb(v); 00052 for(int p = 0; p < 6; p++) 00053 _planes[p] = set_plane(p); 00054 setup_box(); 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: CollisionBox::Default constructor 00059 // Access: Protected 00060 // Description: Creates an invalid Box. Only used when reading 00061 // from a bam file. 00062 //////////////////////////////////////////////////////////////////// 00063 INLINE CollisionBox:: 00064 CollisionBox() { 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: CollisionBox::Copy Constructor 00069 // Access: Public 00070 // Description: 00071 //////////////////////////////////////////////////////////////////// 00072 INLINE CollisionBox:: 00073 CollisionBox(const CollisionBox ©) : 00074 CollisionSolid(copy), 00075 _center(copy._center), 00076 _min(copy._min), 00077 _max(copy._max), 00078 _x(copy._x ), 00079 _y(copy._y ), 00080 _z(copy._z ), 00081 _radius(copy._radius ) 00082 { 00083 for(int v = 0; v < 8; v++) 00084 _vertex[v] = copy._vertex[v]; 00085 for(int p = 0; p < 6; p++) 00086 _planes[p] = copy._planes[p]; 00087 setup_box(); 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: CollisionBox::flush_level 00092 // Access: Public, Static 00093 // Description: Flushes the PStatCollectors used during traversal. 00094 //////////////////////////////////////////////////////////////////// 00095 INLINE void CollisionBox:: 00096 flush_level() { 00097 _volume_pcollector.flush_level(); 00098 _test_pcollector.flush_level(); 00099 } 00100 00101 //////////////////////////////////////////////////////////////////// 00102 // Function: CollisionBox::set_center 00103 // Access: Published 00104 // Description: 00105 //////////////////////////////////////////////////////////////////// 00106 INLINE void CollisionBox:: 00107 set_center(const LPoint3 ¢er) { 00108 _center = center; 00109 mark_internal_bounds_stale(); 00110 mark_viz_stale(); 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: CollisionBox::set_center 00115 // Access: Published 00116 // Description: 00117 //////////////////////////////////////////////////////////////////// 00118 INLINE void CollisionBox:: 00119 set_center(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { 00120 set_center(LPoint3(x, y, z)); 00121 } 00122 00123 //////////////////////////////////////////////////////////////////// 00124 // Function: CollisionBox::get_center 00125 // Access: Published 00126 // Description: 00127 //////////////////////////////////////////////////////////////////// 00128 INLINE const LPoint3 &CollisionBox:: 00129 get_center() const { 00130 return _center; 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: CollisionBox::get_radius 00135 // Access: Published 00136 // Description: 00137 //////////////////////////////////////////////////////////////////// 00138 INLINE PN_stdfloat CollisionBox:: 00139 get_radius() const { 00140 return _radius; 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: CollisionBox::get_num_points 00145 // Access: Published 00146 // Description: Returns 8: the number of vertices of a rectangular solid. 00147 //////////////////////////////////////////////////////////////////// 00148 INLINE_MATHUTIL int CollisionBox:: 00149 get_num_points() const { 00150 return 8; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: CollisionBox::get_point 00155 // Access: Published 00156 // Description: Returns the nth vertex of the OBB. 00157 //////////////////////////////////////////////////////////////////// 00158 INLINE_MATHUTIL LPoint3 CollisionBox:: 00159 get_point(int n) const { 00160 nassertr(n >= 0 && n < 8, LPoint3::zero()); 00161 return _vertex[n]; 00162 } 00163 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: CollisionBox::get_point_aabb 00167 // Access: Published 00168 // Description: Returns the nth vertex of the Axis Aligned Bounding Box. 00169 //////////////////////////////////////////////////////////////////// 00170 INLINE_MATHUTIL LPoint3 CollisionBox:: 00171 get_point_aabb(int n) const { 00172 nassertr(n >= 0 && n < 8, LPoint3::zero()); 00173 00174 // We do some trickery assuming that _min and _max are consecutive 00175 // in memory. 00176 const LPoint3 *a = &_min; 00177 return LPoint3(a[(n>>2)&1][0], a[(n>>1)&1][1], a[(n)&1][2]); 00178 } 00179 00180 //////////////////////////////////////////////////////////////////// 00181 // Function: CollisionBox::get_num_planes 00182 // Access: Published 00183 // Description: Returns 6: the number of faces of a rectangular solid. 00184 //////////////////////////////////////////////////////////////////// 00185 INLINE_MATHUTIL int CollisionBox:: 00186 get_num_planes() const { 00187 return 6; 00188 } 00189 00190 //////////////////////////////////////////////////////////////////// 00191 // Function: CollisionBox::get_plane 00192 // Access: Published 00193 // Description: Returns the nth face of the rectangular solid. 00194 //////////////////////////////////////////////////////////////////// 00195 INLINE_MATHUTIL LPlane CollisionBox:: 00196 get_plane(int n) const { 00197 nassertr(n >= 0 && n < 6, LPlane()); 00198 return _planes[n]; 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: CollisionBox::set_plane 00203 // Access: Published 00204 // Description: Creates the nth face of the rectangular solid. 00205 //////////////////////////////////////////////////////////////////// 00206 INLINE_MATHUTIL LPlane CollisionBox:: 00207 set_plane(int n) const { 00208 nassertr(n >= 0 && n < 6, LPlane()); 00209 return LPlane(get_point(plane_def[n][0]), 00210 get_point(plane_def[n][1]), 00211 get_point(plane_def[n][2])); 00212 } 00213 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: CollisionBox::is_right 00217 // Access: Private, Static 00218 // Description: Returns true if the 2-d v1 is to the right of v2. 00219 //////////////////////////////////////////////////////////////////// 00220 INLINE bool CollisionBox:: 00221 is_right(const LVector2 &v1, const LVector2 &v2) { 00222 return (v1[0] * v2[1] - v1[1] * v2[0]) > 1.0e-6f; 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: CollisionBox::dist_to_line 00227 // Access: Private, Static 00228 // Description: Returns the linear distance of p to the line defined 00229 // by f and f+v, where v is a normalized vector. The 00230 // result is negative if p is left of the line, positive 00231 // if it is right of the line. 00232 //////////////////////////////////////////////////////////////////// 00233 INLINE PN_stdfloat CollisionBox:: 00234 dist_to_line(const LPoint2 &p, 00235 const LPoint2 &f, const LVector2 &v) { 00236 LVector2 v1 = (p - f); 00237 return (v1[0] * v[1] - v1[1] * v[0]); 00238 } 00239 00240 //////////////////////////////////////////////////////////////////// 00241 // Function: CollisionBox::to_2d 00242 // Access: Private 00243 // Description: Assuming the indicated point in 3-d space lies within 00244 // the polygon's plane, returns the corresponding point 00245 // in the polygon's 2-d definition space. 00246 //////////////////////////////////////////////////////////////////// 00247 INLINE LPoint2 CollisionBox:: 00248 to_2d(const LVecBase3 &point3d, int plane) const { 00249 LPoint3 point = LPoint3(point3d) * _to_2d_mat[plane]; 00250 return LPoint2(point[0], point[2]); 00251 } 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: CollisionBox::calc_to_3d_mat 00255 // Access: Private 00256 // Description: Fills the indicated matrix with the appropriate 00257 // rotation transform to move points from the 2-d plane 00258 // into the 3-d (X, 0, Z) plane. 00259 //////////////////////////////////////////////////////////////////// 00260 INLINE void CollisionBox:: 00261 calc_to_3d_mat(LMatrix4 &to_3d_mat,int plane) const { 00262 // We have to be explicit about the coordinate system--we 00263 // specifically mean CS_zup_right, because that points the forward 00264 // vector down the Y axis and moves the coords in (X, 0, Z). We 00265 // want this effect regardless of the user's coordinate system of 00266 // choice. 00267 00268 // The up vector, on the other hand, is completely arbitrary. 00269 00270 look_at(to_3d_mat, -get_plane(plane).get_normal(), 00271 LVector3(0.0f, 0.0f, 1.0f), CS_zup_right); 00272 to_3d_mat.set_row(3, get_plane(plane).get_point()); 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: CollisionBox::rederive_to_3d_mat 00277 // Access: Private 00278 // Description: Fills the indicated matrix with the appropriate 00279 // rotation transform to move points from the 2-d plane 00280 // into the 3-d (X, 0, Z) plane. 00281 // 00282 // This is essentially similar to calc_to_3d_mat, except 00283 // that the matrix is rederived from whatever is stored 00284 // in _to_2d_mat, guaranteeing that it will match 00285 // whatever algorithm produced that one, even if it was 00286 // produced on a different machine with different 00287 // numerical precision. 00288 //////////////////////////////////////////////////////////////////// 00289 INLINE void CollisionBox:: 00290 rederive_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const { 00291 to_3d_mat.invert_from(_to_2d_mat[plane]); 00292 } 00293 00294 //////////////////////////////////////////////////////////////////// 00295 // Function: CollisionBox::to_3d 00296 // Access: Private, Static 00297 // Description: Extrude the indicated point in the polygon's 2-d 00298 // definition space back into 3-d coordinates. 00299 //////////////////////////////////////////////////////////////////// 00300 INLINE LPoint3 CollisionBox:: 00301 to_3d(const LVecBase2 &point2d, const LMatrix4 &to_3d_mat) { 00302 return LPoint3(point2d[0], 0.0f, point2d[1]) * to_3d_mat; 00303 } 00304 00305 //////////////////////////////////////////////////////////////////// 00306 // Function: CollisionBox::PointDef::Constructor 00307 // Access: Public 00308 // Description: 00309 //////////////////////////////////////////////////////////////////// 00310 INLINE CollisionBox::PointDef:: 00311 PointDef(const LPoint2 &p, const LVector2 &v) : _p(p), _v(v) { 00312 } 00313 00314 //////////////////////////////////////////////////////////////////// 00315 // Function: CollisionBox::PointDef::Constructor 00316 // Access: Public 00317 // Description: 00318 //////////////////////////////////////////////////////////////////// 00319 INLINE CollisionBox::PointDef:: 00320 PointDef(PN_stdfloat x, PN_stdfloat y) : _p(x, y), _v(0.0f, 0.0f) { 00321 } 00322 00323 //////////////////////////////////////////////////////////////////// 00324 // Function: CollisionBox::PointDef::Copy Constructor 00325 // Access: Public 00326 // Description: 00327 //////////////////////////////////////////////////////////////////// 00328 INLINE CollisionBox::PointDef:: 00329 PointDef(const CollisionBox::PointDef ©) : _p(copy._p), _v(copy._v) { 00330 } 00331 00332 //////////////////////////////////////////////////////////////////// 00333 // Function: CollisionBox::PointDef::Copy Assignment Operator 00334 // Access: Public 00335 // Description: 00336 //////////////////////////////////////////////////////////////////// 00337 INLINE void CollisionBox::PointDef:: 00338 operator = (const CollisionBox::PointDef ©) { 00339 _p = copy._p; 00340 _v = copy._v; 00341 } 00342 00343 //////////////////////////////////////////////////////////////////// 00344 // Function: CollisionBox::get_plane_points 00345 // Access: Public 00346 // Description: returns the points that form the nth plane 00347 //////////////////////////////////////////////////////////////////// 00348 INLINE CollisionBox::Points CollisionBox:: 00349 get_plane_points(int n) { 00350 return _points[n]; 00351 }