open_toontown_panda3d/panda/src/collide/collisionHandlerFloor.cxx

249 lines
8.2 KiB
C++

// Filename: collisionHandlerFloor.cxx
// Created by: drose (16Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
#include "collisionHandlerFloor.h"
#include "collisionNode.h"
#include "collisionEntry.h"
#include "config_collide.h"
#include "clockObject.h"
TypeHandle CollisionHandlerFloor::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerFloor::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CollisionHandlerFloor::
CollisionHandlerFloor() {
_offset = 0.0f;
_reach = 1.0f;
_max_velocity = 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerFloor::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CollisionHandlerFloor::
~CollisionHandlerFloor() {
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerGravity::set_highest_collision
// Access: Protected
// Description:
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////
float CollisionHandlerFloor::
set_highest_collision(const NodePath &target_node_path, const NodePath &from_node_path, const Entries &entries) {
// Get the maximum height for all collisions with this node.
// This is really the distance to-the-ground, so it will
// be negative when the avatar is above the ground.
// Larger values (less negative) are higher elevation (assuming
// the avatar is right-side-up (or the ray is plumb)).
bool got_max = false;
bool got_min = false;
float max_height = 0.0f;
float min_height = 0.0f;
CollisionEntry *highest = NULL;
CollisionEntry *lowest = NULL;
Entries::const_iterator ei;
for (ei = entries.begin(); ei != entries.end(); ++ei) {
CollisionEntry *entry = (*ei);
nassertr(entry != (CollisionEntry *)NULL, 0.0f);
nassertr(from_node_path == entry->get_from_node_path(), 0.0f);
if (entry->has_surface_point()) {
LPoint3f point = entry->get_surface_point(target_node_path);
if (collide_cat.is_debug()) {
collide_cat.debug()
<< "Intersection point detected at " << point << "\n";
}
float height = point[2];
if (height < _offset + _reach &&
(!got_max || height > max_height)) {
got_max = true;
max_height = height;
highest = entry;
}
if (!got_min || height < min_height) {
got_min = true;
min_height = height;
lowest = entry;
}
}
}
if (!got_max && got_min) {
// We've fallen through the world, but we're also under some walkable
// geometry.
// Move us up to the lowest surface:
got_max = true;
max_height = min_height;
highest = lowest;
}
//#*#_has_contact = got_max;
#if 0
cout<<"\ncolliding with:\n";
for (Colliding::const_iterator i = _current_colliding.begin(); i != _current_colliding.end(); ++i) {
(**i).write(cout, 2);
}
cout<<"\nhighest:\n";
highest->write(cout, 2);
cout<<endl;
#endif
#if 1
// We only collide with things we are impacting with.
// Remove the collisions:
_current_colliding.clear();
// Add only the one that we're impacting with:
add_entry(highest);
#endif
return max_height;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerFloor::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 CollisionHandlerFloor::
handle_entries() {
bool okflag = true;
// Reset the set of things our parent class CollisionHandlerEvent
// recorded a collision with. We'll only consider ourselves
// collided with the topmost object for each from_entry.
_current_colliding.clear();
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;
{
#if 0
// Get the maximum height for all collisions with this node.
bool got_max = false;
float max_height = 0.0f;
CollisionEntry *max_entry = NULL;
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;
max_entry = entry;
}
}
}
// Record a collision with the topmost element for the
// CollisionHandlerEvent base class.
_current_colliding.insert(max_entry);
// Now set our height accordingly.
float adjust = max_height + _offset;
#else
float max_height = set_highest_collision(def._target, from_node_path, entries);
// Now set our height accordingly.
float adjust = max_height + _offset;
#endif
if (!IS_THRESHOLD_ZERO(adjust, 0.001)) {
if (collide_cat.is_debug()) {
collide_cat.debug()
<< "Adjusting height by " << adjust << "\n";
}
if (adjust < 0.0f && _max_velocity != 0.0f) {
float max_adjust =
_max_velocity * ClockObject::get_global_clock()->get_dt();
adjust = max(adjust, -max_adjust);
}
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 {
if (collide_cat.is_spam()) {
collide_cat.spam()
<< "Leaving height unchanged.\n";
}
}
}
}
}
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandlerFloor::apply_linear_force
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CollisionHandlerFloor::
apply_linear_force(ColliderDef &def, const LVector3f &force) {
}