mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
fixed the floor ray sending events for untouched floors
This commit is contained in:
parent
5d8bb3dfab
commit
cf8beef552
@ -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)";
|
||||
|
@ -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<<endl;
|
||||
#endif
|
||||
|
||||
// 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);
|
||||
|
||||
return max_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CollisionHandlerGravity::handle_entries
|
||||
// Access: Protected, Virtual
|
||||
@ -64,18 +124,6 @@ CollisionHandlerGravity::
|
||||
bool CollisionHandlerGravity::
|
||||
handle_entries() {
|
||||
bool okflag = true;
|
||||
_outer_space = true;
|
||||
|
||||
if (0) {
|
||||
cout << endl;
|
||||
cerr
|
||||
<< "CollisionHandlerGravity.handle_entries {\n"
|
||||
<< "_from_entries has " << _from_entries.size()
|
||||
<< "_colliders has " << _colliders.size()
|
||||
<< "current_colliding has " << _current_colliding.size()
|
||||
<< " entries, last_colliding has " << _last_colliding.size()
|
||||
<< "\n}" << endl;
|
||||
}
|
||||
|
||||
FromEntries::const_iterator fi;
|
||||
for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) {
|
||||
@ -94,96 +142,59 @@ handle_entries() {
|
||||
okflag = false;
|
||||
} else {
|
||||
ColliderDef &def = (*ci).second;
|
||||
{
|
||||
// Get the maximum height for all collisions with this node.
|
||||
bool got_max = false;
|
||||
float max_height = 0.0f;
|
||||
float max_height = set_highest_collision(def._target, from_node_path, entries);
|
||||
|
||||
CollisionEntry* highest;
|
||||
if (!entries.empty()) {
|
||||
_outer_space = false;
|
||||
}
|
||||
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;
|
||||
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";
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
if (_airborne_height < 0.001f && _current_velocity < 0.001f) {
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user