From 519ae6bdac62116ccd8dfed8bbe494fb7d1e0d1b Mon Sep 17 00:00:00 2001 From: Darren Ranalli Date: Fri, 24 Aug 2007 19:23:44 +0000 Subject: [PATCH] fluid pusher almost working --- panda/src/collide/collide_composite1.cxx | 1 + panda/src/collide/collisionEntry.I | 23 ++++++++ panda/src/collide/collisionEntry.cxx | 2 + panda/src/collide/collisionEntry.h | 5 ++ panda/src/collide/collisionHandler.I | 40 ++++++++++++++ panda/src/collide/collisionHandler.cxx | 10 ++++ panda/src/collide/collisionHandler.h | 12 ++++ .../collide/collisionHandlerFluidPusher.cxx | 55 ++++++++++++++----- .../src/collide/collisionHandlerFluidPusher.h | 5 ++ panda/src/collide/collisionHandlerPusher.h | 1 - panda/src/collide/collisionInvSphere.cxx | 2 +- panda/src/collide/collisionPolygon.cxx | 6 +- panda/src/collide/collisionSolid.h | 1 + panda/src/collide/collisionTraverser.cxx | 1 + panda/src/collide/collisionTube.cxx | 1 + 15 files changed, 148 insertions(+), 17 deletions(-) create mode 100755 panda/src/collide/collisionHandler.I diff --git a/panda/src/collide/collide_composite1.cxx b/panda/src/collide/collide_composite1.cxx index 6021b7650c..47ee731d69 100644 --- a/panda/src/collide/collide_composite1.cxx +++ b/panda/src/collide/collide_composite1.cxx @@ -7,6 +7,7 @@ #include "collisionHandlerGravity.cxx" #include "collisionHandlerPhysical.cxx" #include "collisionHandlerPusher.cxx" +#include "collisionHandlerFluidPusher.cxx" #include "collisionHandlerQueue.cxx" #include "collisionDSSolid.cxx" #include "collisionInvSphere.cxx" diff --git a/panda/src/collide/collisionEntry.I b/panda/src/collide/collisionEntry.I index b9d93278a5..7032ed41ce 100644 --- a/panda/src/collide/collisionEntry.I +++ b/panda/src/collide/collisionEntry.I @@ -25,6 +25,7 @@ INLINE CollisionEntry:: CollisionEntry() { _flags = 0; + _t = 1.f; } //////////////////////////////////////////////////////////////////// @@ -125,6 +126,28 @@ 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::get_respect_prev_transform // Access: Published diff --git a/panda/src/collide/collisionEntry.cxx b/panda/src/collide/collisionEntry.cxx index 5bed0ed06b..19b8010247 100644 --- a/panda/src/collide/collisionEntry.cxx +++ b/panda/src/collide/collisionEntry.cxx @@ -36,6 +36,7 @@ CollisionEntry(const CollisionEntry ©) : _from_node_path(copy._from_node_path), _into_node_path(copy._into_node_path), _into_clip_planes(copy._into_clip_planes), + _t(copy._t), _flags(copy._flags), _surface_point(copy._surface_point), _surface_normal(copy._surface_normal), @@ -57,6 +58,7 @@ operator = (const CollisionEntry ©) { _from_node_path = copy._from_node_path; _into_node_path = copy._into_node_path; _into_clip_planes = copy._into_clip_planes; + _t = copy._t; _flags = copy._flags; _surface_point = copy._surface_point; _surface_normal = copy._surface_normal; diff --git a/panda/src/collide/collisionEntry.h b/panda/src/collide/collisionEntry.h index 624906ed0d..226dc9c082 100644 --- a/panda/src/collide/collisionEntry.h +++ b/panda/src/collide/collisionEntry.h @@ -63,6 +63,9 @@ PUBLISHED: INLINE NodePath get_from_node_path() const; INLINE NodePath get_into_node_path() const; + INLINE void set_t(float t); + INLINE float get_t() const; + INLINE bool get_respect_prev_transform() const; INLINE void set_surface_point(const LPoint3f &point); @@ -108,6 +111,7 @@ private: NodePath _from_node_path; NodePath _into_node_path; CPT(ClipPlaneAttrib) _into_clip_planes; + float _t; enum Flags { F_has_surface_point = 0x0001, @@ -141,6 +145,7 @@ private: static TypeHandle _type_handle; friend class CollisionTraverser; + friend class CollisionHandlerFluidPusher; }; INLINE ostream &operator << (ostream &out, const CollisionEntry &entry); diff --git a/panda/src/collide/collisionHandler.I b/panda/src/collide/collisionHandler.I new file mode 100755 index 0000000000..7d04d43db4 --- /dev/null +++ b/panda/src/collide/collisionHandler.I @@ -0,0 +1,40 @@ +// Filename: collisionHandler.I +// Created by: WDIG (15Aug07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandler::wants_all_potential_collidees +// Access: Private +// Description: Returns true if handler wants to know about all +// solids that are within the collider's bounding +// volume +//////////////////////////////////////////////////////////////////// +INLINE bool CollisionHandler:: +wants_all_potential_collidees() const { + return _wants_all_potential_collidees; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandler::set_root +// Access: Private +// Description: Sets the root of the collision traversal. Only set +// if wants_all_potential_collidees is true +//////////////////////////////////////////////////////////////////// +INLINE void CollisionHandler:: +set_root(const NodePath &root) { + _root = &root; +} diff --git a/panda/src/collide/collisionHandler.cxx b/panda/src/collide/collisionHandler.cxx index 44bdc00d0e..6f6dead321 100644 --- a/panda/src/collide/collisionHandler.cxx +++ b/panda/src/collide/collisionHandler.cxx @@ -20,6 +20,16 @@ TypeHandle CollisionHandler::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandler::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +CollisionHandler:: +CollisionHandler() { + _wants_all_potential_collidees = false; +} + //////////////////////////////////////////////////////////////////// // Function: CollisionHandler::begin_group // Access: Public, Virtual diff --git a/panda/src/collide/collisionHandler.h b/panda/src/collide/collisionHandler.h index 6d62cfe23c..5523d34430 100644 --- a/panda/src/collide/collisionHandler.h +++ b/panda/src/collide/collisionHandler.h @@ -22,6 +22,7 @@ #include "pandabase.h" #include "typedReferenceCount.h" +#include "nodePath.h" class CollisionEntry; @@ -35,10 +36,15 @@ class CollisionEntry; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_COLLIDE CollisionHandler : public TypedReferenceCount { public: + CollisionHandler(); + virtual void begin_group(); virtual void add_entry(CollisionEntry *entry); virtual bool end_group(); + INLINE bool wants_all_potential_collidees() const; + INLINE void set_root(const NodePath &root); + PUBLISHED: static TypeHandle get_class_type() { return _type_handle; @@ -55,12 +61,18 @@ public: } virtual TypeHandle force_init_type() {init_type(); return get_class_type();} +protected: + bool _wants_all_potential_collidees; + const NodePath *_root; + private: static TypeHandle _type_handle; friend class CollisionTraverser; }; +#include "collisionHandler.I" + #endif diff --git a/panda/src/collide/collisionHandlerFluidPusher.cxx b/panda/src/collide/collisionHandlerFluidPusher.cxx index ce20ed3901..47e90dfde6 100755 --- a/panda/src/collide/collisionHandlerFluidPusher.cxx +++ b/panda/src/collide/collisionHandlerFluidPusher.cxx @@ -102,13 +102,13 @@ handle_entries() { 7. go to 2 */ bool okflag = true; - + if (!_horizontal) { collide_cat.error() << "collisionHandlerFluidPusher::handle_entries is only supported in " "horizontal mode" << endl; nassertr(false, false); } - + // for every fluid mover being pushed... FromEntries::iterator fei; for (fei = _from_entries.begin(); fei != _from_entries.end(); ++fei) { @@ -129,17 +129,30 @@ handle_entries() { ColliderDef &def = (*ci).second; // extract the collision entries into a vector that we can safely modify - Entries SCS(*entries); + Entries entries(*entries); + Entries next_entries; + + // extract out the initial set of collision solids + CollisionSolids SCS; + + Entries::iterator ei; + for (ei = entries.begin(); ei != entries.end(); ++ei) { + SCS.push_back((*ei)->get_into()); + } // currently we only support spheres as the collider const CollisionSphere *sphere; - DCAST_INTO_R(sphere, (*SCS.front()).get_from(), 0); + DCAST_INTO_R(sphere, (*entries.front()).get_from(), 0); // use a slightly larger radius value so that when we move along // collision planes we don't re-collide float sphere_radius = sphere->get_radius() * 1.001; + // make a copy of the original from_nodepath that we can mess with + // in the process of calculating the final position + _from_node_path_copy = from_node_path.copy_to(from_node_path.get_parent()); + LPoint3f N(from_node_path.get_pos_delta(*_root)); - const LPoint3f orig_pos(from_node_path.get_pos()); + const LPoint3f orig_pos(_from_node_path_copy.get_pos()); // this will hold the final calculated position LPoint3f PosX(orig_pos); @@ -157,20 +170,17 @@ handle_entries() { // if both of these become true, we're stuck in a 'corner' bool left_halfspace_obstructed = false; bool right_halfspace_obstructed = false; - LVector3f left_plane_normal; - LVector3f right_plane_normal; float left_plane_dot = 200.0f; float right_plane_dot = 200.0f; // iterate until the mover runs out of movement or gets stuck while (true) { CollisionEntry *C = 0; - Entries::iterator ei; // find the first (earliest) collision - for (ei = SCS.begin(); ei != SCS.end(); ++ei) { + for (ei = entries.begin(); ei != entries.end(); ++ei) { CollisionEntry *entry = (*ei); nassertr(entry != (CollisionEntry *)NULL, false); - if (entry->get_t() < C->get_t()) { + if ((C == 0) || (entry->get_t() < C->get_t())) { nassertr(from_node_path == entry->get_from_node_path(), false); C = entry; break; @@ -186,12 +196,12 @@ handle_entries() { nassertr(C->has_surface_point(), true); nassertr(C->has_surface_normal(), true); nassertr(C->has_interior_point(), true); - LVector3f surface_normal = C->get_surface_normal(from_node_path); + LVector3f surface_normal = C->get_surface_normal(_from_node_path_copy); if (_horizontal) { surface_normal[2] = 0.0f; } surface_normal.normalize(); - PosX = C->get_surface_point(from_node_path) + (sphere_radius * surface_normal); + PosX = C->get_surface_point(_from_node_path_copy) + (sphere_radius * surface_normal); // check to see if we're stuck, given this collision float dot = right_unit.dot(surface_normal); @@ -204,7 +214,6 @@ handle_entries() { break; } left_halfspace_obstructed = true; - left_plane_normal = surface_normal; } } else { // negative dot means plane is coming from the right (looking along original @@ -216,11 +225,29 @@ handle_entries() { break; } right_halfspace_obstructed = true; - right_plane_normal = surface_normal; } } // set up new current/last positions, re-calculate collisions + CPT(TransformState) prev_trans(_from_node_path_copy.get_prev_transform()); + prev_trans->set_pos(_from_node_path_copy.get_pos()); + _from_node_path_copy.set_prev_transform(prev_trans); + _from_node_path_copy.set_pos(PosX); + + // calculate new collisions given new movement vector + CollisionEntry new_entry; + new_entry._from_node_path = _from_node_path_copy; + new_entry._from = sphere; + next_entries.clear(); + CollisionSolids::iterator csi; + for (csi = SCS.begin(); csi != SCS.end(); ++csi) { + PT(CollisionEntry) result = (*csi)->test_intersection_from_sphere(new_entry); + if (result != (CollisionEntry *)NULL) { + next_entries.push_back(result); + } + } + // swap in the new set of collision events + entries.swap(next_entries); } LVector3f net_shove(PosX - orig_pos); diff --git a/panda/src/collide/collisionHandlerFluidPusher.h b/panda/src/collide/collisionHandlerFluidPusher.h index 37111070ad..d7b18df8d4 100755 --- a/panda/src/collide/collisionHandlerFluidPusher.h +++ b/panda/src/collide/collisionHandlerFluidPusher.h @@ -21,6 +21,7 @@ #include "pandabase.h" +#include "collisionSolid.h" #include "collisionHandlerPusher.h" //////////////////////////////////////////////////////////////////// @@ -37,8 +38,12 @@ public: virtual void add_entry(CollisionEntry *entry); protected: + typedef pvector< CPT(CollisionSolid) > CollisionSolids; + virtual bool handle_entries(); + NodePath _from_node_path_copy; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/collide/collisionHandlerPusher.h b/panda/src/collide/collisionHandlerPusher.h index 11761de1c1..fa31fef26e 100644 --- a/panda/src/collide/collisionHandlerPusher.h +++ b/panda/src/collide/collisionHandlerPusher.h @@ -45,7 +45,6 @@ protected: const LVector3f &force_normal); virtual void apply_linear_force(ColliderDef &def, const LVector3f &force); -private: bool _horizontal; diff --git a/panda/src/collide/collisionInvSphere.cxx b/panda/src/collide/collisionInvSphere.cxx index de4960790f..5936c4797c 100644 --- a/panda/src/collide/collisionInvSphere.cxx +++ b/panda/src/collide/collisionInvSphere.cxx @@ -147,7 +147,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { // is as good as any other. surface_normal.set(1.0, 0.0, 0.0); } else { - surface_normal = -vec / vec_length; + surface_normal = vec / -vec_length; } LVector3f normal = (has_effective_normal() && sphere->get_respect_effective_normal()) ? get_effective_normal() : surface_normal; diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index 00438e4500..503d61fd99 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -414,6 +414,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { LPoint3f orig_center = sphere->get_center() * wrt_mat; LPoint3f from_center = orig_center; bool moved_from_center = false; + float t = 1.0f; if (wrt_prev_space != wrt_space) { // If we have a delta between the previous position and the @@ -439,13 +440,15 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { // at the point along its path that is closest to intersecting // the plane. This may be the actual intersection point, or it // may be the starting point or the final point. - float t = -(dist_to_plane(a) / dot); + t = -(dist_to_plane(a) / dot); if (t >= 1.0f) { // Leave it where it is. + t = 1.0f; } else if (t < 0.0f) { from_center = a; moved_from_center = true; + t = 0.0f; } else { from_center = a + t * delta; @@ -556,6 +559,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { new_entry->set_surface_normal(normal); new_entry->set_surface_point(from_center - normal * dist); new_entry->set_interior_point(from_center - normal * (dist + into_depth)); + new_entry->set_t(t); return new_entry; } diff --git a/panda/src/collide/collisionSolid.h b/panda/src/collide/collisionSolid.h index 325e8735c2..d1006d402b 100644 --- a/panda/src/collide/collisionSolid.h +++ b/panda/src/collide/collisionSolid.h @@ -178,6 +178,7 @@ private: friend class CollisionLine; friend class CollisionRay; friend class CollisionSegment; + friend class CollisionHandlerFluidPusher; }; INLINE ostream &operator << (ostream &out, const CollisionSolid &cs) { diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 3ebf5d0dcb..a417d5050a 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -288,6 +288,7 @@ traverse(const NodePath &root) { Handlers::iterator hi; for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) { + (*hi).first->set_root(root); (*hi).first->begin_group(); } diff --git a/panda/src/collide/collisionTube.cxx b/panda/src/collide/collisionTube.cxx index ee7a29de07..059733c746 100644 --- a/panda/src/collide/collisionTube.cxx +++ b/panda/src/collide/collisionTube.cxx @@ -213,6 +213,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { into_intersection_point = from_a + t1 * from_direction; } set_intersection_point(new_entry, into_intersection_point, from_radius); + new_entry->set_t(t1); return new_entry; }