2
0
Эх сурвалжийг харах

added collsionHandlerGravity

Dave Schuyler 22 жил өмнө
parent
commit
50d377f8f0

+ 3 - 0
panda/src/collide/Sources.pp

@@ -14,6 +14,7 @@
     collisionHandler.h  \
     collisionHandlerEvent.I collisionHandlerEvent.h  \
     collisionHandlerFloor.I collisionHandlerFloor.h  \
+    collisionHandlerGravity.I collisionHandlerGravity.h  \
     collisionHandlerPhysical.I collisionHandlerPhysical.h  \
     collisionHandlerPusher.I collisionHandlerPusher.h  \
     collisionHandlerQueue.h \
@@ -36,6 +37,7 @@
     collisionHandler.cxx \
     collisionHandlerEvent.cxx  \
     collisionHandlerFloor.cxx \
+    collisionHandlerGravity.cxx \
     collisionHandlerPhysical.cxx  \
     collisionHandlerPusher.cxx \
     collisionHandlerQueue.cxx  \
@@ -57,6 +59,7 @@
     collisionHandler.h \
     collisionHandlerEvent.I collisionHandlerEvent.h \
     collisionHandlerFloor.I collisionHandlerFloor.h \
+    collisionHandlerGravity.I collisionHandlerGravity.h \
     collisionHandlerPhysical.I collisionHandlerPhysical.h \
     collisionHandlerPusher.I collisionHandlerPusher.h \
     collisionHandlerQueue.h \

+ 1 - 0
panda/src/collide/collide_composite1.cxx

@@ -3,6 +3,7 @@
 #include "collisionHandler.cxx"
 #include "collisionHandlerEvent.cxx"
 #include "collisionHandlerFloor.cxx"
+#include "collisionHandlerGravity.cxx"
 #include "collisionHandlerPhysical.cxx"
 #include "collisionHandlerPusher.cxx"
 #include "collisionHandlerQueue.cxx"

+ 0 - 1
panda/src/collide/collisionHandlerFloor.cxx

@@ -124,7 +124,6 @@ handle_entries() {
           def.updated_transform();
 
           apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust));
