瀏覽代碼

some more collision work. A new handler that only passes along the highest entry, as well as a small tweak to the collision gravity handler to ensure that only entries within the ray's bounds are sent

Zachary Pavlov 16 年之前
父節點
當前提交
0c4b08731a

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

@@ -14,6 +14,7 @@
     collisionGeom.I collisionGeom.h \
     collisionGeom.I collisionGeom.h \
     collisionHandler.I collisionHandler.h  \
     collisionHandler.I collisionHandler.h  \
     collisionHandlerEvent.I collisionHandlerEvent.h  \
     collisionHandlerEvent.I collisionHandlerEvent.h  \
+    collisionHandlerHighestEvent.h  \
     collisionHandlerFloor.I collisionHandlerFloor.h  \
     collisionHandlerFloor.I collisionHandlerFloor.h  \
     collisionHandlerGravity.I collisionHandlerGravity.h  \
     collisionHandlerGravity.I collisionHandlerGravity.h  \
     collisionHandlerPhysical.I collisionHandlerPhysical.h  \
     collisionHandlerPhysical.I collisionHandlerPhysical.h  \
@@ -46,6 +47,7 @@
     collisionGeom.cxx \
     collisionGeom.cxx \
     collisionHandler.cxx \
     collisionHandler.cxx \
     collisionHandlerEvent.cxx  \
     collisionHandlerEvent.cxx  \
+    collisionHandlerHighestEvent.cxx  \
     collisionHandlerFloor.cxx \
     collisionHandlerFloor.cxx \
     collisionHandlerGravity.cxx \
     collisionHandlerGravity.cxx \
     collisionHandlerPhysical.cxx  \
     collisionHandlerPhysical.cxx  \
@@ -78,6 +80,7 @@
     collisionGeom.I collisionGeom.h \
     collisionGeom.I collisionGeom.h \
     collisionHandler.I collisionHandler.h \
     collisionHandler.I collisionHandler.h \
     collisionHandlerEvent.I collisionHandlerEvent.h \
     collisionHandlerEvent.I collisionHandlerEvent.h \
+    collisionHandlerHighestEvent.h \
     collisionHandlerFloor.I collisionHandlerFloor.h \
     collisionHandlerFloor.I collisionHandlerFloor.h \
     collisionHandlerGravity.I collisionHandlerGravity.h \
     collisionHandlerGravity.I collisionHandlerGravity.h \
     collisionHandlerPhysical.I collisionHandlerPhysical.h \
     collisionHandlerPhysical.I collisionHandlerPhysical.h \

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

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

+ 14 - 9
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;
   bool got_max = false;
   float max_height = 0.0f;
   float max_height = 0.0f;
   CollisionEntry *highest = NULL;
   CollisionEntry *highest = NULL;
-
+  
   Entries::const_iterator ei;
   Entries::const_iterator ei;
   for (ei = entries.begin(); ei != entries.end(); ++ei) {
   for (ei = entries.begin(); ei != entries.end(); ++ei) {
     CollisionEntry *entry = (*ei);
     CollisionEntry *entry = (*ei);
@@ -123,6 +123,8 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod
   CollisionEntry *highest = NULL;
   CollisionEntry *highest = NULL;
   CollisionEntry *lowest = NULL;
   CollisionEntry *lowest = NULL;
 
 
+  pvector<PT(CollisionEntry)> valid_entries;
+
   Entries::const_iterator ei;
   Entries::const_iterator ei;
   for (ei = entries.begin(); ei != entries.end(); ++ei) {
   for (ei = entries.begin(); ei != entries.end(); ++ei) {
     CollisionEntry *entry = (*ei);
     CollisionEntry *entry = (*ei);
@@ -135,13 +137,14 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod
         collide_cat.debug()
         collide_cat.debug()
           << "Intersection point detected at " << point << "\n";
           << "Intersection point detected at " << point << "\n";
       }
       }
-
       float height = point[2];
       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) {
       if (!got_min || height < min_height) {
         got_min = true;
         got_min = true;
@@ -157,6 +160,7 @@ set_highest_collision(const NodePath &target_node_path, const NodePath &from_nod
     got_max = true;
     got_max = true;
     max_height = min_height;
     max_height = min_height;
     highest = lowest;
     highest = lowest;
+    valid_entries.push_back(lowest);
   }
   }
   //#*#_has_contact = got_max;
   //#*#_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.
   // We only collide with things we are impacting with.
   // Remove the collisions:
   // Remove the collisions:
-  //_current_colliding.clear();
+  _current_colliding.clear();
   // Add only the one that we're impacting with:
   // 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
   // Set the contact normal so that other code can make use of the
   // surface slope:
   // surface slope:

+ 90 - 0
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();
+}

+ 70 - 0
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
+
+
+

+ 2 - 0
panda/src/collide/config_collide.cxx

@@ -16,6 +16,7 @@
 #include "collisionEntry.h"
 #include "collisionEntry.h"
 #include "collisionHandler.h"
 #include "collisionHandler.h"
 #include "collisionHandlerEvent.h"
 #include "collisionHandlerEvent.h"
+#include "collisionHandlerHighestEvent.h"
 #include "collisionHandlerFloor.h"
 #include "collisionHandlerFloor.h"
 #include "collisionHandlerGravity.h"
 #include "collisionHandlerGravity.h"
 #include "collisionHandlerPhysical.h"
 #include "collisionHandlerPhysical.h"
@@ -121,6 +122,7 @@ init_libcollide() {
   CollisionEntry::init_type();
   CollisionEntry::init_type();
   CollisionHandler::init_type();
   CollisionHandler::init_type();
   CollisionHandlerEvent::init_type();
   CollisionHandlerEvent::init_type();
+  CollisionHandlerHighestEvent::init_type();
   CollisionHandlerFloor::init_type();
   CollisionHandlerFloor::init_type();
   CollisionHandlerGravity::init_type();
   CollisionHandlerGravity::init_type();
   CollisionHandlerPhysical::init_type();
   CollisionHandlerPhysical::init_type();