added collsionHandlerGravity

This commit is contained in:
Dave Schuyler 2003-12-09 02:18:53 +00:00
parent d8f3a308ac
commit 50d377f8f0
6 changed files with 427 additions and 1 deletions

View File

@ -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 \

View File

@ -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"

View File

@ -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()

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// 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;
}

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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) {
}

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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