Merge pull request #118155 from mihe/jolt/motion-contact-filtering
Move the Jolt `body_test_motion` contact filtering to collector
This commit is contained in:
@@ -190,7 +190,7 @@ bool JoltPhysicsDirectSpaceState3D::_body_motion_recover(const JoltBody3D &p_bod
|
||||
for (int i = 0; i < JoltProjectSettings::motion_query_recovery_iterations; ++i) {
|
||||
collector.reset();
|
||||
|
||||
_collide_shape_kinematics(jolt_shape, JPH::Vec3::sOne(), to_jolt_r(transform_com), settings, to_jolt_r(base_offset), collector, motion_filter, motion_filter, motion_filter, motion_filter);
|
||||
_collide_shape_motion(jolt_shape, JPH::Vec3::sOne(), to_jolt_r(transform_com), settings, to_jolt_r(base_offset), collector, motion_filter, motion_filter, motion_filter, motion_filter);
|
||||
|
||||
if (!collector.had_hit()) {
|
||||
break;
|
||||
@@ -316,8 +316,8 @@ bool JoltPhysicsDirectSpaceState3D::_body_motion_collide(const JoltBody3D &p_bod
|
||||
const Vector3 &base_offset = transform_com.origin;
|
||||
|
||||
const JoltMotionFilter3D motion_filter(p_body, p_excluded_bodies, p_excluded_objects);
|
||||
JoltQueryCollectorClosestMulti<JPH::CollideShapeCollector, 32> collector(p_max_collisions);
|
||||
_collide_shape_kinematics(jolt_shape, JPH::Vec3::sOne(), to_jolt_r(transform_com), settings, to_jolt_r(base_offset), collector, motion_filter, motion_filter, motion_filter, motion_filter);
|
||||
JoltQueryCollectorMotion<JPH::CollideShapeCollector, 32> collector(p_motion, p_margin, p_max_collisions);
|
||||
_collide_shape_motion(jolt_shape, JPH::Vec3::sOne(), to_jolt_r(transform_com), settings, to_jolt_r(base_offset), collector, motion_filter, motion_filter, motion_filter, motion_filter);
|
||||
|
||||
if (!collector.had_hit() || p_result == nullptr) {
|
||||
return collector.had_hit();
|
||||
@@ -328,21 +328,8 @@ bool JoltPhysicsDirectSpaceState3D::_body_motion_collide(const JoltBody3D &p_bod
|
||||
for (int i = 0; i < collector.get_hit_count(); ++i) {
|
||||
const JPH::CollideShapeResult &hit = collector.get_hit(i);
|
||||
|
||||
const float penetration_depth = hit.mPenetrationDepth + p_margin;
|
||||
|
||||
if (penetration_depth <= 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vector3 normal = to_godot(-hit.mPenetrationAxis.Normalized());
|
||||
|
||||
if (p_motion.length_squared() > 0) {
|
||||
const Vector3 direction = p_motion.normalized();
|
||||
|
||||
if (direction.dot(normal) >= -CMP_EPSILON) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const float penetration_depth = hit.mPenetrationDepth + p_margin;
|
||||
|
||||
JPH::ContactPoints contact_points1;
|
||||
JPH::ContactPoints contact_points2;
|
||||
@@ -439,7 +426,7 @@ void JoltPhysicsDirectSpaceState3D::_collide_shape_queries(
|
||||
}
|
||||
}
|
||||
|
||||
void JoltPhysicsDirectSpaceState3D::_collide_shape_kinematics(
|
||||
void JoltPhysicsDirectSpaceState3D::_collide_shape_motion(
|
||||
const JPH::Shape *p_shape,
|
||||
JPH::Vec3Arg p_scale,
|
||||
JPH::RMat44Arg p_transform_com,
|
||||
|
||||
@@ -64,7 +64,7 @@ class JoltPhysicsDirectSpaceState3D final : public PhysicsDirectSpaceState3D {
|
||||
void _generate_manifold(const JPH::CollideShapeResult &p_hit, JPH::ContactPoints &r_contact_points1, JPH::ContactPoints &r_contact_points2 JPH_IF_DEBUG_RENDERER(, JPH::RVec3Arg p_center_of_mass)) const;
|
||||
|
||||
void _collide_shape_queries(const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, JPH::RMat44Arg p_transform_com, const JPH::CollideShapeSettings &p_settings, JPH::RVec3Arg p_base_offset, JPH::CollideShapeCollector &p_collector, const JPH::BroadPhaseLayerFilter &p_broad_phase_layer_filter = JPH::BroadPhaseLayerFilter(), const JPH::ObjectLayerFilter &p_object_layer_filter = JPH::ObjectLayerFilter(), const JPH::BodyFilter &p_body_filter = JPH::BodyFilter(), const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const;
|
||||
void _collide_shape_kinematics(const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, JPH::RMat44Arg p_transform_com, const JPH::CollideShapeSettings &p_settings, JPH::RVec3Arg p_base_offset, JPH::CollideShapeCollector &p_collector, const JPH::BroadPhaseLayerFilter &p_broad_phase_layer_filter = JPH::BroadPhaseLayerFilter(), const JPH::ObjectLayerFilter &p_object_layer_filter = JPH::ObjectLayerFilter(), const JPH::BodyFilter &p_body_filter = JPH::BodyFilter(), const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const;
|
||||
void _collide_shape_motion(const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, JPH::RMat44Arg p_transform_com, const JPH::CollideShapeSettings &p_settings, JPH::RVec3Arg p_base_offset, JPH::CollideShapeCollector &p_collector, const JPH::BroadPhaseLayerFilter &p_broad_phase_layer_filter = JPH::BroadPhaseLayerFilter(), const JPH::ObjectLayerFilter &p_object_layer_filter = JPH::ObjectLayerFilter(), const JPH::BodyFilter &p_body_filter = JPH::BodyFilter(), const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const;
|
||||
|
||||
public:
|
||||
JoltPhysicsDirectSpaceState3D() = default;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/math/vector3.h"
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/Core/STLLocalAllocator.h>
|
||||
@@ -37,7 +39,7 @@
|
||||
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
||||
|
||||
template <typename TBase, int TDefaultCapacity>
|
||||
class JoltQueryCollectorAll final : public TBase {
|
||||
class JoltQueryCollectorAll : public TBase {
|
||||
public:
|
||||
typedef typename TBase::ResultType Hit;
|
||||
typedef JPH::Array<Hit, JPH::STLLocalAllocator<Hit, TDefaultCapacity>> HitArray;
|
||||
@@ -75,7 +77,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename TBase>
|
||||
class JoltQueryCollectorAny final : public TBase {
|
||||
class JoltQueryCollectorAny : public TBase {
|
||||
public:
|
||||
typedef typename TBase::ResultType Hit;
|
||||
|
||||
@@ -106,7 +108,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename TBase, int TDefaultCapacity>
|
||||
class JoltQueryCollectorAnyMulti final : public TBase {
|
||||
class JoltQueryCollectorAnyMulti : public TBase {
|
||||
public:
|
||||
typedef typename TBase::ResultType Hit;
|
||||
typedef JPH::Array<Hit, JPH::STLLocalAllocator<Hit, TDefaultCapacity>> HitArray;
|
||||
@@ -154,7 +156,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename TBase>
|
||||
class JoltQueryCollectorClosest final : public TBase {
|
||||
class JoltQueryCollectorClosest : public TBase {
|
||||
public:
|
||||
typedef typename TBase::ResultType Hit;
|
||||
|
||||
@@ -189,7 +191,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename TBase, int TDefaultCapacity>
|
||||
class JoltQueryCollectorClosestMulti final : public TBase {
|
||||
class JoltQueryCollectorClosestMulti : public TBase {
|
||||
public:
|
||||
typedef typename TBase::ResultType Hit;
|
||||
typedef JPH::Array<Hit, JPH::STLLocalAllocator<Hit, TDefaultCapacity + 1>> HitArray;
|
||||
@@ -240,3 +242,45 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TCollector, int TDefaultCapacity>
|
||||
class JoltQueryCollectorMotion : public JoltQueryCollectorClosestMulti<TCollector, TDefaultCapacity> {
|
||||
public:
|
||||
typedef JoltQueryCollectorClosestMulti<TCollector, TDefaultCapacity> Base;
|
||||
typedef typename Base::Hit Hit;
|
||||
|
||||
private:
|
||||
Vector3 direction;
|
||||
float distance_sq = 0.0f;
|
||||
float margin = 0.0f;
|
||||
|
||||
public:
|
||||
JoltQueryCollectorMotion(const Vector3 &p_motion, float p_margin, int p_max_hits = TDefaultCapacity) :
|
||||
Base(p_max_hits),
|
||||
direction(p_motion.normalized()),
|
||||
distance_sq(p_motion.length_squared()),
|
||||
margin(p_margin) {}
|
||||
|
||||
virtual void AddHit(const Hit &p_hit) override {
|
||||
// Ignore hits that are outside of the margin.
|
||||
const float penetration_depth = p_hit.mPenetrationDepth + margin;
|
||||
if (penetration_depth <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore hits that don't oppose the motion direction.
|
||||
//
|
||||
// This is a deliberate divergence from the Godot Physics reference implementation (which
|
||||
// does not do this type of filtering) and is known to cause issues. However, not having
|
||||
// this results in a problematic amount of ghost collisions with `move_and_slide`, for
|
||||
// reasons that are still unclear as of writing this.
|
||||
if (distance_sq > 0) {
|
||||
const Vector3 normal = to_godot(-p_hit.mPenetrationAxis.Normalized());
|
||||
if (direction.dot(normal) >= -CMP_EPSILON) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Base::AddHit(p_hit);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user