Skip to content

Commit 8772365

Browse files
committed
added ragdoll intersection filtering tools
1 parent 30ac1da commit 8772365

File tree

9 files changed

+282
-21
lines changed

9 files changed

+282
-21
lines changed

Content/Documentation/ScriptingAPI-Documentation.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,8 +704,9 @@ The scene holds components. Entity handles can be used to retrieve associated co
704704
- [outer]FILTER_NAVIGATION_MESH : uint -- include navigation meshes
705705
- [outer]FILTER_OBJECT_ALL : uint -- include all objects, meshes
706706
- [outer]FILTER_COLLIDER : uint -- include colliders
707+
- [outer]FILTER_RAGDOLL : uint -- include ragdoll body parts
707708
- [outer]FILTER_ALL : uint -- include everything
708-
- Intersects(Ray|Sphere|Capsule primitive, opt uint filterMask = ~0u, opt uint layerMask = ~0u, opt uint lod = 0) : int entity, Vector position,normal, float distance, Vector velocity, int subsetIndex, Matrix orientation, Vector uv -- intersects a primitive with the scene and returns collision parameters
709+
- Intersects(Ray|Sphere|Capsule primitive, opt uint filterMask = ~0u, opt uint layerMask = ~0u, opt uint lod = 0) : int entity, Vector position,normal, float distance, Vector velocity, int subsetIndex, Matrix orientation, Vector uv, HumanoidBone humanoid_bone -- intersects a primitive with the scene and returns collision parameters. If humanoid_bone is not `HumanoidBone.Count` then the intersection is a ragdoll, and entity refers to the humanoid entity
709710
- IntersectsFirst(Ray primitive, opt uint filterMask = ~0u, opt uint layerMask = ~0u, opt uint lod = 0) : bool -- intersects a primitive with the scene and returns true immediately on intersection, false if there was no intersection. This can be faster for occlusion check than regular `Intersects` that searches for closest intersection.
710711
- Update() -- updates the scene and every entity and component inside the scene
711712
- Clear() -- deletes every entity and component inside the scene
@@ -1408,6 +1409,8 @@ Describes a Collider object.
14081409
- SetLookAt(Vector value) -- Set a target lookAt position (for head an eyes movement)
14091410
- SetRagdollPhysicsEnabled(bool value) -- Activate dynamic ragdoll physics. Note that kinematic ragdoll physics is always active (ragdoll is animation-driven/kinematic by default).
14101411
- IsRagdollPhysicsEnabled() : bool
1412+
- SetIntersectionDisabled(bool value) -- turn off intersection test for this ragdoll. This only affects direct intersection check with Scene::Intersects()
1413+
- IsIntersectionDisabled() : bool
14111414
- SetRagdollFatness(float value) -- Control the overall fatness of the ragdoll body parts except head (default: 1)
14121415
- SetRagdollHeadSize(float value) -- Control the overall size of the ragdoll head (default: 1)
14131416
- GetRagdollFatness() : float
@@ -1469,6 +1472,8 @@ Describes a Collider object.
14691472
RightLittleProximal = 52,
14701473
RightLittleIntermediate = 53,
14711474
RightLittleDistal = 54,
1475+
1476+
Count = 55
14721477
}
14731478

14741479

WickedEngine/wiEnums.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace wi::enums
3131

3232
// Other filtering types:
3333
FILTER_COLLIDER = 1 << 5,
34+
FILTER_RAGDOLL = 1 << 6,
3435

3536
// Include everything:
3637
FILTER_ALL = ~0,

WickedEngine/wiPhysics_Jolt.cpp

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ namespace wi::physics
254254
// for trace hit reporting:
255255
wi::ecs::Entity humanoid_ragdoll_entity = wi::ecs::INVALID_ENTITY;
256256
wi::scene::HumanoidComponent::HumanoidBone humanoid_bone = wi::scene::HumanoidComponent::HumanoidBone::Count;
257+
wi::primitive::Capsule capsule;
257258

258259
~RigidBody()
259260
{
@@ -785,9 +786,11 @@ namespace wi::physics
785786
case BODYPART_LEFT_LOWER_ARM:
786787
case BODYPART_RIGHT_UPPER_ARM:
787788
case BODYPART_RIGHT_LOWER_ARM:
789+
physicsobject.capsule = wi::primitive::Capsule(XMFLOAT3(-capsule_height * 0.5f - capsule_radius, 0, 0), XMFLOAT3(capsule_height * 0.5f + capsule_radius, 0, 0), capsule_radius);
788790
rtshape_settings.mRotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI).Normalized();
789791
break;
790792
default:
793+
physicsobject.capsule = wi::primitive::Capsule(XMFLOAT3(0, -capsule_height * 0.5f - capsule_radius, 0), XMFLOAT3(0, capsule_height * 0.5f + capsule_radius, 0), capsule_radius);
791794
break;
792795
}
793796

