new NodePath-based interface

This commit is contained in:
David Rose 2003-10-23 23:59:09 +00:00
parent 5749e6dfef
commit 0e369940cf
17 changed files with 538 additions and 532 deletions

View File

@ -25,11 +25,6 @@
INLINE CollisionEntry:: INLINE CollisionEntry::
CollisionEntry() { CollisionEntry() {
_flags = 0; _flags = 0;
_from_space = TransformState::make_identity();
_into_space = TransformState::make_identity();
_wrt_space = TransformState::make_identity();
_inv_wrt_space = TransformState::make_identity();
_wrt_prev_space = TransformState::make_identity();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -131,134 +126,105 @@ get_into_node_path() const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_from_space // Function: CollisionEntry::get_respect_prev_transform
// Access: Published // Access: Published
// Description: Returns the global coordinate space of the // Description: Returns true if the collision was detected by a
// CollisionNode returned by get_from_node(), as of the // CollisionTraverser whose respect_prev_transform
// time of the collision. This will be equivalent to a // flag was set true, meaning we should consider motion
// wrt() from the node to render. // significant in evaluating collisions.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const TransformState *CollisionEntry:: INLINE bool CollisionEntry::
get_from_space() const { get_respect_prev_transform() const {
return _from_space; return (_flags & F_respect_prev_transform) != 0;
} }
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_into_space
// Access: Published
// Description: Returns the global coordinate space of the
// CollisionNode or GeomNode returned by
// get_into_node(), as of the time of the collision.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *CollisionEntry::
get_into_space() const {
return _into_space;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_wrt_space // Function: CollisionEntry::set_surface_point
// Access: Published // Access: Published
// Description: Returns the relative transform of the from node as // Description: Stores the point, on the surface of the "into"
// seen from the into node. // object, at which a collision is detected.
//////////////////////////////////////////////////////////////////// //
INLINE const TransformState *CollisionEntry:: // This point is specified in the coordinate space of
get_wrt_space() const { // the "into" object.
return _wrt_space;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_inv_wrt_space
// Access: Published
// Description: Returns the relative transform of the into node as
// seen from the from node.
////////////////////////////////////////////////////////////////////
INLINE const TransformState *CollisionEntry::
get_inv_wrt_space() const {
return _inv_wrt_space;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_wrt_prev_space
// Access: Published
// 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 TransformState *CollisionEntry::
get_wrt_prev_space() const {
return _wrt_prev_space;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_from_mat
// Access: Published
// Description: Returns the global coordinate space of the
// CollisionNode returned by get_from_node(), as of the
// time of the collision. This will be equivalent to a
// wrt() from the node to render.
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4f &CollisionEntry::
get_from_mat() const {
return _from_space->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_into_mat
// Access: Published
// Description: Returns the global coordinate space of the
// CollisionNode or GeomNode returned by
// get_into_node(), as of the time of the collision.
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4f &CollisionEntry::
get_into_mat() const {
return _into_space->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_wrt_mat
// Access: Published
// Description: Returns the relative transform of the from node as
// seen from the into node.
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4f &CollisionEntry::
get_wrt_mat() const {
return _wrt_space->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_inv_wrt_mat
// Access: Published
// 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 _inv_wrt_space->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_wrt_prev_mat
// Access: Published
// 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 _wrt_prev_space->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_into_intersection_point
// Access: Published
// Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry:: INLINE void CollisionEntry::
set_into_intersection_point(const LPoint3f &point) { set_surface_point(const LPoint3f &point) {
_into_intersection_point = point; _surface_point = point;
_flags |= F_has_into_intersection_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;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -270,7 +236,7 @@ set_into_intersection_point(const LPoint3f &point) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_into_intersection_point() const { has_into_intersection_point() const {
return (_flags & F_has_into_intersection_point) != 0; return has_surface_point();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -281,10 +247,9 @@ has_into_intersection_point() const {
// call this if has_into_intersection_point() returns // call this if has_into_intersection_point() returns
// false. // false.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const LPoint3f &CollisionEntry:: INLINE LPoint3f CollisionEntry::
get_into_intersection_point() const { get_into_intersection_point() const {
nassertr(has_into_intersection_point(), _into_intersection_point); return get_surface_point(get_into_node_path());
return _into_intersection_point;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -296,9 +261,7 @@ get_into_intersection_point() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_from_intersection_point() const { has_from_intersection_point() const {
// Since we derive the from_intersection_point from the return has_surface_point();
// into_intersection_point, this is really the same question.
return has_into_intersection_point();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -311,18 +274,7 @@ has_from_intersection_point() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE LPoint3f CollisionEntry:: INLINE LPoint3f CollisionEntry::
get_from_intersection_point() const { get_from_intersection_point() const {
return get_into_intersection_point() * get_inv_wrt_mat(); return get_surface_point(get_from_node_path());
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_into_surface_normal
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry::
set_into_surface_normal(const LVector3f &normal) {
_into_surface_normal = normal;
_flags |= F_has_into_surface_normal;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -334,7 +286,7 @@ set_into_surface_normal(const LVector3f &normal) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_into_surface_normal() const { has_into_surface_normal() const {
return (_flags & F_has_into_surface_normal) != 0; return has_surface_normal();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -345,21 +297,9 @@ has_into_surface_normal() const {
// to call this if has_into_surface_normal() returns // to call this if has_into_surface_normal() returns
// false. // false.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const LVector3f &CollisionEntry:: INLINE LVector3f CollisionEntry::
get_into_surface_normal() const { get_into_surface_normal() const {
nassertr(has_into_surface_normal(), _into_surface_normal); return get_surface_normal(get_into_node_path());
return _into_surface_normal;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_from_surface_normal
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry::
set_from_surface_normal(const LVector3f &normal) {
_from_surface_normal = normal;
_flags |= F_has_from_surface_normal;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -371,7 +311,7 @@ set_from_surface_normal(const LVector3f &normal) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_from_surface_normal() const { has_from_surface_normal() const {
return (_flags & (F_has_into_surface_normal | F_has_from_surface_normal)) != 0; return has_surface_normal();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -382,25 +322,9 @@ has_from_surface_normal() const {
// the collided-from object. It is an error to call // the collided-from object. It is an error to call
// this if has_from_surface_normal() returns false. // this if has_from_surface_normal() returns false.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const LVector3f &CollisionEntry:: INLINE LVector3f CollisionEntry::
get_from_surface_normal() const { get_from_surface_normal() const {
nassertr(has_from_surface_normal(), _from_surface_normal); return get_surface_normal(get_from_node_path());
if ((_flags & F_has_from_surface_normal) == 0) {
((CollisionEntry *)this)->compute_from_surface_normal();
}
return _from_surface_normal;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_into_depth
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry::
set_into_depth(float depth) {
_into_depth = depth;
_flags |= F_has_into_depth;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -413,7 +337,7 @@ set_into_depth(float depth) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_into_depth() const { has_into_depth() const {
return (_flags & F_has_into_depth) != 0; return has_surface_point() && has_interior_point();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -428,18 +352,7 @@ has_into_depth() const {
INLINE float CollisionEntry:: INLINE float CollisionEntry::
get_into_depth() const { get_into_depth() const {
nassertr(has_into_depth(), 0.0); nassertr(has_into_depth(), 0.0);
return _into_depth; return (get_surface_point(get_into_node_path()) - get_interior_point(get_into_node_path())).length();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_from_depth
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry::
set_from_depth(float depth) {
_from_depth = depth;
_flags |= F_has_from_depth;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -452,7 +365,7 @@ set_from_depth(float depth) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionEntry:: INLINE bool CollisionEntry::
has_from_depth() const { has_from_depth() const {
return (_flags & F_has_from_depth) != 0; return has_surface_point() && has_interior_point();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -466,8 +379,82 @@ has_from_depth() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE float CollisionEntry:: INLINE float CollisionEntry::
get_from_depth() const { get_from_depth() const {
nassertr(has_from_depth(), 0.0); return (get_surface_point(get_from_node_path()) - get_interior_point(get_from_node_path())).length();
return _from_depth; }
////////////////////////////////////////////////////////////////////
// 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();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -33,15 +33,10 @@ CollisionEntry(const CollisionEntry &copy) :
_into_node(copy._into_node), _into_node(copy._into_node),
_from_node_path(copy._from_node_path), _from_node_path(copy._from_node_path),
_into_node_path(copy._into_node_path), _into_node_path(copy._into_node_path),
_from_space(copy._from_space),
_into_space(copy._into_space),
_wrt_space(copy._wrt_space),
_inv_wrt_space(copy._inv_wrt_space),
_wrt_prev_space(copy._wrt_prev_space),
_flags(copy._flags), _flags(copy._flags),
_into_intersection_point(copy._into_intersection_point), _surface_point(copy._surface_point),
_into_surface_normal(copy._into_surface_normal), _surface_normal(copy._surface_normal),
_into_depth(copy._into_depth) _interior_point(copy._interior_point)
{ {
} }
@ -58,26 +53,101 @@ operator = (const CollisionEntry &copy) {
_into_node = copy._into_node; _into_node = copy._into_node;
_from_node_path = copy._from_node_path; _from_node_path = copy._from_node_path;
_into_node_path = copy._into_node_path; _into_node_path = copy._into_node_path;
_from_space = copy._from_space;
_into_space = copy._into_space;
_wrt_space = copy._wrt_space;
_inv_wrt_space = copy._inv_wrt_space;
_wrt_prev_space = copy._wrt_prev_space;
_flags = copy._flags; _flags = copy._flags;
_into_intersection_point = copy._into_intersection_point; _surface_point = copy._surface_point;
_into_surface_normal = copy._into_surface_normal; _surface_normal = copy._surface_normal;
_into_depth = copy._into_depth; _interior_point = copy._interior_point;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::compute_from_surface_normal // Function: CollisionEntry::get_surface_point
// Access: Private // Access: Published
// Description: Computes the "from" surface normal by converting the // Description: Returns the point, on the surface of the "into"
// "into" surface normal into the colliding object's // object, at which a collision is detected. This can
// space. // be thought of as the first point of intersection.
//
// The point will be converted into whichever coordinate
// space the caller specifies.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CollisionEntry:: LPoint3f CollisionEntry::
compute_from_surface_normal() { get_surface_point(const NodePath &space) const {
_from_surface_normal = get_into_surface_normal() * get_inv_wrt_mat(); nassertr(has_surface_point(), LPoint3f::zero());
_flags |= F_has_from_surface_normal; return _surface_point * _into_node_path.get_mat(space);
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_surface_normal
// Access: Published
// Description: Returns the surface normal of the "into" object at
// the point at which a collision is detected.
//
// The normal will be converted into whichever coordinate
// space the caller specifies.
////////////////////////////////////////////////////////////////////
LVector3f CollisionEntry::
get_surface_normal(const NodePath &space) const {
nassertr(has_surface_normal(), LVector3f::zero());
return _surface_normal * _into_node_path.get_mat(space);
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_interior_point
// Access: Published
// Description: Returns 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). It can be thought of as the deepest point
// of intersection.
//
// The point will be converted into whichever coordinate
// space the caller specifies.
////////////////////////////////////////////////////////////////////
LPoint3f CollisionEntry::
get_interior_point(const NodePath &space) const {
if (!has_interior_point()) {
return get_surface_point(space);
}
return _interior_point * _into_node_path.get_mat(space);
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_all
// Access: Published
// Description: Simultaneously transforms the surface point, surface
// normal, and interior point of the collision into the
// indicated coordinate space.
//
// Returns true if all three properties are available,
// or false if any one of them is not.
////////////////////////////////////////////////////////////////////
bool CollisionEntry::
get_all(const NodePath &space, LPoint3f &surface_point,
LVector3f &surface_normal, LPoint3f &interior_point) const {
const LMatrix4f &mat = _into_node_path.get_mat(space);
bool all_ok = true;
if (!has_surface_point()) {
surface_point = LPoint3f::zero();
all_ok = false;
} else {
surface_point = _surface_point * mat;
}
if (!has_surface_normal()) {
surface_normal = LVector3f::zero();
all_ok = false;
} else {
surface_normal = _surface_normal * mat;
}
if (!has_interior_point()) {
interior_point = surface_point;
all_ok = false;
} else {
interior_point = _interior_point * mat;
}
return true;
} }

View File

@ -62,41 +62,57 @@ PUBLISHED:
INLINE const NodePath &get_from_node_path() const; INLINE const NodePath &get_from_node_path() const;
INLINE const NodePath &get_into_node_path() const; INLINE const NodePath &get_into_node_path() const;
INLINE const TransformState *get_from_space() const; INLINE bool get_respect_prev_transform() const;
INLINE const TransformState *get_into_space() const;
INLINE const TransformState *get_wrt_space() const;
INLINE const TransformState *get_inv_wrt_space() const;
INLINE const TransformState *get_wrt_prev_space() const;
INLINE const LMatrix4f &get_from_mat() const; INLINE void set_surface_point(const LPoint3f &point);
INLINE const LMatrix4f &get_into_mat() const; INLINE void set_surface_normal(const LVector3f &normal);
INLINE const LMatrix4f &get_wrt_mat() const; INLINE void set_interior_point(const LPoint3f &point);
INLINE const LMatrix4f &get_inv_wrt_mat() const;
INLINE const LMatrix4f &get_wrt_prev_mat() const; INLINE bool has_surface_point() const;
INLINE bool has_surface_normal() const;
INLINE bool has_interior_point() const;
LPoint3f get_surface_point(const NodePath &space) const;
LVector3f get_surface_normal(const NodePath &space) const;
LPoint3f get_interior_point(const NodePath &space) const;
bool get_all(const NodePath &space,
LPoint3f &surface_point,
LVector3f &surface_normal,
LPoint3f &interior_point) const;
// The following methods are all deprecated in favor of the above
// methods. They are here only temporarily to ease transition.
INLINE void set_into_intersection_point(const LPoint3f &point);
INLINE bool has_into_intersection_point() const; INLINE bool has_into_intersection_point() const;
INLINE const LPoint3f &get_into_intersection_point() const; INLINE LPoint3f get_into_intersection_point() const;
INLINE bool has_from_intersection_point() const; INLINE bool has_from_intersection_point() const;
INLINE LPoint3f get_from_intersection_point() const; INLINE LPoint3f get_from_intersection_point() const;
INLINE void set_into_surface_normal(const LVector3f &normal);
INLINE bool has_into_surface_normal() const; INLINE bool has_into_surface_normal() const;
INLINE const LVector3f &get_into_surface_normal() const; INLINE LVector3f get_into_surface_normal() const;
INLINE void set_from_surface_normal(const LVector3f &normal);
INLINE bool has_from_surface_normal() const; INLINE bool has_from_surface_normal() const;
INLINE const LVector3f &get_from_surface_normal() const; INLINE LVector3f get_from_surface_normal() const;
INLINE void set_into_depth(float depth);
INLINE bool has_into_depth() const; INLINE bool has_into_depth() const;
INLINE float get_into_depth() const; INLINE float get_into_depth() const;
INLINE void set_from_depth(float depth);
INLINE bool has_from_depth() const; INLINE bool has_from_depth() const;
INLINE float get_from_depth() const; INLINE float get_from_depth() const;
public:
INLINE CPT(TransformState) get_wrt_space() const;
INLINE CPT(TransformState) get_inv_wrt_space() const;
INLINE CPT(TransformState) get_wrt_prev_space() const;
INLINE const LMatrix4f &get_wrt_mat() const;
INLINE const LMatrix4f &get_inv_wrt_mat() const;
INLINE const LMatrix4f &get_wrt_prev_mat() const;
private: private:
INLINE void test_intersection(CollisionHandler *record, INLINE void test_intersection(CollisionHandler *record,
const CollisionTraverser *trav) const; const CollisionTraverser *trav) const;
@ -109,27 +125,19 @@ private:
PT(PandaNode) _into_node; PT(PandaNode) _into_node;
NodePath _from_node_path; NodePath _from_node_path;
NodePath _into_node_path; NodePath _into_node_path;
CPT(TransformState) _from_space;
CPT(TransformState) _into_space;
CPT(TransformState) _wrt_space;
CPT(TransformState) _inv_wrt_space;
CPT(TransformState) _wrt_prev_space;
enum Flags { enum Flags {
F_has_into_intersection_point = 0x0001, F_has_surface_point = 0x0001,
F_has_into_surface_normal = 0x0002, F_has_surface_normal = 0x0002,
F_has_from_surface_normal = 0x0004, F_has_interior_point = 0x0004,
F_has_into_depth = 0x0008, F_respect_prev_transform = 0x0008,
F_has_from_depth = 0x0010,
}; };
int _flags; int _flags;
LPoint3f _into_intersection_point; LPoint3f _surface_point;
LVector3f _into_surface_normal; LVector3f _surface_normal;
LVector3f _from_surface_normal; LPoint3f _interior_point;
float _into_depth;
float _from_depth;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {

View File

@ -77,12 +77,7 @@ handle_entries() {
okflag = false; okflag = false;
} else { } else {
ColliderDef &def = (*ci).second; ColliderDef &def = (*ci).second;
if (!def.is_valid()) { {
collide_cat.error()
<< "Removing invalid collider " << from_node_path << " from "
<< get_type() << "\n";
_colliders.erase(ci);
} else {
// Get the maximum height for all collisions with this node. // Get the maximum height for all collisions with this node.
bool got_max = false; bool got_max = false;
float max_height = 0.0f; float max_height = 0.0f;
@ -93,8 +88,8 @@ handle_entries() {
nassertr(entry != (CollisionEntry *)NULL, false); nassertr(entry != (CollisionEntry *)NULL, false);
nassertr(from_node_path == entry->get_from_node_path(), false); nassertr(from_node_path == entry->get_from_node_path(), false);
if (entry->has_from_intersection_point()) { if (entry->has_surface_point()) {
LPoint3f point = entry->get_from_intersection_point(); LPoint3f point = entry->get_surface_point(def._target);
if (collide_cat.is_debug()) { if (collide_cat.is_debug()) {
collide_cat.debug() collide_cat.debug()
<< "Intersection point detected at " << point << "\n"; << "Intersection point detected at " << point << "\n";
@ -122,24 +117,14 @@ handle_entries() {
adjust = max(adjust, -max_adjust); adjust = max(adjust, -max_adjust);
} }
if (def._node != (PandaNode *)NULL) { CPT(TransformState) trans = def._target.get_transform();
// If we are adjusting a plain PandaNode, get the
// transform and adjust just the Z value to preserve
// maximum precision.
CPT(TransformState) trans = def._node->get_transform();
LVecBase3f pos = trans->get_pos(); LVecBase3f pos = trans->get_pos();
pos[2] += adjust; pos[2] += adjust;
def._node->set_transform(trans->set_pos(pos)); def._target.set_transform(trans->set_pos(pos));
def.updated_transform();
} else {
// Otherwise, go ahead and do the matrix math to do things
// the old and clumsy way.
LMatrix4f mat;
def.get_mat(mat);
mat(3, 2) += adjust;
def.set_mat(mat);
}
apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust)); apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust));
} else { } else {
if (collide_cat.is_spam()) { if (collide_cat.is_spam()) {
collide_cat.spam() collide_cat.spam()

View File

@ -17,49 +17,28 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::set_drive_interface
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionHandlerPhysical::ColliderDef::
set_drive_interface(DriveInterface *drive_interface) {
_drive_interface = drive_interface;
_node.clear();
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::set_node
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CollisionHandlerPhysical::ColliderDef::
set_node(PandaNode *node) {
_node = node;
_drive_interface.clear();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::set_target // Function: CollisionHandlerPhysical::ColliderDef::set_target
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void CollisionHandlerPhysical::ColliderDef:: INLINE void CollisionHandlerPhysical::ColliderDef::
set_target(const NodePath &target) { set_target(const NodePath &target, DriveInterface *drive_interface) {
_target = target; _target = target;
if (!target.is_empty()) { _drive_interface = drive_interface;
_node = target.node();
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::is_valid // Function: CollisionHandlerPhysical::ColliderDef::updated_transform
// Access: Public // Access: Public
// Description: Returns true if this ColliderDef is still valid; // Description: Called by the handler when it has changed the
// e.g. it refers to a valid node or drive interface. // transform on the target node, this applies the change
// to the drive interface if one is specified.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CollisionHandlerPhysical::ColliderDef:: INLINE void CollisionHandlerPhysical::ColliderDef::
is_valid() const { updated_transform() {
return (_node != (PandaNode *)NULL) || if (_drive_interface != (DriveInterface *)NULL) {
(_drive_interface != (DriveInterface *)NULL); _drive_interface->set_mat(_target.get_mat());
_drive_interface->force_dgraph();
}
} }

View File

@ -24,43 +24,6 @@
TypeHandle CollisionHandlerPhysical::_type_handle; TypeHandle CollisionHandlerPhysical::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::get_mat
// Access: Public
// Description: Fills mat with the matrix representing the current
// position and orientation of this collider.
////////////////////////////////////////////////////////////////////
void CollisionHandlerPhysical::ColliderDef::
get_mat(LMatrix4f &mat) const {
if (_node != (PandaNode *)NULL) {
mat = _node->get_transform()->get_mat();
} else if (_drive_interface != (DriveInterface *)NULL) {
mat = _drive_interface->get_mat();
} else {
collide_cat.error()
<< "Invalid CollisionHandlerPhysical::ColliderDef\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::ColliderDef::set_mat
// Access: Public
// Description: Moves this collider to the position and orientation
// indicated by the given transform.
////////////////////////////////////////////////////////////////////
void CollisionHandlerPhysical::ColliderDef::
set_mat(const LMatrix4f &mat) {
if (_node != (PandaNode *)NULL) {
_node->set_transform(TransformState::make_mat(mat));
} else if (_drive_interface != (DriveInterface *)NULL) {
_drive_interface->set_mat(mat);
_drive_interface->force_dgraph();
} else {
collide_cat.error()
<< "Invalid CollisionHandlerPhysical::ColliderDef\n";
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::Constructor // Function: CollisionHandlerPhysical::Constructor
// Access: Public // Access: Public
@ -140,6 +103,27 @@ add_collider(const NodePath &collider, const NodePath &target) {
_colliders[collider].set_target(target); _colliders[collider].set_target(target);
} }
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::add_collider
// Access: Published
// Description: Adds a new collider to the list with a NodePath
// that will be updated with the collider's new
// position, or updates the existing collider with a new
// NodePath object.
//
// The indicated DriveInterface will also be updated
// with the target's new transform each frame. This
// method should be used when the target is directly
// controlled by a DriveInterface.
////////////////////////////////////////////////////////////////////
void CollisionHandlerPhysical::
add_collider(const NodePath &collider, const NodePath &target,
DriveInterface *drive_interface) {
nassertv(!collider.is_empty() && collider.node()->is_of_type(CollisionNode::get_class_type()));
nassertv(!target.is_empty());
_colliders[collider].set_target(target, drive_interface);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::remove_collider // Function: CollisionHandlerPhysical::remove_collider
// Access: Published // Access: Published
@ -189,16 +173,3 @@ void CollisionHandlerPhysical::
add_collider_node(CollisionNode *node, PandaNode *target) { add_collider_node(CollisionNode *node, PandaNode *target) {
add_collider(NodePath(node), NodePath(target)); add_collider(NodePath(node), NodePath(target));
} }
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerPhysical::add_collider_drive
// Access: Published
// Description: Adds a new collider to the list with a DriveInterface
// pointer that needs to be told about the collider's
// new position, or updates the existing collider with a
// new DriveInterface pointer.
////////////////////////////////////////////////////////////////////
void CollisionHandlerPhysical::
add_collider_drive(CollisionNode *node, DriveInterface *drive_interface) {
_colliders[NodePath(node)].set_drive_interface(drive_interface);
}

View File

@ -46,6 +46,8 @@ public:
PUBLISHED: PUBLISHED:
void add_collider(const NodePath &collider, const NodePath &target); void add_collider(const NodePath &collider, const NodePath &target);
void add_collider(const NodePath &collider, const NodePath &target,
DriveInterface *drive_interface);
bool remove_collider(const NodePath &collider); bool remove_collider(const NodePath &collider);
bool has_collider(const NodePath &collider) const; bool has_collider(const NodePath &collider) const;
void clear_colliders(); void clear_colliders();
@ -54,9 +56,6 @@ PUBLISHED:
// transition to the above new NodePath-based methods. // transition to the above new NodePath-based methods.
void add_collider_node(CollisionNode *node, PandaNode *target); void add_collider_node(CollisionNode *node, PandaNode *target);
// add_collider_drive() is becoming obsolete. If you need it, let us know.
void add_collider_drive(CollisionNode *node, DriveInterface *drive_interface);
protected: protected:
typedef pvector< PT(CollisionEntry) > Entries; typedef pvector< PT(CollisionEntry) > Entries;
typedef pmap<NodePath, Entries> FromEntries; typedef pmap<NodePath, Entries> FromEntries;
@ -64,17 +63,12 @@ protected:
class ColliderDef { class ColliderDef {
public: public:
INLINE void set_drive_interface(DriveInterface *drive_interface); INLINE void set_target(const NodePath &target,
INLINE void set_node(PandaNode *node); DriveInterface *drive_interface = NULL);
INLINE void set_target(const NodePath &target); INLINE void updated_transform();
INLINE bool is_valid() const;
void get_mat(LMatrix4f &mat) const;
void set_mat(const LMatrix4f &mat);
PT(DriveInterface) _drive_interface;
PT(PandaNode) _node;
NodePath _target; NodePath _target;
PT(DriveInterface) _drive_interface;
}; };
typedef pmap<NodePath, ColliderDef> Colliders; typedef pmap<NodePath, ColliderDef> Colliders;

View File

@ -91,12 +91,7 @@ handle_entries() {
okflag = false; okflag = false;
} else { } else {
ColliderDef &def = (*ci).second; ColliderDef &def = (*ci).second;
if (!def.is_valid()) { {
collide_cat.error()
<< "Removing invalid collider " << from_node_path << " from "
<< get_type() << "\n";
_colliders.erase(ci);
} else {
// How to apply multiple shoves from different solids onto the // How to apply multiple shoves from different solids onto the
// same collider? One's first intuition is to vector sum all // same collider? One's first intuition is to vector sum all
// the shoves. However, this causes problems when two parallel // the shoves. However, this causes problems when two parallel
@ -114,19 +109,21 @@ handle_entries() {
nassertr(entry != (CollisionEntry *)NULL, false); nassertr(entry != (CollisionEntry *)NULL, false);
nassertr(from_node_path == entry->get_from_node_path(), false); nassertr(from_node_path == entry->get_from_node_path(), false);
if (!entry->has_from_surface_normal() || LPoint3f surface_point;
!entry->has_from_depth()) { LVector3f normal;
LPoint3f interior_point;
if (!entry->get_all(def._target, surface_point, normal, interior_point)) {
#ifndef NDEBUG #ifndef NDEBUG
if (collide_cat.is_debug()) { if (collide_cat.is_debug()) {
collide_cat.debug() collide_cat.debug()
<< "Cannot shove on " << from_node_path << " for collision into " << "Cannot shove on " << from_node_path << " for collision into "
<< *entry->get_into_node() << "; no normal/depth information.\n"; << entry->get_into_node_path() << "; no normal/depth information.\n";
} }
#endif #endif
} else { } else {
// Shove it just enough to clear the volume. // Shove it just enough to clear the volume.
if (entry->get_from_depth() != 0.0f) { if (!surface_point.almost_equal(interior_point)) {
LVector3f normal = entry->get_from_surface_normal();
if (_horizontal) { if (_horizontal) {
normal[2] = 0.0f; normal[2] = 0.0f;
} }
@ -137,7 +134,7 @@ handle_entries() {
ShoveData sd; ShoveData sd;
sd._vector = normal; sd._vector = normal;
sd._length = entry->get_from_depth(); sd._length = (surface_point - interior_point).length();
sd._valid = true; sd._valid = true;
sd._entry = entry; sd._entry = entry;
@ -145,7 +142,7 @@ handle_entries() {
if (collide_cat.is_debug()) { if (collide_cat.is_debug()) {
collide_cat.debug() collide_cat.debug()
<< "Shove on " << from_node_path << " from " << "Shove on " << from_node_path << " from "
<< *entry->get_into_node() << ": " << sd._vector << entry->get_into_node_path() << ": " << sd._vector
<< " times " << sd._length << "\n"; << " times " << sd._length << "\n";
} }
#endif #endif
@ -248,23 +245,13 @@ handle_entries() {
} }
#endif #endif
if (def._node != (PandaNode *)NULL) { CPT(TransformState) trans = def._target.get_transform();
// If we are adjusting a plain PandaNode, get the
// transform and adjust just the position to preserve
// maximum precision.
CPT(TransformState) trans = def._node->get_transform();
LVecBase3f pos = trans->get_pos(); LVecBase3f pos = trans->get_pos();
pos += net_shove * trans->get_mat(); pos += net_shove * trans->get_mat();
def._node->set_transform(trans->set_pos(pos)); def._target.set_transform(trans->set_pos(pos));
def.updated_transform();
apply_linear_force(def, force_normal); apply_linear_force(def, force_normal);
} else {
// Otherwise, go ahead and do the matrix math to do things
// the old and clumsy way.
LMatrix4f mat;
def.get_mat(mat);
def.set_mat(LMatrix4f::translate_mat(net_shove) * mat);
}
} }
} }
} }

View File

@ -108,9 +108,11 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere; const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0); DCAST_INTO_R(sphere, entry.get_from(), 0);
LPoint3f from_center = sphere->get_center() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LPoint3f from_center = sphere->get_center() * wrt_mat;
LVector3f from_radius_v = LVector3f from_radius_v =
LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat(); LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
float from_radius = length(from_radius_v); float from_radius = length(from_radius_v);
float dist = dist_to_plane(from_center); float dist = dist_to_plane(from_center);
@ -127,12 +129,10 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) new_entry = new CollisionEntry(entry); PT(CollisionEntry) new_entry = new CollisionEntry(entry);
LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat(); LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat();
float from_depth = from_radius - dist;
new_entry->set_into_surface_normal(get_normal()); new_entry->set_surface_normal(get_normal());
new_entry->set_from_surface_normal(from_normal); new_entry->set_surface_point(from_center - get_normal() * dist);
new_entry->set_from_depth(from_depth); new_entry->set_interior_point(from_center - get_normal() * from_radius);
new_entry->set_into_intersection_point(from_center - get_normal() * dist);
return new_entry; return new_entry;
} }
@ -147,8 +147,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray; const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0); DCAST_INTO_R(ray, entry.get_from(), 0);
LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
LPoint3f from_origin = ray->get_origin() * wrt_mat;
LVector3f from_direction = ray->get_direction() * wrt_mat;
float t; float t;
if (!_plane.intersects_line(t, from_origin, from_direction)) { if (!_plane.intersects_line(t, from_origin, from_direction)) {
@ -169,8 +171,8 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) new_entry = new CollisionEntry(entry); PT(CollisionEntry) new_entry = new CollisionEntry(entry);
LPoint3f into_intersection_point = from_origin + t * from_direction; LPoint3f into_intersection_point = from_origin + t * from_direction;
new_entry->set_into_surface_normal(get_normal()); new_entry->set_surface_normal(get_normal());
new_entry->set_into_intersection_point(into_intersection_point); new_entry->set_surface_point(into_intersection_point);
return new_entry; return new_entry;
} }

View File

@ -16,7 +16,6 @@
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "collisionPolygon.h" #include "collisionPolygon.h"
#include "collisionHandler.h" #include "collisionHandler.h"
#include "collisionEntry.h" #include "collisionEntry.h"
@ -34,6 +33,7 @@
#include "bamReader.h" #include "bamReader.h"
#include "bamWriter.h" #include "bamWriter.h"
#include "geomPolygon.h" #include "geomPolygon.h"
#include "transformState.h"
#include <algorithm> #include <algorithm>
@ -273,16 +273,21 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere; const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0); DCAST_INTO_R(sphere, entry.get_from(), 0);
LPoint3f orig_center = sphere->get_center() * entry.get_wrt_mat(); CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_space();
const LMatrix4f &wrt_mat = wrt_space->get_mat();
LPoint3f orig_center = sphere->get_center() * wrt_mat;
LPoint3f from_center = orig_center; LPoint3f from_center = orig_center;
bool moved_from_center = false; bool moved_from_center = false;
if (entry.get_wrt_prev_space() != entry.get_wrt_space()) { if (wrt_prev_space != wrt_space) {
// If we have a delta between the previous position and the // If we have a delta between the previous position and the
// current position, we use that to determine some more properties // current position, we use that to determine some more properties
// of the collision. // of the collision.
LPoint3f b = from_center; LPoint3f b = from_center;
LPoint3f a = sphere->get_center() * entry.get_wrt_prev_mat(); LPoint3f a = sphere->get_center() * wrt_prev_space->get_mat();
LVector3f delta = b - a; LVector3f delta = b - a;
// First, there is no collision if the "from" object is moving in // First, there is no collision if the "from" object is moving in
@ -317,7 +322,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
} }
LVector3f from_radius_v = LVector3f from_radius_v =
LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat(); LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
float from_radius = length(from_radius_v); float from_radius = length(from_radius_v);
float dist = dist_to_plane(from_center); float dist = dist_to_plane(from_center);
@ -406,15 +411,9 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
into_depth = from_radius - dist_to_plane(orig_center); into_depth = from_radius - dist_to_plane(orig_center);
} }
new_entry->set_into_surface_normal(get_normal()); new_entry->set_surface_normal(get_normal());
new_entry->set_into_depth(into_depth); new_entry->set_surface_point(from_center - get_normal() * dist);
new_entry->set_interior_point(from_center - get_normal() * (dist + into_depth));
LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat();
LVector3f from_depth_vec = (get_normal() * into_depth) * entry.get_inv_wrt_mat();
new_entry->set_from_surface_normal(from_normal);
new_entry->set_from_depth(from_depth_vec.length());
new_entry->set_into_intersection_point(from_center - get_normal() * dist);
return new_entry; return new_entry;
} }
@ -435,8 +434,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray; const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0); DCAST_INTO_R(ray, entry.get_from(), 0);
LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
LPoint3f from_origin = ray->get_origin() * wrt_mat;
LVector3f from_direction = ray->get_direction() * wrt_mat;
float t; float t;
if (!get_plane().intersects_line(t, from_origin, from_direction)) { if (!get_plane().intersects_line(t, from_origin, from_direction)) {
@ -462,8 +463,8 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
} }
PT(CollisionEntry) new_entry = new CollisionEntry(entry); PT(CollisionEntry) new_entry = new CollisionEntry(entry);
new_entry->set_into_surface_normal(get_normal()); new_entry->set_surface_normal(get_normal());
new_entry->set_into_intersection_point(plane_point); new_entry->set_surface_point(plane_point);
return new_entry; return new_entry;
} }
@ -484,8 +485,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment; const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0); DCAST_INTO_R(segment, entry.get_from(), 0);
LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
LPoint3f from_a = segment->get_point_a() * wrt_mat;
LPoint3f from_b = segment->get_point_b() * wrt_mat;
LPoint3f from_direction = from_b - from_a; LPoint3f from_direction = from_b - from_a;
float t; float t;
@ -513,8 +516,8 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
} }
PT(CollisionEntry) new_entry = new CollisionEntry(entry); PT(CollisionEntry) new_entry = new CollisionEntry(entry);
new_entry->set_into_surface_normal(get_normal()); new_entry->set_surface_normal(get_normal());
new_entry->set_into_intersection_point(plane_point); new_entry->set_surface_point(plane_point);
return new_entry; return new_entry;
} }

View File

@ -121,9 +121,11 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere; const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0); DCAST_INTO_R(sphere, entry.get_from(), 0);
LPoint3f from_center = sphere->get_center() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LPoint3f from_center = sphere->get_center() * wrt_mat;
LVector3f from_radius_v = LVector3f from_radius_v =
LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat(); LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
float from_radius = length(from_radius_v); float from_radius = length(from_radius_v);
LPoint3f into_center = _center; LPoint3f into_center = _center;
@ -143,26 +145,20 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
} }
PT(CollisionEntry) new_entry = new CollisionEntry(entry); PT(CollisionEntry) new_entry = new CollisionEntry(entry);
float dist = sqrtf(dist2); LVector3f surface_normal;
LVector3f into_normal;
float vec_length = vec.length(); float vec_length = vec.length();
if (IS_NEARLY_ZERO(vec_length)) { if (IS_NEARLY_ZERO(vec_length)) {
// If we don't have a collision normal (e.g. the centers are // If we don't have a collision normal (e.g. the centers are
// exactly coincident), then make up an arbitrary normal--any one // exactly coincident), then make up an arbitrary normal--any one
// is as good as any other. // is as good as any other.
into_normal.set(1.0, 0.0, 0.0); surface_normal.set(1.0, 0.0, 0.0);
} else { } else {
into_normal = vec / vec_length; surface_normal = vec / vec_length;
} }
LPoint3f into_intersection_point = into_normal * (dist - from_radius);
float into_depth = into_radius + from_radius - dist;
new_entry->set_into_surface_normal(into_normal); new_entry->set_surface_normal(surface_normal);
new_entry->set_into_intersection_point(into_intersection_point); new_entry->set_surface_point(into_center + surface_normal * into_radius);
new_entry->set_into_depth(into_depth); new_entry->set_interior_point(from_center - surface_normal * from_radius);
LVector3f from_depth_vec = (into_normal * into_depth) * entry.get_inv_wrt_mat();
new_entry->set_from_depth(from_depth_vec.length());
return new_entry; return new_entry;
} }
@ -177,8 +173,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray; const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0); DCAST_INTO_R(ray, entry.get_from(), 0);
LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
LPoint3f from_origin = ray->get_origin() * wrt_mat;
LVector3f from_direction = ray->get_direction() * wrt_mat;
double t1, t2; double t1, t2;
if (!intersects_line(t1, t2, from_origin, from_direction)) { if (!intersects_line(t1, t2, from_origin, from_direction)) {
@ -208,7 +206,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
// at t1. // at t1.
into_intersection_point = from_origin + t1 * from_direction; into_intersection_point = from_origin + t1 * from_direction;
} }
new_entry->set_into_intersection_point(into_intersection_point); new_entry->set_surface_point(into_intersection_point);
return new_entry; return new_entry;
} }
@ -223,8 +221,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment; const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0); DCAST_INTO_R(segment, entry.get_from(), 0);
LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
LPoint3f from_a = segment->get_point_a() * wrt_mat;
LPoint3f from_b = segment->get_point_b() * wrt_mat;
LVector3f from_direction = from_b - from_a; LVector3f from_direction = from_b - from_a;
double t1, t2; double t1, t2;
@ -256,7 +256,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
// sphere or beyond it. The first intersection point is at t1. // sphere or beyond it. The first intersection point is at t1.
into_intersection_point = from_a + t1 * from_direction; into_intersection_point = from_a + t1 * from_direction;
} }
new_entry->set_into_intersection_point(into_intersection_point); new_entry->set_surface_point(into_intersection_point);
return new_entry; return new_entry;
} }

View File

@ -452,7 +452,9 @@ r_traverse(CollisionLevelState &level_state) {
CollisionEntry entry; CollisionEntry entry;
entry._into_node = cnode; entry._into_node = cnode;
entry._into_node_path = level_state.get_node_path(); entry._into_node_path = level_state.get_node_path();
entry._into_space = entry._into_node_path.get_net_transform(); if (_respect_prev_transform) {
entry._flags |= CollisionEntry::F_respect_prev_transform;
}
int num_colliders = level_state.get_num_colliders(); int num_colliders = level_state.get_num_colliders();
for (int c = 0; c < num_colliders; c++) { for (int c = 0; c < num_colliders; c++) {
@ -463,17 +465,6 @@ r_traverse(CollisionLevelState &level_state) {
cnode->get_into_collide_mask()) != 0) { cnode->get_into_collide_mask()) != 0) {
entry._from_node_path = level_state.get_collider_node_path(c); entry._from_node_path = level_state.get_collider_node_path(c);
entry._from = level_state.get_collider(c); entry._from = level_state.get_collider(c);
entry._from_space = entry._from_node_path.get_net_transform();
entry._wrt_space = entry._from_node_path.get_transform(entry._into_node_path);
entry._inv_wrt_space = entry._into_node_path.get_transform(entry._from_node_path);
if (_respect_prev_transform) {
entry._wrt_prev_space = entry._from_node_path.get_prev_transform(entry._into_node_path);
} else {
entry._wrt_prev_space = entry._wrt_space;
}
compare_collider_to_node(entry, compare_collider_to_node(entry,
level_state.get_parent_bound(c), level_state.get_parent_bound(c),
@ -502,7 +493,9 @@ r_traverse(CollisionLevelState &level_state) {
CollisionEntry entry; CollisionEntry entry;
entry._into_node = gnode; entry._into_node = gnode;
entry._into_node_path = level_state.get_node_path(); entry._into_node_path = level_state.get_node_path();
entry._into_space = entry._into_node_path.get_net_transform(); if (_respect_prev_transform) {
entry._flags |= CollisionEntry::F_respect_prev_transform;
}
int num_colliders = level_state.get_num_colliders(); int num_colliders = level_state.get_num_colliders();
for (int c = 0; c < num_colliders; c++) { for (int c = 0; c < num_colliders; c++) {
@ -510,10 +503,6 @@ r_traverse(CollisionLevelState &level_state) {
entry._from_node = level_state.get_collider_node(c); entry._from_node = level_state.get_collider_node(c);
entry._from_node_path = level_state.get_collider_node_path(c); entry._from_node_path = level_state.get_collider_node_path(c);
entry._from = level_state.get_collider(c); entry._from = level_state.get_collider(c);
entry._from_space = entry._from_node_path.get_net_transform();
entry._wrt_space = entry._from_node_path.get_transform(entry._into_node_path);
entry._inv_wrt_space = entry._into_node_path.get_transform(entry._from_node_path);
compare_collider_to_geom_node(entry, compare_collider_to_geom_node(entry,
level_state.get_parent_bound(c), level_state.get_parent_bound(c),
@ -641,7 +630,7 @@ compare_collider_to_solid(CollisionEntry &entry,
} }
if (within_solid_bounds) { if (within_solid_bounds) {
Colliders::const_iterator ci; Colliders::const_iterator ci;
ci = _colliders.find(entry.get_from_node()); ci = _colliders.find(entry.get_from_node_path());
nassertv(ci != _colliders.end()); nassertv(ci != _colliders.end());
entry.test_intersection((*ci).second, this); entry.test_intersection((*ci).second, this);
} }
@ -663,7 +652,7 @@ compare_collider_to_geom(CollisionEntry &entry, Geom *geom,
} }
if (within_geom_bounds) { if (within_geom_bounds) {
Colliders::const_iterator ci; Colliders::const_iterator ci;
ci = _colliders.find(entry.get_from_node()); ci = _colliders.find(entry.get_from_node_path());
nassertv(ci != _colliders.end()); nassertv(ci != _colliders.end());
PTA_Vertexf coords; PTA_Vertexf coords;

View File

@ -108,6 +108,12 @@ private:
PT(CollisionHandler) _default_handler; PT(CollisionHandler) _default_handler;
TypeHandle _graph_type; TypeHandle _graph_type;
// A map of NodePaths is slightly dangerous, since there is a
// (small) possiblity that a particular NodePath's sorting order
// relative to other NodePaths will spontaneously change. This can
// only happen if two NodePaths get collapsed together due to a
// removal of a certain kind of instanced node; see the comments in
// NodePath.cxx.
typedef pmap<NodePath, PT(CollisionHandler) > Colliders; typedef pmap<NodePath, PT(CollisionHandler) > Colliders;
Colliders _colliders; Colliders _colliders;
typedef pvector<NodePath> OrderedColliders; typedef pvector<NodePath> OrderedColliders;

View File

@ -31,6 +31,7 @@
#include "bamReader.h" #include "bamReader.h"
#include "bamWriter.h" #include "bamWriter.h"
#include "cmath.h" #include "cmath.h"
#include "transformState.h"
TypeHandle CollisionTube::_type_handle; TypeHandle CollisionTube::_type_handle;
@ -130,19 +131,24 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere; const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0); DCAST_INTO_R(sphere, entry.get_from(), 0);
LPoint3f from_a = sphere->get_center() * entry.get_wrt_mat(); CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_space();
const LMatrix4f &wrt_mat = wrt_space->get_mat();
LPoint3f from_a = sphere->get_center() * wrt_mat;
LPoint3f from_b = from_a; LPoint3f from_b = from_a;
if (entry.get_wrt_prev_space() != entry.get_wrt_space()) { if (wrt_prev_space != wrt_space) {
// If the sphere is moving relative to the tube, it becomes a tube // If the sphere is moving relative to the tube, it becomes a tube
// itself. // itself.
from_a = sphere->get_center() * entry.get_wrt_prev_mat(); from_a = sphere->get_center() * wrt_prev_space->get_mat();
} }
LVector3f from_direction = from_b - from_a; LVector3f from_direction = from_b - from_a;
LVector3f from_radius_v = LVector3f from_radius_v =
LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat(); LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
float from_radius = length(from_radius_v); float from_radius = length(from_radius_v);
double t1, t2; double t1, t2;
@ -189,8 +195,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray; const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0); DCAST_INTO_R(ray, entry.get_from(), 0);
LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
LPoint3f from_origin = ray->get_origin() * wrt_mat;
LVector3f from_direction = ray->get_direction() * wrt_mat;
double t1, t2; double t1, t2;
if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) { if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
@ -235,8 +243,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment; const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0); DCAST_INTO_R(segment, entry.get_from(), 0);
LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat(); const LMatrix4f &wrt_mat = entry.get_wrt_mat();
LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
LPoint3f from_a = segment->get_point_a() * wrt_mat;
LPoint3f from_b = segment->get_point_b() * wrt_mat;
LVector3f from_direction = from_b - from_a; LVector3f from_direction = from_b - from_a;
double t1, t2; double t1, t2;
@ -683,16 +693,9 @@ set_intersection_point(CollisionEntry *new_entry,
// our collision was tangential. // our collision was tangential.
LPoint3f orig_point = into_intersection_point - normal * extra_radius; LPoint3f orig_point = into_intersection_point - normal * extra_radius;
// And the difference between point and orig_point is the depth to new_entry->set_surface_point(point);
// which the object has intersected the tube. new_entry->set_surface_normal(normal);
float depth = (point - orig_point).length(); new_entry->set_interior_point(orig_point);
new_entry->set_into_intersection_point(point);
new_entry->set_into_surface_normal(normal);
new_entry->set_into_depth(depth);
LVector3f from_depth_vec = (normal * depth) * new_entry->get_inv_wrt_mat();
new_entry->set_from_depth(from_depth_vec.length());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -27,3 +27,30 @@ SolidInfo() {
_detected_count = 0; _detected_count = 0;
_missed_count = 0; _missed_count = 0;
} }
////////////////////////////////////////////////////////////////////
// Function: CollisionVisualizer::set_viz_scale
// Access: Published
// Description: Scales the objects that are drawn to represent the
// normals and points of the collisions. By default,
// these objects are drawn at an arbitrary scale which
// is appropriate if the scene units are measured in
// feet. Change this scale accordinatly if the scene
// units are measured on some other scale or if you need
// to observe these objects from farther away.
////////////////////////////////////////////////////////////////////
INLINE void CollisionVisualizer::
set_viz_scale(float viz_scale) {
_viz_scale = viz_scale;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionVisualizer::get_viz_scale
// Access: Published
// Description: Returns the value last set by set_viz_scale().
////////////////////////////////////////////////////////////////////
INLINE float CollisionVisualizer::
get_viz_scale() const {
return _viz_scale;
}

View File

@ -45,6 +45,7 @@ CollisionVisualizer(const string &name) : PandaNode(name) {
// We always want to render the CollisionVisualizer node itself // We always want to render the CollisionVisualizer node itself
// (even if it doesn't appear to have any geometry within it). // (even if it doesn't appear to have any geometry within it).
set_bound(OmniBoundingVolume()); set_bound(OmniBoundingVolume());
_viz_scale = 1.0f;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -167,28 +168,39 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) { for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
const CollisionPoint &point = (*pi); const CollisionPoint &point = (*pi);
// Draw a tiny sphere at the collision point. // Draw a small red sphere at the surface point, and a smaller
// white sphere at the interior point.
{ {
PT(GeomSphere) sphere = new GeomSphere; PT(GeomSphere) sphere = new GeomSphere;
PTA_Vertexf verts; PTA_Vertexf verts;
verts.push_back(point._point); verts.push_back(point._surface_point);
verts.push_back(point._point + LVector3f(0.1f, 0.0f, 0.0f)); verts.push_back(point._surface_point +
LVector3f(0.1f * _viz_scale, 0.0f, 0.0f));
sphere->set_coords(verts); sphere->set_coords(verts);
sphere->set_colors(colors, G_OVERALL); sphere->set_colors(colors, G_PER_PRIM);
sphere->set_num_prims(1); sphere->set_num_prims(1);
if (point._interior_point != point._surface_point) {
verts.push_back(point._interior_point);
verts.push_back(point._interior_point +
LVector3f(0.05f * _viz_scale, 0.0f, 0.0f));
sphere->set_num_prims(2);
}
CullableObject *object = CullableObject *object =
new CullableObject(sphere, empty_state, xform_data._render_transform); new CullableObject(sphere, empty_state, xform_data._render_transform);
trav->get_cull_handler()->record_object(object); trav->get_cull_handler()->record_object(object);
} }
// Draw the normal vector at the collision point. // Draw the normal vector at the surface point.
if (!point._normal.almost_equal(LVector3f::zero())) { if (!point._surface_normal.almost_equal(LVector3f::zero())) {
PT(GeomLine) line = new GeomLine; PT(GeomLine) line = new GeomLine;
PTA_Vertexf verts; PTA_Vertexf verts;
verts.push_back(point._point); verts.push_back(point._surface_point);
verts.push_back(point._point + point._normal); verts.push_back(point._surface_point +
point._surface_normal * _viz_scale);
line->set_coords(verts); line->set_coords(verts);
line->set_colors(colors, G_PER_VERTEX); line->set_colors(colors, G_PER_VERTEX);
line->set_num_prims(1); line->set_num_prims(1);
@ -197,25 +209,6 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
new CullableObject(line, empty_state, xform_data._render_transform); new CullableObject(line, empty_state, xform_data._render_transform);
trav->get_cull_handler()->record_object(object); trav->get_cull_handler()->record_object(object);
// Also draw the depth vector.
if (point._depth != 0.0) {
PT(GeomLine) line = new GeomLine;
PTA_Vertexf verts;
verts.push_back(point._point);
verts.push_back(point._point - point._normal * point._depth);
PTA_Colorf colors;
colors.push_back(Colorf(0.0f, 0.0f, 1.0f, 1.0f));
line->set_coords(verts);
line->set_colors(colors, G_OVERALL);
line->set_num_prims(1);
CullableObject *object =
new CullableObject(line, empty_state, xform_data._render_transform);
trav->get_cull_handler()->record_object(object);
}
} }
} }
} }
@ -272,18 +265,15 @@ collision_tested(const CollisionEntry &entry, bool detected) {
if (detected) { if (detected) {
viz_info._solids[entry.get_into()]._detected_count++; viz_info._solids[entry.get_into()]._detected_count++;
if (entry.has_into_intersection_point()) { if (entry.has_surface_point()) {
CollisionPoint p; CollisionPoint p;
p._point = entry.get_into_intersection_point(); p._surface_point = entry.get_surface_point(entry.get_into_node_path());
if (entry.has_into_surface_normal()) { if (entry.has_surface_normal()) {
p._normal = entry.get_into_surface_normal(); p._surface_normal = entry.get_surface_normal(entry.get_into_node_path());
} else { } else {
p._normal = LVector3f::zero(); p._surface_normal = LVector3f::zero();
p._depth = 0.0;
}
if (entry.has_into_depth()) {
p._depth = entry.get_into_depth();
} }
p._interior_point = entry.get_interior_point(entry.get_into_node_path());
viz_info._points.push_back(p); viz_info._points.push_back(p);
} }

View File

@ -41,6 +41,9 @@ PUBLISHED:
CollisionVisualizer(const string &name); CollisionVisualizer(const string &name);
virtual ~CollisionVisualizer(); virtual ~CollisionVisualizer();
INLINE void set_viz_scale(float viz_scale);
INLINE float get_viz_scale() const;
void clear(); void clear();
public: public:
@ -69,9 +72,9 @@ private:
class CollisionPoint { class CollisionPoint {
public: public:
LPoint3f _point; LPoint3f _surface_point;
LVector3f _normal; LVector3f _surface_normal;
float _depth; LPoint3f _interior_point;
}; };
typedef pvector<CollisionPoint> Points; typedef pvector<CollisionPoint> Points;
@ -84,6 +87,8 @@ private:
typedef map<CPT(TransformState), VizInfo> Data; typedef map<CPT(TransformState), VizInfo> Data;
Data _data; Data _data;
float _viz_scale;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;