Panda3D
|
00001 // Filename: collisionEntry.cxx 00002 // Created by: drose (16Mar02) 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 "collisionEntry.h" 00016 #include "dcast.h" 00017 #include "indent.h" 00018 00019 TypeHandle CollisionEntry::_type_handle; 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: CollisionEntry::Copy Constructor 00023 // Access: Public 00024 // Description: 00025 //////////////////////////////////////////////////////////////////// 00026 CollisionEntry:: 00027 CollisionEntry(const CollisionEntry ©) : 00028 _from(copy._from), 00029 _into(copy._into), 00030 _from_node(copy._from_node), 00031 _into_node(copy._into_node), 00032 _from_node_path(copy._from_node_path), 00033 _into_node_path(copy._into_node_path), 00034 _into_clip_planes(copy._into_clip_planes), 00035 _t(copy._t), 00036 _flags(copy._flags), 00037 _surface_point(copy._surface_point), 00038 _surface_normal(copy._surface_normal), 00039 _interior_point(copy._interior_point), 00040 _contact_pos(copy._contact_pos), 00041 _contact_normal(copy._contact_normal) 00042 { 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: CollisionEntry::Copy Assignment Operator 00047 // Access: Public 00048 // Description: 00049 //////////////////////////////////////////////////////////////////// 00050 void CollisionEntry:: 00051 operator = (const CollisionEntry ©) { 00052 _from = copy._from; 00053 _into = copy._into; 00054 _from_node = copy._from_node; 00055 _into_node = copy._into_node; 00056 _from_node_path = copy._from_node_path; 00057 _into_node_path = copy._into_node_path; 00058 _into_clip_planes = copy._into_clip_planes; 00059 _t = copy._t; 00060 _flags = copy._flags; 00061 _surface_point = copy._surface_point; 00062 _surface_normal = copy._surface_normal; 00063 _interior_point = copy._interior_point; 00064 _contact_pos = copy._contact_pos; 00065 _contact_normal = copy._contact_normal; 00066 } 00067 00068 //////////////////////////////////////////////////////////////////// 00069 // Function: CollisionEntry::get_surface_point 00070 // Access: Published 00071 // Description: Returns the point, on the surface of the "into" 00072 // object, at which a collision is detected. This can 00073 // be thought of as the first point of intersection. 00074 // However the contact point is the actual first point of 00075 // intersection. 00076 // 00077 // The point will be converted into whichever coordinate 00078 // space the caller specifies. 00079 //////////////////////////////////////////////////////////////////// 00080 LPoint3 CollisionEntry:: 00081 get_surface_point(const NodePath &space) const { 00082 nassertr(has_surface_point(), LPoint3::zero()); 00083 CPT(TransformState) transform = _into_node_path.get_transform(space); 00084 return _surface_point * transform->get_mat(); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: CollisionEntry::get_surface_normal 00089 // Access: Published 00090 // Description: Returns the surface normal of the "into" object at 00091 // the point at which a collision is detected. 00092 // 00093 // The normal will be converted into whichever coordinate 00094 // space the caller specifies. 00095 //////////////////////////////////////////////////////////////////// 00096 LVector3 CollisionEntry:: 00097 get_surface_normal(const NodePath &space) const { 00098 nassertr(has_surface_normal(), LVector3::zero()); 00099 CPT(TransformState) transform = _into_node_path.get_transform(space); 00100 return _surface_normal * transform->get_mat(); 00101 } 00102 00103 //////////////////////////////////////////////////////////////////// 00104 // Function: CollisionEntry::get_interior_point 00105 // Access: Published 00106 // Description: Returns the point, within the interior of the "into" 00107 // object, which represents the depth to which the 00108 // "from" object has penetrated. This can also be 00109 // described as the intersection point on the surface of 00110 // the "from" object (which is inside the "into" 00111 // object). It can be thought of as the deepest point 00112 // of intersection. 00113 // 00114 // The point will be converted into whichever coordinate 00115 // space the caller specifies. 00116 //////////////////////////////////////////////////////////////////// 00117 LPoint3 CollisionEntry:: 00118 get_interior_point(const NodePath &space) const { 00119 if (!has_interior_point()) { 00120 return get_surface_point(space); 00121 } 00122 CPT(TransformState) transform = _into_node_path.get_transform(space); 00123 return _interior_point * transform->get_mat(); 00124 } 00125 00126 //////////////////////////////////////////////////////////////////// 00127 // Function: CollisionEntry::get_all 00128 // Access: Published 00129 // Description: Simultaneously transforms the surface point, surface 00130 // normal, and interior point of the collision into the 00131 // indicated coordinate space. 00132 // 00133 // Returns true if all three properties are available, 00134 // or false if any one of them is not. 00135 //////////////////////////////////////////////////////////////////// 00136 bool CollisionEntry:: 00137 get_all(const NodePath &space, LPoint3 &surface_point, 00138 LVector3 &surface_normal, LPoint3 &interior_point) const { 00139 CPT(TransformState) transform = _into_node_path.get_transform(space); 00140 const LMatrix4 &mat = transform->get_mat(); 00141 bool all_ok = true; 00142 00143 if (!has_surface_point()) { 00144 surface_point = LPoint3::zero(); 00145 all_ok = false; 00146 } else { 00147 surface_point = _surface_point * mat; 00148 } 00149 00150 if (!has_surface_normal()) { 00151 surface_normal = LVector3::zero(); 00152 all_ok = false; 00153 } else { 00154 surface_normal = _surface_normal * mat; 00155 } 00156 00157 if (!has_interior_point()) { 00158 interior_point = surface_point; 00159 all_ok = false; 00160 } else { 00161 interior_point = _interior_point * mat; 00162 } 00163 00164 return all_ok; 00165 } 00166 00167 //////////////////////////////////////////////////////////////////// 00168 // Function: CollisionEntry::get_contact_pos 00169 // Access: Published 00170 // Description: Returns the position of the "from" object at the instant 00171 // that a collision is first detected. 00172 // 00173 // The position will be converted into whichever coordinate 00174 // space the caller specifies. 00175 //////////////////////////////////////////////////////////////////// 00176 LPoint3 CollisionEntry:: 00177 get_contact_pos(const NodePath &space) const { 00178 nassertr(has_contact_pos(), LPoint3::zero()); 00179 CPT(TransformState) transform = _into_node_path.get_transform(space); 00180 return _contact_pos * transform->get_mat(); 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: CollisionEntry::get_contact_normal 00185 // Access: Published 00186 // Description: Returns the surface normal of the "into" object at 00187 // the contact position. 00188 // 00189 // The normal will be converted into whichever coordinate 00190 // space the caller specifies. 00191 //////////////////////////////////////////////////////////////////// 00192 LVector3 CollisionEntry:: 00193 get_contact_normal(const NodePath &space) const { 00194 nassertr(has_contact_normal(), LVector3::zero()); 00195 CPT(TransformState) transform = _into_node_path.get_transform(space); 00196 return _contact_normal * transform->get_mat(); 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function: CollisionEntry::get_all_contact_info 00201 // Access: Published 00202 // Description: Simultaneously transforms the contact position and 00203 // contact normal of the collision into the 00204 // indicated coordinate space. 00205 // 00206 // Returns true if all three properties are available, 00207 // or false if any one of them is not. 00208 //////////////////////////////////////////////////////////////////// 00209 bool CollisionEntry:: 00210 get_all_contact_info(const NodePath &space, LPoint3 &contact_pos, 00211 LVector3 &contact_normal) const { 00212 CPT(TransformState) transform = _into_node_path.get_transform(space); 00213 const LMatrix4 &mat = transform->get_mat(); 00214 bool all_ok = true; 00215 00216 if (!has_contact_pos()) { 00217 contact_pos = LPoint3::zero(); 00218 all_ok = false; 00219 } else { 00220 contact_pos = _contact_pos * mat; 00221 } 00222 00223 if (!has_contact_normal()) { 00224 contact_normal = LVector3::zero(); 00225 all_ok = false; 00226 } else { 00227 contact_normal = _contact_normal * mat; 00228 } 00229 00230 return all_ok; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: CollisionEntry::output 00235 // Access: Published 00236 // Description: 00237 //////////////////////////////////////////////////////////////////// 00238 void CollisionEntry:: 00239 output(ostream &out) const { 00240 out << _from_node_path; 00241 if (!_into_node_path.is_empty()) { 00242 out << " into " << _into_node_path; 00243 } 00244 if (has_surface_point()) { 00245 out << " at " << get_surface_point(NodePath()); 00246 } 00247 } 00248 00249 //////////////////////////////////////////////////////////////////// 00250 // Function: CollisionEntry::write 00251 // Access: Published 00252 // Description: 00253 //////////////////////////////////////////////////////////////////// 00254 void CollisionEntry:: 00255 write(ostream &out, int indent_level) const { 00256 indent(out, indent_level) 00257 << "CollisionEntry:\n"; 00258 if (!_from_node_path.is_empty()) { 00259 indent(out, indent_level + 2) 00260 << "from " << _from_node_path << "\n"; 00261 } 00262 if (!_into_node_path.is_empty()) { 00263 indent(out, indent_level + 2) 00264 << "into " << _into_node_path; 00265 00266 out << " ["; 00267 _into_node_path.node()->list_tags(out, ", "); 00268 out << "]"; 00269 00270 const ClipPlaneAttrib *cpa = get_into_clip_planes(); 00271 if (cpa != (ClipPlaneAttrib *)NULL) { 00272 out << " (clipped)"; 00273 } 00274 out << "\n"; 00275 } 00276 if (has_surface_point()) { 00277 indent(out, indent_level + 2) 00278 << "at " << get_surface_point(NodePath()) << "\n"; 00279 } 00280 if (has_surface_normal()) { 00281 indent(out, indent_level + 2) 00282 << "normal " << get_surface_normal(NodePath()) << "\n"; 00283 } 00284 if (has_interior_point()) { 00285 indent(out, indent_level + 2) 00286 << "interior " << get_interior_point(NodePath()) 00287 << " (depth " 00288 << (get_interior_point(NodePath()) - get_surface_point(NodePath())).length() 00289 << ")\n"; 00290 } 00291 indent(out, indent_level + 2) 00292 << "respect_prev_transform = " << get_respect_prev_transform() << "\n"; 00293 } 00294 00295 //////////////////////////////////////////////////////////////////// 00296 // Function: CollisionEntry::check_clip_planes 00297 // Access: Private 00298 // Description: Checks whether the into_node_path has a 00299 // ClipPlaneAttrib defined. 00300 //////////////////////////////////////////////////////////////////// 00301 void CollisionEntry:: 00302 check_clip_planes() { 00303 _into_clip_planes = DCAST(ClipPlaneAttrib, _into_node_path.get_net_state()->get_attrib(ClipPlaneAttrib::get_class_slot())); 00304 _flags |= F_checked_clip_planes; 00305 }