@@ -1656,15 +1659,39 @@ namespace wi::physics
16561659
if (humanoid.ragdoll == nullptr)
16571660
return;
16581661
Ragdoll& ragdoll = *(Ragdoll*)humanoid.ragdoll.get();
1659-
if (humanoid.IsRagdollPhysicsEnabled())
1662+
1663+
if (humanoid.ragdoll_bodyparts.size() != Ragdoll::BODYPART_COUNT)
16601664
{
1661-
BodyInterface& body_interface = physics_scene.physics_system.GetBodyInterfaceNoLock();
1662-
for (auto& rb : ragdoll.rigidbodies)
1665+
humanoid.ragdoll_bodyparts.resize(Ragdoll::BODYPART_COUNT);
1666+
}
1667+
humanoid.ragdoll_bounds = wi::primitive::AABB();
1668+
int caps = 0;
1669+
1670+
BodyInterface& body_interface = physics_scene.physics_system.GetBodyInterfaceNoLock();
1671+
for (auto& rb : ragdoll.rigidbodies)
1672+
{
1673+
TransformComponent* transform = scene.transforms.GetComponent(rb.entity);
1674+
if (transform == nullptr)
1675+
continue;
1676+
Mat44 mat = body_interface.GetWorldTransform(rb.bodyID);
1677+
1678+
XMFLOAT4X4 capsulemat = cast(mat);
1679+
XMMATRIX M = XMLoadFloat4x4(&capsulemat);
1680+
auto& bp = humanoid.ragdoll_bodyparts[caps++];
1681+
bp.bone = rb.humanoid_bone;
1682+
bp.capsule.radius = rb.capsule.radius;
1683+
XMStoreFloat3(&bp.capsule.base, XMVector3Transform(XMLoadFloat3(&rb.capsule.base), M));
1684+
XMStoreFloat3(&bp.capsule.tip, XMVector3Transform(XMLoadFloat3(&rb.capsule.tip), M));
1685+
humanoid.ragdoll_bounds = wi::primitive::AABB::Merge(humanoid.ragdoll_bounds, bp.capsule.getAABB());
1686+
1687+
#if 0
1688+
scene.locker.lock();
1689+
wi::renderer::DrawCapsule(bp.capsule, XMFLOAT4(1, 1, 1, 1), false);
1690+
scene.locker.unlock();
1691+
#endif
1692+
1693+
if (humanoid.IsRagdollPhysicsEnabled())
16631694
{
1664-
TransformComponent* transform = scene.transforms.GetComponent(rb.entity);
1665-
if (transform == nullptr)
1666-
continue;
1667-
Mat44 mat = body_interface.GetWorldTransform(rb.bodyID);
16681695
mat = mat * rb.additionalTransformInverse;
16691696
mat = mat * rb.restBasis;
16701697
Vec3 position = mat.GetTranslation();
@@ -1681,6 +1708,14 @@ namespace wi::physics
16811708
transform->SetDirty();
16821709
}
16831710
}
1711+
1712+
#if 0
1713+
scene.locker.lock();
1714+
XMFLOAT4X4 mat;
1715+
XMStoreFloat4x4(&mat, humanoid.ragdoll_bounds.getAsBoxMatrix());
1716+
wi::renderer::DrawBox(mat, XMFLOAT4(1, 1, 1, 1), false);
1717+
scene.locker.unlock();
1718+
#endif
16841719
});
16851720

16861721
#ifdef JPH_DEBUG_RENDERER
@@ -2015,6 +2050,38 @@ namespace wi::physics
20152050
return cast(soft_vertices[physicsIndex].mPosition);
20162051
}
20172052

2053+
2054+
template <class CollectorType>
2055+
class WickedClosestHitCollector : public JPH::ClosestHitCollisionCollector<CollectorType>
2056+
{
2057+
public:
2058+
const Scene* scene = nullptr;
2059+
const PhysicsScene* physics_scene = nullptr;
2060+
2061+
using ResultType = typename CollectorType::ResultType;
2062+
void AddHit(const ResultType& inResult) override
2063+
{
2064+
BodyLockRead lock(physics_scene->physics_system.GetBodyLockInterfaceNoLock(), inResult.mBodyID);
2065+
if (!lock.Succeeded())
2066+
return;
2067+
const Body& body = lock.GetBody();
2068+
const uint64_t userdata = body.GetUserData();
2069+
2070+
if (body.IsRigidBody())
2071+
{
2072+
const RigidBody* physicsobject = (RigidBody*)userdata;
2073+
if (physicsobject->humanoid_ragdoll_entity != INVALID_ENTITY)
2074+
{
2075+
const HumanoidComponent* humanoid = scene->humanoids.GetComponent(physicsobject->humanoid_ragdoll_entity);
2076+
if (humanoid != nullptr && humanoid->IsIntersectionDisabled())
2077+
return; // skip this from AddHit
2078+
}
2079+
}
2080+
2081+
ClosestHitCollisionCollector<CollectorType>::AddHit(inResult);
2082+
}
2083+
};
2084+
20182085
RayIntersectionResult Intersects(
20192086
const wi::scene::Scene& scene,
20202087
wi::primitive::Ray ray
@@ -2042,7 +2109,9 @@ namespace wi::physics
20422109
settings.mBackFaceMode = EBackFaceMode::IgnoreBackFaces;
20432110
settings.mTreatConvexAsSolid = false;
20442111

2045-
ClosestHitCollisionCollector<CastRayCollector> collector;
2112+
WickedClosestHitCollector<CastRayCollector> collector;
2113+
collector.scene = &scene;
2114+
collector.physics_scene = &physics_scene;
20462115

20472116
physics_scene.physics_system.GetNarrowPhaseQuery().CastRay(inray, settings, collector);
20482117
if (!collector.HadHit())

0 commit comments

Comments
 (0)