diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp index 7f143cc8..5a67d445 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp @@ -610,7 +610,7 @@ bool RigidBody::isGroundCollisionEnabled() const { bool enabled = false; enabled |= info.ground_col_mode != GroundCollisionMode::IgnoreGround; - enabled |= info.unk30; + enabled |= info.is_ragdoll; return enabled; } @@ -636,7 +636,7 @@ bool RigidBody::isWaterCollisionEnabled() const { bool enabled = false; // unk30 enables all collisions? - enabled |= info.unk30; + enabled |= info.is_ragdoll; enabled |= info.water_col_mode != WaterCollisionMode::IgnoreWater; return enabled; } diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp index 85c8d752..3f1bd76e 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp @@ -344,7 +344,7 @@ RigidBodyT* RigidBodyFromShape::make(const Shape& shape, RigidBodyInstanceParam* const u32 idx = group_handler ? group_handler->getIndex() : 0; collision_filter_info = [&] { EntityCollisionMask info{collision_filter_info}; - info.group_handler_index.SetUnsafe(idx); + info.regular.group_handler_index.SetUnsafe(idx); return info.raw; }(); } else { diff --git a/src/KingSystem/Physics/System/physClosestPointQuery.cpp b/src/KingSystem/Physics/System/physClosestPointQuery.cpp index ab4b8ffd..736334c5 100644 --- a/src/KingSystem/Physics/System/physClosestPointQuery.cpp +++ b/src/KingSystem/Physics/System/physClosestPointQuery.cpp @@ -28,9 +28,9 @@ bool ClosestPointQuery::isSuccess() const { void ClosestPointQuery::setLayerMasksAndBodyCollisionFilterInfo(const LayerMaskBuilder& builder) { EntityCollisionMask mask; - mask.data.query_custom_receiver_layer_mask = + mask.regular.query_custom_receiver_layer_mask = builder.getMasks()[int(ContactLayerType::Entity)].layers; - mask.data.layer = ContactLayer::EntityQueryCustomReceiver; + mask.regular.layer = ContactLayer::EntityQueryCustomReceiver; mBody->setCollisionFilterInfo(mask.raw); setLayerMasks(builder); diff --git a/src/KingSystem/Physics/System/physEntityGroupFilter.cpp b/src/KingSystem/Physics/System/physEntityGroupFilter.cpp index 646d846d..8b20d914 100644 --- a/src/KingSystem/Physics/System/physEntityGroupFilter.cpp +++ b/src/KingSystem/Physics/System/physEntityGroupFilter.cpp @@ -112,27 +112,30 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const { const EntityCollisionMask a{infoA}; const EntityCollisionMask b{infoB}; - constexpr auto GroupHandlerIdxMask = decltype(a.group_handler_index)::GetMask(); - constexpr auto GroupHandlerIdxShift = decltype(a.group_handler_index)::StartBit(); - if (!EntityCollisionMask(infoA | infoB).is_ground_hit_mask) { - if (a.unk30 && b.unk30) { + constexpr auto GroupHandlerIdxMask = decltype(a.regular.group_handler_index)::GetMask(); + constexpr auto GroupHandlerIdxShift = decltype(a.regular.group_handler_index)::StartBit(); + + if (a.is_ragdoll && b.is_ragdoll) { if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) { - if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index)) + if (testHandler(a.regular.group_handler_index) || + testHandler(b.regular.group_handler_index)) { return false; + } } else if ((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift != 0) { - if (a.data.unk5 == b.data.unk10 || b.data.unk5 == a.data.unk10) + if (a.regular.ragdoll_bone_index == b.regular.ragdoll_bone_index2 || + b.regular.ragdoll_bone_index == a.regular.ragdoll_bone_index2) return false; } return true; } - const auto layerA = static_cast(a.data.layer.Value()); - const auto layerB = static_cast(b.data.layer.Value()); + const auto layerA = static_cast(a.regular.layer.Value()); + const auto layerB = static_cast(b.regular.layer.Value()); if (layerA != ContactLayer::EntityQueryCustomReceiver && layerB != ContactLayer::EntityQueryCustomReceiver) { - if (!a.unk30 && !b.unk30) { + if (!a.is_ragdoll && !b.is_ragdoll) { if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB)) return false; if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB)) @@ -140,8 +143,10 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const { } if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) { - if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index)) + if (testHandler(a.regular.group_handler_index) || + testHandler(b.regular.group_handler_index)) { return false; + } } else if (((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift) > 15) { return false; } @@ -154,9 +159,9 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const { } if (layerA == ContactLayer::EntityQueryCustomReceiver) - return a.data.query_custom_receiver_layer_mask & (1 << layerB); + return a.regular.query_custom_receiver_layer_mask & (1 << layerB); else - return b.data.query_custom_receiver_layer_mask & (1 << layerA); + return b.regular.query_custom_receiver_layer_mask & (1 << layerA); } if (a.is_ground_hit_mask && b.is_ground_hit_mask) { @@ -176,37 +181,37 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const { if (a.is_ground_hit_mask && !b.is_ground_hit_mask) { const auto layerA = static_cast(a.ground_hit.layer.Value()); - const auto layerB = static_cast(b.data.layer.Value()); + const auto layerB = static_cast(b.regular.layer.Value()); entity_mask = b; ground_hit_mask = a; if (layerB == ContactLayer::EntityQueryCustomReceiver) - return b.data.query_custom_receiver_layer_mask & (1 << layerA); + return b.regular.query_custom_receiver_layer_mask & (1 << layerA); - if (!b.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB)) + if (!b.is_ragdoll && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB)) return false; - if (!b.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB)) + if (!b.is_ragdoll && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB)) return false; if (!testLayerCollision(layerA, layerB)) return false; } else /* A entity, B ground hit */ { - const auto layerA = static_cast(a.data.layer.Value()); + const auto layerA = static_cast(a.regular.layer.Value()); const auto layerB = static_cast(b.ground_hit.layer.Value()); entity_mask = a; ground_hit_mask = b; if (layerA == ContactLayer::EntityQueryCustomReceiver) - return a.data.query_custom_receiver_layer_mask & (1 << layerB); + return a.regular.query_custom_receiver_layer_mask & (1 << layerB); - if (!a.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB)) + if (!a.is_ragdoll && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB)) return false; - if (!a.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB)) + if (!a.is_ragdoll && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB)) return false; if (!testLayerCollision(layerB, layerA)) return false; } - return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.data.ground_hit)); + return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.regular.ground_hit)); } hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) const { @@ -217,7 +222,7 @@ hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) co const EntityCollisionMask info{infoB}; if (info.is_ground_hit_mask) return infoPhantomData.raw & (1 << info.ground_hit.getLayer()); - return infoPhantomData.layer_mask & (1 << info.data.layer); + return infoPhantomData.layer_mask & (1 << info.regular.layer); } hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const { @@ -336,19 +341,19 @@ hkBool EntityGroupFilter::testCollisionForRayCasting(u32 infoRayCast, u32 info) if (b.is_ground_hit_mask) return checkCollisionWithGroundHitMask(b.ground_hit, a); - const u32 bHandlerIdx = b.group_handler_index; + const u32 bHandlerIdx = b.regular.group_handler_index; const u32 aHandlerIdx = a.group_handler_index; if (aHandlerIdx == bHandlerIdx) { if (bHandlerIdx > 15) return false; - return a.layer_mask & (1 << b.data.layer); + return a.layer_mask & (1 << b.regular.layer); } if (testHandler(aHandlerIdx) || testHandler(bHandlerIdx)) return false; - return a.layer_mask & (1 << b.data.layer); + return a.layer_mask & (1 << b.regular.layer); } KSYS_ALWAYS_INLINE hkBool EntityGroupFilter::isCollisionEnabled(const hkpShapeRayCastInput& aInput, @@ -420,7 +425,7 @@ u32 makeEntityCollisionMask(ContactLayer layer, u32 mask) { if (current.is_ground_hit_mask) { return makeEntityGroundHitMaskImpl(layer, mask).raw; } else { - current.data.layer.SetUnsafe(layer); + current.regular.layer.SetUnsafe(layer); return current.raw; } } @@ -430,7 +435,7 @@ u32 setEntityCollisionMaskGroundHit(GroundHit ground_hit, u32 mask) { if (current.is_ground_hit_mask) { // This shouldn't happen: this function is not supposed to be called on ground hit masks. } else { - current.data.ground_hit.SetUnsafe(ground_hit); + current.regular.ground_hit.SetUnsafe(ground_hit); } return current.raw; } diff --git a/src/KingSystem/Physics/System/physEntityGroupFilter.h b/src/KingSystem/Physics/System/physEntityGroupFilter.h index b4c1c7d2..fb1989c3 100644 --- a/src/KingSystem/Physics/System/physEntityGroupFilter.h +++ b/src/KingSystem/Physics/System/physEntityGroupFilter.h @@ -109,17 +109,17 @@ inline u32 EntitySystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLa EntityCollisionMask result; if (layer == ContactLayer::EntityRagdoll) { - result.data.layer.Init(layer); - result.data.unk5.Init(current_info.data.unk5); - result.data.unk10.Init(current_info.data.unk10); - result.group_handler_index.Init(getIndex()); - result.data.ground_hit.Init(ground_hit); - result.unk30 = true; + result.regular.layer.Init(layer); + result.regular.ragdoll_bone_index.Init(current_info.regular.ragdoll_bone_index); + result.regular.ragdoll_bone_index2.Init(current_info.regular.ragdoll_bone_index2); + result.regular.group_handler_index.Init(getIndex()); + result.regular.ground_hit.Init(ground_hit); + result.is_ragdoll = true; } else { - result.data.layer.Init(layer); + result.regular.layer.Init(layer); result.ground_col_mode.Init(current_info.ground_col_mode); - result.group_handler_index.Init(getIndex()); - result.data.ground_hit.Init(ground_hit); + result.regular.group_handler_index.Init(getIndex()); + result.regular.ground_hit.Init(ground_hit); } return result.raw; } @@ -136,9 +136,9 @@ inline u32 EntitySystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, Grou inline u32 EntitySystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) { EntityCollisionMask info; - info.data.layer.Init(ContactLayer::EntityRagdoll); - info.group_handler_index.Init(getIndex()); - info.data.ground_hit.Init(ground_hit); + info.regular.layer.Init(ContactLayer::EntityRagdoll); + info.regular.group_handler_index.Init(getIndex()); + info.regular.ground_hit.Init(ground_hit); return info.raw; } @@ -193,17 +193,17 @@ inline void EntityGroupFilter::setLayerCustomMask(ContactLayer layer, u32 mask) } inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) { - return EntityCollisionMask(info).group_handler_index; + return EntityCollisionMask(info).regular.group_handler_index; } inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5, u32 unk10) { EntityCollisionMask info; - info.data.layer.Init(layer); - info.data.unk5.Init(unk5); - info.data.unk10.Init(unk10); - info.data.ground_hit.Init(ground_hit); - info.unk30 = true; + info.regular.layer.Init(layer); + info.regular.ragdoll_bone_index.Init(unk5); + info.regular.ragdoll_bone_index2.Init(unk10); + info.regular.ground_hit.Init(ground_hit); + info.is_ragdoll = true; return info.raw; } diff --git a/src/KingSystem/Physics/physDefines.h b/src/KingSystem/Physics/physDefines.h index d9ba068c..a238e44d 100644 --- a/src/KingSystem/Physics/physDefines.h +++ b/src/KingSystem/Physics/physDefines.h @@ -210,21 +210,28 @@ enum class WaterCollisionMode { IgnoreWater = 1, }; +/// Collision filter info / collision mask that is used for entity rigid bodies. +/// https://docs.google.com/spreadsheets/d/e/2PACX-1vQyEL5_Wee3MI23c-nHa4dMPJDVen9TMMcrOUX7Wka9NAH1AW9bkkq7ZJHawJkSzGOqgHUYc-83t4Or/pubhtml union EntityCollisionMask { - union Data { + union RegularMask { ContactLayer getLayer() const { return int(layer); } ContactLayer getLayerSensor() const { return int(layer + FirstSensor); } GroundHit getGroundHit() const { return int(ground_hit); } u32 raw; util::BitField<0, 5, u32> layer; - // TODO: figure out what this is - util::BitField<5, 5, u32> unk5; - util::BitField<10, 5, u32> unk10; + + /// Only valid for ragdoll masks. + util::BitField<5, 5, u32> ragdoll_bone_index; + /// Only valid for ragdoll masks. + util::BitField<10, 5, u32> ragdoll_bone_index2; + + /// Only valid for CustomReceiver masks. /// Layers to collide with for EntityQueryCustomReceiver entities. util::BitField<5, NumRegularEntityLayers, u32> query_custom_receiver_layer_mask; - util::BitField<24, 1, u32> unk24; - util::BitField<25, 1, u32> unk25; + + /// Only valid for non-CustomReceiver masks. + util::BitField<16, 10, u32> group_handler_index; util::BitField<26, 4, u32> ground_hit; }; @@ -254,34 +261,34 @@ union EntityCollisionMask { static EntityCollisionMask make(ContactLayer layer, GroundHit ground_hit) { EntityCollisionMask mask; - mask.data.layer.Init(layer); - mask.data.ground_hit.Init(ground_hit); + mask.regular.layer.Init(layer); + mask.regular.ground_hit.Init(ground_hit); return mask; } ContactLayer getLayer() const { - return is_ground_hit_mask ? ground_hit.getLayer() : data.getLayer(); + return is_ground_hit_mask ? ground_hit.getLayer() : regular.getLayer(); } ContactLayer getLayerSensor() const { return is_ground_hit_mask ? ContactLayer(ContactLayer::SensorCustomReceiver) : - data.getLayerSensor(); + regular.getLayerSensor(); } GroundHit getGroundHit() const { - return is_ground_hit_mask ? GroundHit::HitAll : data.getGroundHit(); + return is_ground_hit_mask ? GroundHit::HitAll : regular.getGroundHit(); } u32 raw; - Data data; + RegularMask regular; GroundHitMask ground_hit; + /// Only valid in non-ragdoll, non-CustomReceiver mode. util::BitField<5, 2, GroundCollisionMode, u32> ground_col_mode; + /// Only valid in non-ragdoll, non-CustomReceiver mode. util::BitField<7, 1, WaterCollisionMode, u32> water_col_mode; - util::BitField<16, 10, u32> group_handler_index; /// If this flag is set, then this entity will always collide with ground or water, /// regardless of the configured GroundCollisionMode or WaterCollisionMode modes. - // TODO: is this "is_ragdoll"? See EntitySystemGroupHandler::makeCollisionFilterInfo. - util::BitField<30, 1, bool, u32> unk30; + util::BitField<30, 1, bool, u32> is_ragdoll; util::BitField<31, 1, bool, u32> is_ground_hit_mask; }; static_assert(sizeof(EntityCollisionMask) == sizeof(u32));