mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -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()) {
|
if (!_into_node_path.is_empty()) {
|
||||||
indent(out, indent_level + 2)
|
indent(out, indent_level + 2)
|
||||||
<< "into " << _into_node_path;
|
<< "into " << _into_node_path;
|
||||||
|
|
||||||
|
out << " [";
|
||||||
|
_into_node_path.node()->list_tags(out, ", ");
|
||||||
|
out << "]";
|
||||||
|
|
||||||
const ClipPlaneAttrib *cpa = get_into_clip_planes();
|
const ClipPlaneAttrib *cpa = get_into_clip_planes();
|
||||||
if (cpa != (ClipPlaneAttrib *)NULL) {
|
if (cpa != (ClipPlaneAttrib *)NULL) {
|
||||||
out << " (clipped)";
|
out << " (clipped)";
|
||||||
|
@ -50,6 +50,66 @@ CollisionHandlerGravity::
|
|||||||
~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
|
// Function: CollisionHandlerGravity::handle_entries
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
@ -64,18 +124,6 @@ CollisionHandlerGravity::
|
|||||||
bool CollisionHandlerGravity::
|
bool CollisionHandlerGravity::
|
||||||
handle_entries() {
|
handle_entries() {
|
||||||
bool okflag = true;
|
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;
|
FromEntries::const_iterator fi;
|
||||||
for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) {
|
for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) {
|
||||||
@ -94,96 +142,59 @@ handle_entries() {
|
|||||||
okflag = false;
|
okflag = false;
|
||||||
} else {
|
} else {
|
||||||
ColliderDef &def = (*ci).second;
|
ColliderDef &def = (*ci).second;
|
||||||
{
|
float max_height = set_highest_collision(def._target, from_node_path, entries);
|
||||||
// Get the maximum height for all collisions with this node.
|
|
||||||
bool got_max = false;
|
|
||||||
float max_height = 0.0f;
|
|
||||||
|
|
||||||
CollisionEntry* highest;
|
// Now set our height accordingly.
|
||||||
if (!entries.empty()) {
|
float adjust = max_height + _offset;
|
||||||
_outer_space = false;
|
if (_current_velocity > 0.0f || !IS_THRESHOLD_ZERO(adjust, 0.001)) {
|
||||||
}
|
if (collide_cat.is_debug()) {
|
||||||
Entries::const_iterator ei;
|
collide_cat.debug()
|
||||||
for (ei = entries.begin(); ei != entries.end(); ++ei) {
|
<< "Adjusting height by " << adjust << "\n";
|
||||||
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.
|
if (_current_velocity > 0.0f || adjust < -0.001f) {
|
||||||
float adjust = max_height + _offset;
|
// ...we have a vertical thrust,
|
||||||
if (_current_velocity > 0.0f || !IS_THRESHOLD_ZERO(adjust, 0.001)) {
|
// ...or the node is above the floor, so it is airborne.
|
||||||
if (collide_cat.is_debug()) {
|
float dt = ClockObject::get_global_clock()->get_dt();
|
||||||
collide_cat.debug()
|
// Fyi, the sign of _gravity is reversed. I think it makes the get_*() set_*()
|
||||||
<< "Adjusting height by " << adjust << "\n";
|
// more intuitive to do it this way.
|
||||||
}
|
float gravity_adjust = _current_velocity * dt + 0.5 * -_gravity * dt * dt;
|
||||||
|
if (adjust > 0.0f) {
|
||||||
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) {
|
|
||||||
// ...the node is under the floor, so it has landed.
|
// ...the node is under the floor, so it has landed.
|
||||||
_impact_velocity = _current_velocity;
|
// Keep the adjust to bring us up to the ground and
|
||||||
// These values are used by is_on_ground().
|
// then add the gravity_adjust to get us airborne:
|
||||||
_current_velocity = _airborne_height = 0.0f;
|
adjust += max(0.0f, gravity_adjust);
|
||||||
// Add only the one that we're impacting with:
|
} else {
|
||||||
add_entry(highest);
|
// ...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();
|
if (_airborne_height < 0.001f && _current_velocity < 0.001f) {
|
||||||
LVecBase3f pos = trans->get_pos();
|
// ...the node is under the floor, so it has landed.
|
||||||
pos[2] += adjust;
|
_impact_velocity = _current_velocity;
|
||||||
def._target.set_transform(trans->set_pos(pos));
|
// These values are used by is_on_ground().
|
||||||
def.updated_transform();
|
|
||||||
|
|
||||||
apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust));
|
|
||||||
} else {
|
|
||||||
_current_velocity = _airborne_height = 0.0f;
|
_current_velocity = _airborne_height = 0.0f;
|
||||||
if (collide_cat.is_spam()) {
|
} else {
|
||||||
collide_cat.spam()
|
// ...we're airborne.
|
||||||
<< "Leaving height unchanged.\n";
|
_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;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CollisionHandlerGravity::apply_linear_force
|
// Function: CollisionHandlerGravity::apply_linear_force
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
|
@ -56,6 +56,7 @@ PUBLISHED:
|
|||||||
INLINE float get_max_velocity() const;
|
INLINE float get_max_velocity() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
float set_highest_collision(const NodePath &target_node_path, const NodePath &from_node_path, const Entries &entries);
|
||||||
virtual bool handle_entries();
|
virtual bool handle_entries();
|
||||||
virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
|
virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user