// Filename: collisionEntry.I // Created by: drose (16Mar02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE CollisionEntry:: CollisionEntry() { _flags = 0; // > 1. means collision didn't happen _t = 2.f; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_from // Access: Published // Description: Returns the CollisionSolid pointer for the particular // solid that triggered this collision. //////////////////////////////////////////////////////////////////// INLINE const CollisionSolid *CollisionEntry:: get_from() const { return _from; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_into // Access: Published // Description: Returns true if the "into" solid is, in fact, a // CollisionSolid, and its pointer is known (in which // case get_into() may be called to retrieve it). If // this returns false, the collision was detected into a // GeomNode, and there is no CollisionSolid pointer to // be retrieved. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_into() const { return (_into != (CollisionSolid *)NULL); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_into // Access: Published // Description: Returns the CollisionSolid pointer for the particular // solid was collided into. This pointer might be NULL // if the collision was into a piece of visible // geometry, instead of a normal CollisionSolid // collision; see has_into(). //////////////////////////////////////////////////////////////////// INLINE const CollisionSolid *CollisionEntry:: get_into() const { return _into; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_from_node // Access: Published // Description: Returns the node that contains the CollisionSolid // that triggered this collision. This will be a node // that has been added to a CollisionTraverser via // add_collider(). //////////////////////////////////////////////////////////////////// INLINE CollisionNode *CollisionEntry:: get_from_node() const { return _from_node; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_into_node // Access: Published // Description: Returns the node that contains the CollisionSolid // that was collided into. This returns a PandaNode // pointer instead of something more specific, because // it might be either a CollisionNode or a GeomNode. // // Also see get_into_node_path(). //////////////////////////////////////////////////////////////////// INLINE PandaNode *CollisionEntry:: get_into_node() const { return _into_node; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_from_node_path // Access: Published // Description: Returns the NodePath that represents the // CollisionNode that contains the CollisionSolid that // triggered this collision. This will be a NodePath // that has been added to a CollisionTraverser via // add_collider(). //////////////////////////////////////////////////////////////////// INLINE NodePath CollisionEntry:: get_from_node_path() const { return _from_node_path; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_into_node_path // Access: Published // Description: Returns the NodePath that represents the specific // CollisionNode or GeomNode instance that was collided // into. This is the same node returned by // get_into_node(), represented as a NodePath; however, // it may be more useful because the NodePath can // resolve the particular instance of the node, if there // is more than one. //////////////////////////////////////////////////////////////////// INLINE NodePath CollisionEntry:: get_into_node_path() const { return _into_node_path; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_t // Access: Published // Description: Sets a time value for this collision relative to // other CollisionEntries //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_t(float t) { _t = t; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_t // Access: Published // Description: returns time value for this collision relative to // other CollisionEntries //////////////////////////////////////////////////////////////////// INLINE float CollisionEntry:: get_t() const { return _t; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::collided // Access: Published // Description: returns true if this represents an actual collision // as opposed to a potential collision, needed for // iterative collision resolution where path of // collider changes mid-frame //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: collided() const { return ((0.f <= _t) && (_t <= 1.f)); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::reset_collided // Access: Published // Description: prepare for another collision test //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: reset_collided() { _t = 2.f; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_respect_prev_transform // Access: Published // Description: Returns true if the collision was detected by a // CollisionTraverser whose respect_prev_transform // flag was set true, meaning we should consider motion // significant in evaluating collisions. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: get_respect_prev_transform() const { return (_flags & F_respect_prev_transform) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_surface_point // Access: Published // Description: Stores the point, on the surface of the "into" // object, at which a collision is detected. // // This point is specified in the coordinate space of // the "into" object. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_surface_point(const LPoint3f &point) { _surface_point = point; _flags |= F_has_surface_point; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_surface_normal // Access: Published // Description: Stores the surface normal of the "into" object at the // point of the intersection. // // This normal is specified in the coordinate space of // the "into" object. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_surface_normal(const LVector3f &normal) { _surface_normal = normal; _flags |= F_has_surface_normal; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_interior_point // Access: Published // Description: Stores the point, within the interior of the "into" // object, which represents the depth to which the // "from" object has penetrated. This can also be // described as the intersection point on the surface of // the "from" object (which is inside the "into" // object). // // This point is specified in the coordinate space of // the "into" object. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_interior_point(const LPoint3f &point) { _interior_point = point; _flags |= F_has_interior_point; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_surface_point // Access: Published // Description: Returns true if the surface point has been specified, // false otherwise. See get_surface_point(). Some // types of collisions may not compute the surface // point. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_surface_point() const { return (_flags & F_has_surface_point) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_surface_normal // Access: Published // Description: Returns true if the surface normal has been specified, // false otherwise. See get_surface_normal(). Some // types of collisions may not compute the surface // normal. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_surface_normal() const { return (_flags & F_has_surface_normal) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_interior_point // Access: Published // Description: Returns true if the interior point has been specified, // false otherwise. See get_interior_point(). Some // types of collisions may not compute the interior // point. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_interior_point() const { return (_flags & F_has_interior_point) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_contact_pos // Access: Published // Description: Stores the position of the "from" object at the // instant at which the collision is first detected. // // This position is specified in the coordinate space of // the "into" object. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_contact_pos(const LPoint3f &pos) { _contact_pos = pos; _flags |= F_has_contact_pos; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_contact_normal // Access: Published // Description: Stores the surface normal of the "into" object at the // contact pos. // // This normal is specified in the coordinate space of // the "into" object. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: set_contact_normal(const LVector3f &normal) { _contact_normal = normal; _flags |= F_has_contact_normal; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_contact_pos // Access: Published // Description: Returns true if the contact position has been specified, // false otherwise. See get_contact_pos(). Some // types of collisions may not compute the contact // pos. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_contact_pos() const { return (_flags & F_has_contact_pos) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::has_contact_normal // Access: Published // Description: Returns true if the contact normal has been specified, // false otherwise. See get_contact_normal(). Some // types of collisions may not compute the contact // normal. //////////////////////////////////////////////////////////////////// INLINE bool CollisionEntry:: has_contact_normal() const { return (_flags & F_has_contact_normal) != 0; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_wrt_space // Access: Public // Description: Returns the relative transform of the from node as // seen from the into node. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) CollisionEntry:: get_wrt_space() const { return _from_node_path.get_transform(_into_node_path); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_inv_wrt_space // Access: Public // Description: Returns the relative transform of the into node as // seen from the from node. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) CollisionEntry:: get_inv_wrt_space() const { return _into_node_path.get_transform(_from_node_path); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_wrt_prev_space // Access: Public // Description: Returns the relative transform of the from node as // seen from the into node, as of the previous frame // (according to set_prev_transform(), set_fluid_pos(), // etc.) //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) CollisionEntry:: get_wrt_prev_space() const { if (get_respect_prev_transform()) { return _from_node_path.get_prev_transform(_into_node_path); } else { return get_wrt_space(); } } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_wrt_mat // Access: Public // Description: Returns the relative transform of the from node as // seen from the into node. //////////////////////////////////////////////////////////////////// INLINE const LMatrix4f &CollisionEntry:: get_wrt_mat() const { return get_wrt_space()->get_mat(); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_inv_wrt_mat // Access: Public // Description: Returns the relative transform of the into node as // seen from the from node. //////////////////////////////////////////////////////////////////// INLINE const LMatrix4f &CollisionEntry:: get_inv_wrt_mat() const { return get_inv_wrt_space()->get_mat(); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_wrt_prev_mat // Access: Public // Description: Returns the relative transform of the from node as // seen from the into node, as of the previous frame // (according to set_prev_transform(), set_fluid_pos(), // etc.) //////////////////////////////////////////////////////////////////// INLINE const LMatrix4f &CollisionEntry:: get_wrt_prev_mat() const { return get_wrt_prev_space()->get_mat(); } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::get_into_clip_planes // Access: Public // Description: Returns the ClipPlaneAttrib, if any, that is applied // to the into_node_path, or NULL if there is no clip // plane in effect. //////////////////////////////////////////////////////////////////// INLINE const ClipPlaneAttrib *CollisionEntry:: get_into_clip_planes() const { if ((_flags & F_checked_clip_planes) == 0) { ((CollisionEntry *)this)->check_clip_planes(); } return _into_clip_planes; } //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::test_intersection // Access: Private // Description: This is intended to be called only by the // CollisionTraverser. It requests the CollisionEntry // to start the intersection test between the from and // into solids stored within it, passing the result (if // positive) to the indicated CollisionHandler. //////////////////////////////////////////////////////////////////// INLINE void CollisionEntry:: test_intersection(CollisionHandler *record, const CollisionTraverser *trav) const { PT(CollisionEntry) result = get_from()->test_intersection(*this); #ifdef DO_COLLISION_RECORDING if (trav->has_recorder()) { if (result != (CollisionEntry *)NULL) { trav->get_recorder()->collision_tested(*result, true); } else { trav->get_recorder()->collision_tested(*this, false); } } #endif // DO_COLLISION_RECORDING #ifdef DO_PSTATS ((CollisionSolid *)get_into())->get_test_pcollector().add_level(1); #endif // DO_PSTATS // if there was no collision detected but the handler wants to know about all // potential collisions, create a "didn't collide" collision entry for it if (record->wants_all_potential_collidees() && result == (CollisionEntry *)NULL) { result = new CollisionEntry(*this); result->reset_collided(); } if (result != (CollisionEntry *)NULL) { record->add_entry(result); } } INLINE ostream & operator << (ostream &out, const CollisionEntry &entry) { entry.output(out); return out; }