diff --git a/panda/src/collide/collisionEntry.I b/panda/src/collide/collisionEntry.I index f0ca2dc0e3..0bad75aa10 100644 --- a/panda/src/collide/collisionEntry.I +++ b/panda/src/collide/collisionEntry.I @@ -294,6 +294,46 @@ get_into_surface_normal() const { return _into_surface_normal; } +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::set_from_surface_normal +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CollisionEntry:: +set_from_surface_normal(const LVector3f &normal) { + _from_surface_normal = normal; + _flags |= F_has_from_surface_normal; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::has_from_surface_normal +// Access: Public +// Description: Returns true if the detected collision knows the +// surface normal of the collided-into object at the +// point of the collision, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool CollisionEntry:: +has_from_surface_normal() const { + return (_flags & (F_has_into_surface_normal | F_has_from_surface_normal)) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::get_from_surface_normal +// Access: Public +// Description: Returns the surface normal of the collided-into +// object at the point of the collision, in the space of +// the collided-from object. It is an error to call +// this if has_from_surface_normal() returns false. +//////////////////////////////////////////////////////////////////// +INLINE const LVector3f &CollisionEntry:: +get_from_surface_normal() const { + nassertr(has_from_surface_normal(), _from_surface_normal); + if ((_flags & F_has_from_surface_normal) == 0) { + ((CollisionEntry *)this)->compute_from_surface_normal(); + } + return _from_surface_normal; +} + //////////////////////////////////////////////////////////////////// // Function: CollisionEntry::set_into_depth @@ -333,3 +373,42 @@ get_into_depth() const { nassertr(has_into_depth(), 0.0); return _into_depth; } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::set_from_depth +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CollisionEntry:: +set_from_depth(float depth) { + _from_depth = depth; + _flags |= F_has_from_depth; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::has_from_depth +// Access: Public +// Description: Returns true if the collision entry knows how "deep" +// the collision was from the collided-from object; that +// is, how far from the surface of the collided-from +// object the colliding object has penetrated. +//////////////////////////////////////////////////////////////////// +INLINE bool CollisionEntry:: +has_from_depth() const { + return (_flags & F_has_from_depth) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::get_from_depth +// Access: Public +// Description: Returns how "deep" the collision was from the +// collided-from object; that is, how far from the +// surface of the collided-from object the colliding +// object has penetrated. It is an error to call this +// if has_from_depth() returns false. +//////////////////////////////////////////////////////////////////// +INLINE float CollisionEntry:: +get_from_depth() const { + nassertr(has_from_depth(), 0.0); + return _from_depth; +} diff --git a/panda/src/collide/collisionEntry.cxx b/panda/src/collide/collisionEntry.cxx index 2ba8d393ec..cc039afabd 100644 --- a/panda/src/collide/collisionEntry.cxx +++ b/panda/src/collide/collisionEntry.cxx @@ -64,3 +64,16 @@ operator = (const CollisionEntry ©) { _into_surface_normal = copy._into_surface_normal; _into_depth = copy._into_depth; } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionEntry::compute_from_surface_normal +// Access: Private +// Description: Computes the "from" surface normal by converting the +// "into" surface normal into the colliding object's +// space. +//////////////////////////////////////////////////////////////////// +void CollisionEntry:: +compute_from_surface_normal() { + _from_surface_normal = get_into_surface_normal() * get_inv_wrt_space(); + _flags |= F_has_from_surface_normal; +} diff --git a/panda/src/collide/collisionEntry.h b/panda/src/collide/collisionEntry.h index 325e508c0e..0f3e525eea 100644 --- a/panda/src/collide/collisionEntry.h +++ b/panda/src/collide/collisionEntry.h @@ -78,11 +78,21 @@ PUBLISHED: INLINE bool has_into_surface_normal() const; INLINE const LVector3f &get_into_surface_normal() const; + INLINE void set_from_surface_normal(const LVector3f &normal); + INLINE bool has_from_surface_normal() const; + INLINE const LVector3f &get_from_surface_normal() const; + INLINE void set_into_depth(float depth); INLINE bool has_into_depth() const; INLINE float get_into_depth() const; + INLINE void set_from_depth(float depth); + INLINE bool has_from_depth() const; + INLINE float get_from_depth() const; + private: + void compute_from_surface_normal(); + CPT(CollisionSolid) _from; CPT(CollisionSolid) _into; @@ -97,8 +107,10 @@ private: enum Flags { F_has_into_intersection_point = 0x0001, F_has_into_surface_normal = 0x0002, - F_has_into_depth = 0x0004, - F_has_from_velocity = 0x0008, + F_has_from_surface_normal = 0x0004, + F_has_into_depth = 0x0008, + F_has_from_depth = 0x0010, + F_has_from_velocity = 0x0020, }; int _flags; @@ -106,7 +118,9 @@ private: LVector3f _from_velocity; LPoint3f _into_intersection_point; LVector3f _into_surface_normal; + LVector3f _from_surface_normal; float _into_depth; + float _from_depth; public: static TypeHandle get_class_type() { diff --git a/panda/src/collide/collisionHandlerPusher.cxx b/panda/src/collide/collisionHandlerPusher.cxx index 7749c62b48..9eca9627a1 100644 --- a/panda/src/collide/collisionHandlerPusher.cxx +++ b/panda/src/collide/collisionHandlerPusher.cxx @@ -117,8 +117,8 @@ handle_entries() { nassertr(entry != (CollisionEntry *)NULL, false); nassertr(from_node == entry->get_from_node(), false); - if (!entry->has_into_surface_normal() || - !entry->has_into_depth()) { + if (!entry->has_from_surface_normal() || + !entry->has_from_depth()) { #ifndef NDEBUG if (collide_cat.is_debug()) { collide_cat.debug() @@ -129,8 +129,8 @@ handle_entries() { } else { // Shove it just enough to clear the volume. - if (entry->get_into_depth() != 0.0f) { - LVector3f normal = entry->get_into_surface_normal(); + if (entry->get_from_depth() != 0.0f) { + LVector3f normal = entry->get_from_surface_normal(); if (_horizontal) { normal[2] = 0.0f; } @@ -141,7 +141,7 @@ handle_entries() { ShoveData sd; sd._vector = normal; - sd._length = entry->get_into_depth(); + sd._length = entry->get_from_depth(); sd._valid = true; sd._entry = entry; diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index 40aa581321..957f407f6e 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -141,11 +141,13 @@ test_intersection_from_sphere(CollisionHandler *record, } PT(CollisionEntry) new_entry = new CollisionEntry(entry); - LVector3f into_normal = get_normal() * entry.get_inv_wrt_space(); - float into_depth = from_radius - dist; + LVector3f from_normal = get_normal() * entry.get_inv_wrt_space(); + float from_depth = from_radius - dist; - new_entry->set_into_surface_normal(into_normal); - new_entry->set_into_depth(into_depth); + new_entry->set_into_surface_normal(get_normal()); + new_entry->set_from_surface_normal(from_normal); + new_entry->set_from_depth(from_depth); + new_entry->set_into_intersection_point(from_center); record->add_entry(new_entry); return 1; @@ -184,6 +186,7 @@ test_intersection_from_ray(CollisionHandler *record, PT(CollisionEntry) new_entry = new CollisionEntry(entry); LPoint3f into_intersection_point = from_origin + t * from_direction; + new_entry->set_into_surface_normal(get_normal()); new_entry->set_into_intersection_point(into_intersection_point); record->add_entry(new_entry); diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index d600c472e8..04254b87d0 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -364,17 +364,18 @@ test_intersection_from_sphere(CollisionHandler *record, } PT(CollisionEntry) new_entry = new CollisionEntry(entry); - LVector3f into_normal = get_normal() * entry.get_inv_wrt_space(); - float into_depth = from_radius - dist; + LVector3f from_normal = get_normal() * entry.get_inv_wrt_space(); + float from_depth = from_radius - dist; if (moved_from_center) { // We have to base the depth of intersection on the sphere's final // resting point, not the point from which we tested the // intersection. - into_depth = from_radius - dist_to_plane(orig_center); + from_depth = from_radius - dist_to_plane(orig_center); } - new_entry->set_into_surface_normal(into_normal); - new_entry->set_into_depth(into_depth); + new_entry->set_into_surface_normal(get_normal()); + new_entry->set_from_surface_normal(from_normal); + new_entry->set_from_depth(from_depth); new_entry->set_into_intersection_point(from_center); record->add_entry(new_entry); @@ -423,11 +424,9 @@ test_intersection_from_ray(CollisionHandler *record, } PT(CollisionEntry) new_entry = new CollisionEntry(entry); + new_entry->set_into_surface_normal(get_normal()); new_entry->set_into_intersection_point(plane_point); - LVector3f into_normal = get_normal() * entry.get_inv_wrt_space(); - new_entry->set_into_surface_normal(into_normal); - record->add_entry(new_entry); return 1; } @@ -476,11 +475,9 @@ test_intersection_from_segment(CollisionHandler *record, } PT(CollisionEntry) new_entry = new CollisionEntry(entry); + new_entry->set_into_surface_normal(get_normal()); new_entry->set_into_intersection_point(plane_point); - LVector3f into_normal = get_normal() * entry.get_inv_wrt_space(); - new_entry->set_into_surface_normal(into_normal); - record->add_entry(new_entry); return 1; } diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 2cb07cffbb..215e2d3cb4 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -150,10 +150,16 @@ test_intersection_from_sphere(CollisionHandler *record, 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 * entry.get_inv_wrt_space()); - new_entry->set_into_intersection_point(into_intersection_point * entry.get_inv_wrt_space()); + new_entry->set_into_surface_normal(into_normal); + new_entry->set_into_intersection_point(into_intersection_point); new_entry->set_into_depth(into_depth); + // This is a bit of a hack. This result is incorrect if there is a + // scale between the colliding object and this sphere. We need to + // account for that scale, but to account for it correctly + // (especially including non-uniform scales) is rather complicated. + new_entry->set_from_depth(into_depth); + record->add_entry(new_entry); return 1; }