diff --git a/panda/src/collide/collisionEntry.cxx b/panda/src/collide/collisionEntry.cxx index 5086f3f416..21a6e74020 100644 --- a/panda/src/collide/collisionEntry.cxx +++ b/panda/src/collide/collisionEntry.cxx @@ -188,6 +188,11 @@ write(ostream &out, int indent_level) const { if (!_into_node_path.is_empty()) { indent(out, indent_level + 2) << "into " << _into_node_path; + + out << " ["; + _into_node_path.node()->list_tags(out, ", "); + out << "]"; + const ClipPlaneAttrib *cpa = get_into_clip_planes(); if (cpa != (ClipPlaneAttrib *)NULL) { out << " (clipped)"; diff --git a/panda/src/collide/collisionHandlerGravity.cxx b/panda/src/collide/collisionHandlerGravity.cxx index b47692aabc..f2310eec2e 100755 --- a/panda/src/collide/collisionHandlerGravity.cxx +++ b/panda/src/collide/collisionHandlerGravity.cxx @@ -50,6 +50,66 @@ CollisionHandlerGravity:: ~CollisionHandlerGravity() { } +//////////////////////////////////////////////////////////////////// +// Function: CollisionHandlerGravity::set_highest_collision +// Access: Protected +// Description: +// +// +// +// +// +// +//////////////////////////////////////////////////////////////////// +float CollisionHandlerGravity:: +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. + bool got_max = false; + float max_height = 0.0f; + + CollisionEntry* highest; + _outer_space = entries.empty(); + 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 (!got_max || height > max_height) { + got_max = true; + max_height = height; + highest = entry; + } + } + } + + #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<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; - highest = entry; - } - } - } - - // 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 = ClockObject::get_global_clock()->get_dt(); - // 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; - } - - // ...we are airborne. - // We only collide with things we are impacting with. - // Remove the collisions: - _current_colliding.clear(); + float max_height = set_highest_collision(def._target, from_node_path, entries); - if (_airborne_height < 0.001f && _current_velocity < 0.001f) { + // 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 = ClockObject::get_global_clock()->get_dt(); + // Fyi, the sign of _gravity is reversed. 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. - _impact_velocity = _current_velocity; - // These values are used by is_on_ground(). - _current_velocity = _airborne_height = 0.0f; - // Add only the one that we're impacting with: - add_entry(highest); + // 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; + } - 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 (_airborne_height < 0.001f && _current_velocity < 0.001f) { + // ...the node is under the floor, so it has landed. + _impact_velocity = _current_velocity; + // These values are used by is_on_ground(). _current_velocity = _airborne_height = 0.0f; - if (collide_cat.is_spam()) { - collide_cat.spam() - << "Leaving height unchanged.\n"; - } + } else { + // ...we're airborne. + _current_colliding.clear(); + } + + 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"; } } } @@ -191,7 +202,6 @@ handle_entries() { return okflag; } - //////////////////////////////////////////////////////////////////// // Function: CollisionHandlerGravity::apply_linear_force // Access: Protected, Virtual diff --git a/panda/src/collide/collisionHandlerGravity.h b/panda/src/collide/collisionHandlerGravity.h index f81dcd551f..9450abd779 100755 --- a/panda/src/collide/collisionHandlerGravity.h +++ b/panda/src/collide/collisionHandlerGravity.h @@ -56,6 +56,7 @@ PUBLISHED: INLINE float get_max_velocity() const; protected: + float set_highest_collision(const NodePath &target_node_path, const NodePath &from_node_path, const Entries &entries); virtual bool handle_entries(); virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);