diff --git a/panda/src/collide/Sources.pp b/panda/src/collide/Sources.pp index b9b76c603b..d3089dbb78 100644 --- a/panda/src/collide/Sources.pp +++ b/panda/src/collide/Sources.pp @@ -14,6 +14,7 @@ collisionGeom.I collisionGeom.h \ collisionHandler.I collisionHandler.h \ collisionHandlerEvent.I collisionHandlerEvent.h \ + collisionHandlerHighestEvent.h \ collisionHandlerFloor.I collisionHandlerFloor.h \ collisionHandlerGravity.I collisionHandlerGravity.h \ collisionHandlerPhysical.I collisionHandlerPhysical.h \ @@ -46,6 +47,7 @@ collisionGeom.cxx \ collisionHandler.cxx \ collisionHandlerEvent.cxx \ + collisionHandlerHighestEvent.cxx \ collisionHandlerFloor.cxx \ collisionHandlerGravity.cxx \ collisionHandlerPhysical.cxx \ @@ -78,6 +80,7 @@ collisionGeom.I collisionGeom.h \ collisionHandler.I collisionHandler.h \ collisionHandlerEvent.I collisionHandlerEvent.h \ + collisionHandlerHighestEvent.h \ collisionHandlerFloor.I collisionHandlerFloor.h \ collisionHandlerGravity.I collisionHandlerGravity.h \ collisionHandlerPhysical.I collisionHandlerPhysical.h \ diff --git a/panda/src/collide/collide_composite1.cxx b/panda/src/collide/collide_composite1.cxx index 47ee731d69..94ced0b778 100644 --- a/panda/src/collide/collide_composite1.cxx +++ b/panda/src/collide/collide_composite1.cxx @@ -3,6 +3,7 @@ #include "collisionGeom.cxx" #include "collisionHandler.cxx" #include "collisionHandlerEvent.cxx" +#include "collisionHandlerHighestEvent.cxx" #include "collisionHandlerFloor.cxx" #include "collisionHandlerGravity.cxx" #include "collisionHandlerPhysical.cxx" diff --git a/panda/src/collide/collisionHandlerGravity.cxx b/panda/src/collide/collisionHandlerGravity.cxx index d70bce0863..037c6661a9 100755 --- a/panda/src/collide/collisionHandlerGravity.cxx +++ b/panda/src/collide/collisionHandlerGravity.cxx @@ -66,7 +66,7 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod bool got_max = false; float max_height = 0.0f; CollisionEntry *highest = NULL; - + Entries::const_iterator ei; for (ei = entries.begin(); ei != entries.end(); ++ei) { CollisionEntry *entry = (*ei); @@ -123,6 +123,8 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod CollisionEntry *highest = NULL; CollisionEntry *lowest = NULL; + pvector valid_entries; + Entries::const_iterator ei; for (ei = entries.begin(); ei != entries.end(); ++ei) { CollisionEntry *entry = (*ei); @@ -135,13 +137,14 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod 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(height < _offset + _reach) { + valid_entries.push_back(entry); + if (!got_max || height > max_height) { + got_max = true; + max_height = height; + highest = entry; + } } if (!got_min || height < min_height) { got_min = true; @@ -157,6 +160,7 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod got_max = true; max_height = min_height; highest = lowest; + valid_entries.push_back(lowest); } //#*#_has_contact = got_max; @@ -172,9 +176,10 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod // We only collide with things we are impacting with. // Remove the collisions: - //_current_colliding.clear(); + _current_colliding.clear(); // Add only the one that we're impacting with: - //add_entry(highest); + _current_colliding.insert(valid_entries.begin(), valid_entries.end()); + // Set the contact normal so that other code can make use of the // surface slope: diff --git a/panda/src/collide/collisionHandlerHighestEvent.cxx b/panda/src/collide/collisionHandlerHighestEvent.cxx new file mode 100755 index 0000000000..52797c425b --- /dev/null +++ b/panda/src/collide/collisionHandlerHighestEvent.cxx @@ -0,0 +1,90 @@ +// Filename: collisionHandlerEvent.cxx +// Created by: drose (16Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +#include "collisionHandlerHighestEvent.h" +#include "config_collide.h" + +#include "eventParameter.h" +#include "throw_event.h" + + +TypeHandle CollisionHandlerHighestEvent::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandlerEvent::Constructor +// Access: Public +// Description: The default CollisionHandlerEvent will throw no +// events. Its pattern strings must first be set via a +// call to add_in_pattern() and/or add_out_pattern(). +//////////////////////////////////////////////////////////////////// +CollisionHandlerHighestEvent:: +CollisionHandlerHighestEvent() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandlerEvent::begin_group +// Access: Public, Virtual +// Description: Will be called by the CollisionTraverser before a new +// traversal is begun. It instructs the handler to +// reset itself in preparation for a number of +// CollisionEntries to be sent. +//////////////////////////////////////////////////////////////////// +void CollisionHandlerHighestEvent:: +begin_group() { + if (collide_cat.is_spam()) { + collide_cat.spam() + << "begin_group.\n"; + } + _last_colliding.clear(); + if(_closest_collider) + bool inserted = _last_colliding.insert(_closest_collider).second; + _current_colliding.clear(); + _collider_distance = 10000000000; + _closest_collider = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandlerEvent::add_entry +// Access: Public, Virtual +// Description: Called between a begin_group() .. end_group() +// sequence for each collision that is detected. +//////////////////////////////////////////////////////////////////// +void CollisionHandlerHighestEvent:: +add_entry(CollisionEntry *entry) { + nassertv(entry != (CollisionEntry *)NULL); + LVector3f vec = + entry->get_surface_point(entry->get_from_node_path()) - + entry->get_from()->get_collision_origin(); + double dist = vec.length_squared(); + if(dist < _collider_distance) { + _collider_distance = dist; + _closest_collider = entry; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandlerPhysical::end_group +// Access: Public, Virtual +// Description: Called by the CollisionTraverser at the completion of +// all collision detections for this traversal. It +// should do whatever finalization is required for the +// handler. +//////////////////////////////////////////////////////////////////// +bool CollisionHandlerHighestEvent:: +end_group() { + if(_closest_collider) + bool inserted = _current_colliding.insert(_closest_collider).second; + return CollisionHandlerEvent::end_group(); +} diff --git a/panda/src/collide/collisionHandlerHighestEvent.h b/panda/src/collide/collisionHandlerHighestEvent.h new file mode 100755 index 0000000000..f655e4a8b5 --- /dev/null +++ b/panda/src/collide/collisionHandlerHighestEvent.h @@ -0,0 +1,70 @@ +// Filename: collisionHandlerEvent.h +// Created by: drose (16Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef COLLISIONHANDLERHIGHESTEVENT_H +#define COLLISIONHANDLERHIGHESTEVENT_H + +#include "pandabase.h" + +#include "collisionHandlerEvent.h" +#include "collisionNode.h" +#include "collisionEntry.h" + +#include "vector_string.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : CollisionHandlerEvent +// Description : A specialized kind of CollisionHandler that throws an +// event for each collision detected. The event thrown +// may be based on the name of the moving object or the +// struck object, or both. The first parameter of the +// event will be a pointer to the CollisionEntry that +// triggered it. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_COLLIDE CollisionHandlerHighestEvent : public CollisionHandlerEvent { +PUBLISHED: + CollisionHandlerHighestEvent(); + +public: + virtual void begin_group(); + virtual void add_entry(CollisionEntry *entry); + virtual bool end_group(); +private: + double _collider_distance; + PT(CollisionEntry) _closest_collider; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + CollisionHandler::init_type(); + register_type(_type_handle, "CollisionHandlerHighestEvent", + CollisionHandler::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; +}; + +#endif + + + diff --git a/panda/src/collide/config_collide.cxx b/panda/src/collide/config_collide.cxx index f49d2e2c79..53f444efd0 100644 --- a/panda/src/collide/config_collide.cxx +++ b/panda/src/collide/config_collide.cxx @@ -16,6 +16,7 @@ #include "collisionEntry.h" #include "collisionHandler.h" #include "collisionHandlerEvent.h" +#include "collisionHandlerHighestEvent.h" #include "collisionHandlerFloor.h" #include "collisionHandlerGravity.h" #include "collisionHandlerPhysical.h" @@ -121,6 +122,7 @@ init_libcollide() { CollisionEntry::init_type(); CollisionHandler::init_type(); CollisionHandlerEvent::init_type(); + CollisionHandlerHighestEvent::init_type(); CollisionHandlerFloor::init_type(); CollisionHandlerGravity::init_type(); CollisionHandlerPhysical::init_type();