-
         } else {
           if (collide_cat.is_spam()) {
             collide_cat.spam()

+ 157 - 0
panda/src/collide/collisionHandlerGravity.I

@@ -0,0 +1,157 @@
+// Filename: CollisionHandlerGravity.I
+// Created by:  drose (16Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::set_offset
+//       Access: Public
+//  Description: Sets the linear offset to add to (or subtract from)
+//               the highest detected collision point to determine the
+//               actual height at which to set the collider.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerGravity::
+set_offset(float offset) {
+  _offset = offset;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::get_offset
+//       Access: Public
+//  Description: Returns the linear offset to add to (or subtract from)
+//               the highest detected collision point to determine the
+//               actual height at which to set the collider.
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionHandlerGravity::
+get_offset() const {
+  return _offset;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::get_airborne_height
+//       Access: Public
+//  Description: Return the height of the object from the ground.
+//
+//               The object might not necessarily be at rest.  Use
+//               is_on_ground() if you want to know whether the
+//               object is on the ground and at rest.
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionHandlerGravity::
+get_airborne_height() const {
+  return _airborne_height;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::is_on_ground
+//       Access: Public
+//  Description: Is the object at rest?
+////////////////////////////////////////////////////////////////////
+INLINE bool CollisionHandlerGravity::
+is_on_ground() const {
+  // Testing for 0.0f here is not as foolhardy as it may appear.  The
+  // handle_entries() function will set these values to 0.0f if they
+  // are within a threshold.
+  return get_airborne_height() == 0.0f && _current_velocity == 0.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::add_velocity
+//       Access: Public
+//  Description: Adds the sepcified amount to the current velocity.
+//               This is mostly here allow this common operation to
+//               be faster for scripting, but it's also more concise
+//               even in cpp.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerGravity::
+add_velocity(float velocity) {
+  _current_velocity += velocity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::set_velocity
+//       Access: Public
+//  Description: Sets the current vertical velocity.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerGravity::
+set_velocity(float velocity) {
+  _current_velocity = velocity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::get_velocity
+//       Access: Public
+//  Description: Gets the current vertical velocity.
+//
+//               Generally, negative values mean the object is in
+//               free fall; while postive values mean the object has
+//               vertical thrust.
+//
+//               A zero value does not necessarily mean the object
+//               on the ground, it may also be weightless and/or at
+//               the apex of its jump.
+//
+//               See Also: is_on_ground() and get_gravity()
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionHandlerGravity::
+get_velocity() const {
+  return _current_velocity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::set_gravity
+//       Access: Public
+//  Description: Sets the linear gravity force (always plumb).
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerGravity::
+set_gravity(float gravity) {
+  _gravity = gravity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::get_gravity
+//       Access: Public
+//  Description: Gets the linear gravity force (always plumb).
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionHandlerGravity::
+get_gravity() const {
+  return _gravity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::set_max_velocity
+//       Access: Public
+//  Description: Sets the maximum speed at which the object will be
+//               allowed to descend towards a floor below it, in units
+//               per second.  Set this to zero to allow it to
+//               instantly teleport any distance.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerGravity::
+set_max_velocity(float max_velocity) {
+  _max_velocity = max_velocity;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::get_max_velocity
+//       Access: Public
+//  Description: Retrieves the maximum speed at which the object will
+//               be allowed to descend towards a floor below it, in
+//               units per second.  See set_max_velocity().
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionHandlerGravity::
+get_max_velocity() const {
+  return _max_velocity;
+}

+ 175 - 0
panda/src/collide/collisionHandlerGravity.cxx

@@ -0,0 +1,175 @@
+// Filename: CollisionHandlerGravity.cxx
+// Created by:  drose (16Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "CollisionHandlerGravity.h"
+#include "collisionNode.h"
+#include "collisionEntry.h"
+#include "config_collide.h"
+
+#include "clockObject.h"
+
+TypeHandle CollisionHandlerGravity::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CollisionHandlerGravity::
+CollisionHandlerGravity() {
+  _offset = 0.0f;
+  _airborne_height = 0.0f;
+  _gravity = 32.174f;
+  _current_velocity = 0.0f;
+  _max_velocity = 400.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CollisionHandlerGravity::
+~CollisionHandlerGravity() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::handle_entries
+//       Access: Protected, Virtual
+//  Description: Called by the parent class after all collisions have
+//               been detected, this manages the various collisions
+//               and moves around the nodes as necessary.
+//
+//               The return value is normally true, but it may be
+//               false to indicate the CollisionTraverser should
+//               disable this handler from being called in the future.
+////////////////////////////////////////////////////////////////////
+bool CollisionHandlerGravity::
+handle_entries() {
+  bool okflag = true;
+
+  FromEntries::const_iterator fi;
+  for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) {
+    const NodePath &from_node_path = (*fi).first;
+    const Entries &entries = (*fi).second;
+
+    Colliders::iterator ci;
+    ci = _colliders.find(from_node_path);
+    if (ci == _colliders.end()) {
+      // Hmm, someone added a CollisionNode to a traverser and gave
+      // it this CollisionHandler pointer--but they didn't tell us
+      // about the node.
+      collide_cat.error()
+        << get_type() << " doesn't know about "
+        << from_node_path << ", disabling.\n";
+      okflag = false;
+    } else {
+      ColliderDef &def = (*ci).second;
+      {
+        // Get the maximum height for all collisions with this node.
+        bool got_max = false;
+        float max_height = 0.0f;
+        
+        Entries::const_iterator ei;
+        for (ei = entries.begin(); ei != entries.end(); ++ei) {
+          CollisionEntry *entry = (*ei);
+          nassertr(entry != (CollisionEntry *)NULL, false);
+          nassertr(from_node_path == entry->get_from_node_path(), false);
+          
+          if (entry->has_surface_point()) {
+            LPoint3f point = entry->get_surface_point(def._target);
+            if (collide_cat.is_debug()) {
+              collide_cat.debug()
+                << "Intersection point detected at " << point << "\n";
+            }
+            
+            float height = point[2];
+            if (!got_max || height > max_height) {
+              got_max = true;
+              max_height = height;
+            }
+          }
+        }
+        
+        // Now set our height accordingly.
+        float adjust = max_height + _offset;
+        if (_current_velocity > 0.0f || !IS_THRESHOLD_ZERO(adjust, 0.001)) {
+          if (collide_cat.is_debug()) {
+            collide_cat.debug()
+              << "Adjusting height by " << adjust << "\n";
+          }
+          
+          if (_current_velocity > 0.0f || adjust < -0.001f) {
+            // ...we have a vertical thrust,
+            // ...or the node is above the floor, so it is airborne.
+            float dt = min(ClockObject::get_global_clock()->get_dt(), 0.1f);
+            // The sign in this equation is reversed from normal.  This is
+            // because _current_velocity is a scaler and the equation normally
+            // has a vector.  I suppose the sign of _gravity could have been
+            // reversed, but I think it makes the get_*() set_*()
+            // more intuitive to do it this way.
+            float gravity_adjust = _current_velocity * dt - 0.5 * _gravity * dt * dt;
+            if (adjust > 0.0f) {
+              // ...the node is under the floor, so it has landed.
+              // Keep the adjust to bring us up to the ground and
+              // then add the gravity_adjust to get us airborne:
+              adjust += max(0.0f, gravity_adjust);
+            } else {
+              // ...the node is above the floor, so it is airborne.
+              adjust = max(adjust, gravity_adjust);
+            }
+            _current_velocity -= _gravity * dt;
+            // Record the airborne height in case someone else needs it: 
+            _airborne_height = -max_height + adjust;
+          }
+          
+          if (_airborne_height < 0.001f && _current_velocity < 0.001f) {
+            // ...the node is under the floor, so it has landed.
+            // These values are used by is_on_ground().
+            _current_velocity = _airborne_height = 0.0f;
+          }
+
+          CPT(TransformState) trans = def._target.get_transform();
+          LVecBase3f pos = trans->get_pos();
+          pos[2] += adjust;
+          def._target.set_transform(trans->set_pos(pos));
+          def.updated_transform();
+
+          apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust));
+        } else {
+          _current_velocity = _airborne_height = 0.0f;
+          if (collide_cat.is_spam()) {
+            collide_cat.spam()
+              << "Leaving height unchanged.\n";
+          }
+        }
+      }
+    }
+  }
+
+  return okflag;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerGravity::apply_linear_force
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CollisionHandlerGravity::
+apply_linear_force(ColliderDef &def, const LVector3f &force) {
+}

+ 91 - 0
panda/src/collide/collisionHandlerGravity.h

@@ -0,0 +1,91 @@
+// Filename: CollisionHandlerGravity.h
+// Created by:  drose (16Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CollisionHandlerGravity_H
+#define CollisionHandlerGravity_H
+
+#include "pandabase.h"
+
+#include "collisionHandlerPhysical.h"
+
+///////////////////////////////////////////////////////////////////
+//       Class : CollisionHandlerGravity
+// Description : A specialized kind of CollisionHandler that sets the
+//               Z height of the collider to a fixed linear offset
+//               from the highest detected collision point each frame.
+//               It's intended to implement walking around on a floor
+//               of varying height by casting a ray down from the
+//               avatar's head.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA CollisionHandlerGravity : public CollisionHandlerPhysical {
+PUBLISHED:
+  CollisionHandlerGravity();
+  virtual ~CollisionHandlerGravity();
+
+  INLINE void set_offset(float offset);
+  INLINE float get_offset() const;
+
+  INLINE float get_airborne_height() const;
+  INLINE bool is_on_ground() const;
+
+  INLINE void add_velocity(float velocity);
+  INLINE void set_velocity(float velocity);
+  INLINE float get_velocity() const;
+
+  INLINE void set_gravity(float gravity);
+  INLINE float get_gravity() const;
+
+  INLINE void set_max_velocity(float max_vel);
+  INLINE float get_max_velocity() const;
+
+protected:
+  virtual bool handle_entries();
+  virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
+
+private:
+  float _offset;
+  float _airborne_height;
+  float _gravity;
+  float _current_velocity;
+  float _max_velocity;
+
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    CollisionHandlerPhysical::init_type();
+    register_type(_type_handle, "CollisionHandlerGravity",
+                  CollisionHandlerPhysical::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "CollisionHandlerGravity.I"
+
+#endif
+
+
+