fluid pusher almost working

This commit is contained in:
Darren Ranalli 2007-08-24 19:23:44 +00:00
parent 56a1e82988
commit 519ae6bdac
15 changed files with 148 additions and 17 deletions

View File

@ -7,6 +7,7 @@
#include "collisionHandlerGravity.cxx"
#include "collisionHandlerPhysical.cxx"
#include "collisionHandlerPusher.cxx"
#include "collisionHandlerFluidPusher.cxx"
#include "collisionHandlerQueue.cxx"
#include "collisionDSSolid.cxx"
#include "collisionInvSphere.cxx"

View File

@ -25,6 +25,7 @@
INLINE CollisionEntry::
CollisionEntry() {
_flags = 0;
_t = 1.f;
}
////////////////////////////////////////////////////////////////////
@ -125,6 +126,28 @@ get_into_node_path() const {
return _into_node_path;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_t
// Access: Published
// Description: Sets a time value for this collision relative to
// other CollisionEntries
////////////////////////////////////////////////////////////////////
INLINE void CollisionEntry::
set_t(float t) {
_t = t;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::set_t
// Access: Published
// Description: returns time value for this collision relative to
// other CollisionEntries
////////////////////////////////////////////////////////////////////
INLINE float CollisionEntry::
get_t() const {
return _t;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionEntry::get_respect_prev_transform
// Access: Published

View File

@ -36,6 +36,7 @@ CollisionEntry(const CollisionEntry &copy) :
_from_node_path(copy._from_node_path),
_into_node_path(copy._into_node_path),
_into_clip_planes(copy._into_clip_planes),
_t(copy._t),
_flags(copy._flags),
_surface_point(copy._surface_point),
_surface_normal(copy._surface_normal),
@ -57,6 +58,7 @@ operator = (const CollisionEntry &copy) {
_from_node_path = copy._from_node_path;
_into_node_path = copy._into_node_path;
_into_clip_planes = copy._into_clip_planes;
_t = copy._t;
_flags = copy._flags;
_surface_point = copy._surface_point;
_surface_normal = copy._surface_normal;

View File

@ -63,6 +63,9 @@ PUBLISHED:
INLINE NodePath get_from_node_path() const;
INLINE NodePath get_into_node_path() const;
INLINE void set_t(float t);
INLINE float get_t() const;
INLINE bool get_respect_prev_transform() const;
INLINE void set_surface_point(const LPoint3f &point);
@ -108,6 +111,7 @@ private:
NodePath _from_node_path;
NodePath _into_node_path;
CPT(ClipPlaneAttrib) _into_clip_planes;
float _t;
enum Flags {
F_has_surface_point = 0x0001,
@ -141,6 +145,7 @@ private:
static TypeHandle _type_handle;
friend class CollisionTraverser;
friend class CollisionHandlerFluidPusher;
};
INLINE ostream &operator << (ostream &out, const CollisionEntry &entry);

View File

@ -0,0 +1,40 @@
// Filename: collisionHandler.I
// Created by: WDIG (15Aug07)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CollisionHandler::wants_all_potential_collidees
// Access: Private
// Description: Returns true if handler wants to know about all
// solids that are within the collider's bounding
// volume
////////////////////////////////////////////////////////////////////
INLINE bool CollisionHandler::
wants_all_potential_collidees() const {
return _wants_all_potential_collidees;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandler::set_root
// Access: Private
// Description: Sets the root of the collision traversal. Only set
// if wants_all_potential_collidees is true
////////////////////////////////////////////////////////////////////
INLINE void CollisionHandler::
set_root(const NodePath &root) {
_root = &root;
}

View File

@ -20,6 +20,16 @@
TypeHandle CollisionHandler::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CollisionHandler::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
CollisionHandler::
CollisionHandler() {
_wants_all_potential_collidees = false;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionHandler::begin_group
// Access: Public, Virtual

View File

@ -22,6 +22,7 @@
#include "pandabase.h"
#include "typedReferenceCount.h"
#include "nodePath.h"
class CollisionEntry;
@ -35,10 +36,15 @@ class CollisionEntry;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_COLLIDE CollisionHandler : public TypedReferenceCount {
public:
CollisionHandler();
virtual void begin_group();
virtual void add_entry(CollisionEntry *entry);
virtual bool end_group();
INLINE bool wants_all_potential_collidees() const;
INLINE void set_root(const NodePath &root);
PUBLISHED:
static TypeHandle get_class_type() {
return _type_handle;
@ -55,12 +61,18 @@ public:
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
protected:
bool _wants_all_potential_collidees;
const NodePath *_root;
private:
static TypeHandle _type_handle;
friend class CollisionTraverser;
};
#include "collisionHandler.I"
#endif

View File

@ -102,13 +102,13 @@ handle_entries() {
7. go to 2
*/
bool okflag = true;
if (!_horizontal) {
collide_cat.error() << "collisionHandlerFluidPusher::handle_entries is only supported in "
"horizontal mode" << endl;
nassertr(false, false);
}
// for every fluid mover being pushed...
FromEntries::iterator fei;
for (fei = _from_entries.begin(); fei != _from_entries.end(); ++fei) {
@ -129,17 +129,30 @@ handle_entries() {
ColliderDef &def = (*ci).second;
// extract the collision entries into a vector that we can safely modify
Entries SCS(*entries);
Entries entries(*entries);
Entries next_entries;
// extract out the initial set of collision solids
CollisionSolids SCS;
Entries::iterator ei;
for (ei = entries.begin(); ei != entries.end(); ++ei) {
SCS.push_back((*ei)->get_into());
}
// currently we only support spheres as the collider
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, (*SCS.front()).get_from(), 0);
DCAST_INTO_R(sphere, (*entries.front()).get_from(), 0);
// use a slightly larger radius value so that when we move along
// collision planes we don't re-collide
float sphere_radius = sphere->get_radius() * 1.001;
// make a copy of the original from_nodepath that we can mess with
// in the process of calculating the final position
_from_node_path_copy = from_node_path.copy_to(from_node_path.get_parent());
LPoint3f N(from_node_path.get_pos_delta(*_root));
const LPoint3f orig_pos(from_node_path.get_pos());
const LPoint3f orig_pos(_from_node_path_copy.get_pos());
// this will hold the final calculated position
LPoint3f PosX(orig_pos);
@ -157,20 +170,17 @@ handle_entries() {
// if both of these become true, we're stuck in a 'corner'
bool left_halfspace_obstructed = false;
bool right_halfspace_obstructed = false;
LVector3f left_plane_normal;
LVector3f right_plane_normal;
float left_plane_dot = 200.0f;
float right_plane_dot = 200.0f;
// iterate until the mover runs out of movement or gets stuck
while (true) {
CollisionEntry *C = 0;
Entries::iterator ei;
// find the first (earliest) collision
for (ei = SCS.begin(); ei != SCS.end(); ++ei) {
for (ei = entries.begin(); ei != entries.end(); ++ei) {
CollisionEntry *entry = (*ei);
nassertr(entry != (CollisionEntry *)NULL, false);
if (entry->get_t() < C->get_t()) {
if ((C == 0) || (entry->get_t() < C->get_t())) {
nassertr(from_node_path == entry->get_from_node_path(), false);
C = entry;
break;
@ -186,12 +196,12 @@ handle_entries() {
nassertr(C->has_surface_point(), true);
nassertr(C->has_surface_normal(), true);
nassertr(C->has_interior_point(), true);
LVector3f surface_normal = C->get_surface_normal(from_node_path);
LVector3f surface_normal = C->get_surface_normal(_from_node_path_copy);
if (_horizontal) {
surface_normal[2] = 0.0f;
}
surface_normal.normalize();
PosX = C->get_surface_point(from_node_path) + (sphere_radius * surface_normal);
PosX = C->get_surface_point(_from_node_path_copy) + (sphere_radius * surface_normal);
// check to see if we're stuck, given this collision
float dot = right_unit.dot(surface_normal);
@ -204,7 +214,6 @@ handle_entries() {
break;
}
left_halfspace_obstructed = true;
left_plane_normal = surface_normal;
}
} else {
// negative dot means plane is coming from the right (looking along original
@ -216,11 +225,29 @@ handle_entries() {
break;
}
right_halfspace_obstructed = true;
right_plane_normal = surface_normal;
}
}
// set up new current/last positions, re-calculate collisions
CPT(TransformState) prev_trans(_from_node_path_copy.get_prev_transform());
prev_trans->set_pos(_from_node_path_copy.get_pos());
_from_node_path_copy.set_prev_transform(prev_trans);
_from_node_path_copy.set_pos(PosX);
// calculate new collisions given new movement vector
CollisionEntry new_entry;
new_entry._from_node_path = _from_node_path_copy;
new_entry._from = sphere;
next_entries.clear();
CollisionSolids::iterator csi;
for (csi = SCS.begin(); csi != SCS.end(); ++csi) {
PT(CollisionEntry) result = (*csi)->test_intersection_from_sphere(new_entry);
if (result != (CollisionEntry *)NULL) {
next_entries.push_back(result);
}
}
// swap in the new set of collision events
entries.swap(next_entries);
}
LVector3f net_shove(PosX - orig_pos);

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "collisionSolid.h"
#include "collisionHandlerPusher.h"
////////////////////////////////////////////////////////////////////
@ -37,8 +38,12 @@ public:
virtual void add_entry(CollisionEntry *entry);
protected:
typedef pvector< CPT(CollisionSolid) > CollisionSolids;
virtual bool handle_entries();
NodePath _from_node_path_copy;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -45,7 +45,6 @@ protected:
const LVector3f &force_normal);
virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
private:
bool _horizontal;

View File

@ -147,7 +147,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
// is as good as any other.
surface_normal.set(1.0, 0.0, 0.0);
} else {
surface_normal = -vec / vec_length;
surface_normal = vec / -vec_length;
}
LVector3f normal = (has_effective_normal() && sphere->get_respect_effective_normal()) ? get_effective_normal() : surface_normal;

View File

@ -414,6 +414,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
LPoint3f orig_center = sphere->get_center() * wrt_mat;
LPoint3f from_center = orig_center;
bool moved_from_center = false;
float t = 1.0f;
if (wrt_prev_space != wrt_space) {
// If we have a delta between the previous position and the
@ -439,13 +440,15 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
// at the point along its path that is closest to intersecting
// the plane. This may be the actual intersection point, or it
// may be the starting point or the final point.
float t = -(dist_to_plane(a) / dot);
t = -(dist_to_plane(a) / dot);
if (t >= 1.0f) {
// Leave it where it is.
t = 1.0f;
} else if (t < 0.0f) {
from_center = a;
moved_from_center = true;
t = 0.0f;
} else {
from_center = a + t * delta;
@ -556,6 +559,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
new_entry->set_surface_normal(normal);
new_entry->set_surface_point(from_center - normal * dist);
new_entry->set_interior_point(from_center - normal * (dist + into_depth));
new_entry->set_t(t);
return new_entry;
}

View File

@ -178,6 +178,7 @@ private:
friend class CollisionLine;
friend class CollisionRay;
friend class CollisionSegment;
friend class CollisionHandlerFluidPusher;
};
INLINE ostream &operator << (ostream &out, const CollisionSolid &cs) {

View File

@ -288,6 +288,7 @@ traverse(const NodePath &root) {
Handlers::iterator hi;
for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
(*hi).first->set_root(root);
(*hi).first->begin_group();
}

View File

@ -213,6 +213,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
into_intersection_point = from_a + t1 * from_direction;
}
set_intersection_point(new_entry, into_intersection_point, from_radius);
new_entry->set_t(t1);
return new_entry;
}