diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 8e9fae07..774860aa 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -82982,8 +82982,8 @@ Address,Quality,Size,Name 0x0000007100f8d7a8,O,000152,_ZNK4ksys4phys9RigidBody20resetLinkedRigidBodyEv 0x0000007100f8d840,U,001156,phys::RigidBody::x_8 0x0000007100f8dcc4,O,000056,_ZNK4ksys4phys9RigidBody13getMotionTypeEv -0x0000007100f8dcfc,U,001044,phys::RigidBody::x_9 -0x0000007100f8e110,U,000748,phys::RigidBody::x_10 +0x0000007100f8dcfc,O,001044,_ZN4ksys4phys9RigidBody19replaceMotionObjectEv +0x0000007100f8e110,O,000748,_ZN4ksys4phys9RigidBody4x_10Ev 0x0000007100f8e3fc,U,000816,phys::RigidBody::x_11 0x0000007100f8e72c,U,000136,phys::RigidBody::x_12 0x0000007100f8e7b4,O,000052,_ZN4ksys4phys9RigidBody16setContactPointsEPNS0_18RigidContactPointsE @@ -82995,18 +82995,18 @@ Address,Quality,Size,Name 0x0000007100f8ee38,O,000024,_ZN4ksys4phys9RigidBody16resetFrozenStateEv 0x0000007100f8ee50,U,000048,phys::RigidBody::x_17 0x0000007100f8ee80,O,000384,_ZN4ksys4phys9RigidBody27updateCollidableQualityTypeEb -0x0000007100f8f000,U,000012,phys::RigidBody::x_18 -0x0000007100f8f00c,U,000080,phys::RigidBody::x_19 -0x0000007100f8f05c,U,000080,phys::RigidBody::x_20 +0x0000007100f8f000,O,000012,_ZNK4ksys4phys9RigidBody13getCollidableEv +0x0000007100f8f00c,O,000080,_ZN4ksys4phys9RigidBody15addContactLayerENS0_12ContactLayerE +0x0000007100f8f05c,O,000080,_ZN4ksys4phys9RigidBody18removeContactLayerENS0_12ContactLayerE 0x0000007100f8f0ac,O,000008,_ZN4ksys4phys9RigidBody14setContactMaskEj 0x0000007100f8f0b4,O,000012,_ZN4ksys4phys9RigidBody13setContactAllEv 0x0000007100f8f0c0,O,000008,_ZN4ksys4phys9RigidBody14setContactNoneEv -0x0000007100f8f0c8,U,000176,phys::RigidBody::x_4 -0x0000007100f8f178,U,000064,phys::RigidBody::x_1 -0x0000007100f8f1b8,U,000012,phys::RigidBody::x_21 +0x0000007100f8f0c8,O,000176,_ZN4ksys4phys9RigidBody21enableGroundCollisionEb +0x0000007100f8f178,O,000064,_ZNK4ksys4phys9RigidBody15getContactLayerEv +0x0000007100f8f1b8,O,000012,_ZNK4ksys4phys9RigidBody22getCollisionFilterInfoEv 0x0000007100f8f1c4,U,000572,RigidBody::x_0 -0x0000007100f8f400,U,000172,phys::RigidBody::x_5 -0x0000007100f8f4ac,U,000048,phys::RigidBody::x_22 +0x0000007100f8f400,O,000172,_ZN4ksys4phys9RigidBody20enableWaterCollisionEb +0x0000007100f8f4ac,O,000048,_ZNK4ksys4phys9RigidBody23isWaterCollisionEnabledEv 0x0000007100f8f4dc,U,000064,phys::RigidBody::x_23 0x0000007100f8f51c,U,000104,phys::RigidBody::x_24 0x0000007100f8f584,U,000144,phys::RigidBody::x_25 diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index 29183b98..564c4196 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(hkStubs OBJECT Havok/Common/Base/Math/Quaternion/hkQuaternionf.h Havok/Common/Base/Math/SweptTransform/hkSweptTransform.h Havok/Common/Base/Math/SweptTransform/hkSweptTransformf.h + Havok/Common/Base/Math/SweptTransform/hkSweptTransformfUtil.h Havok/Common/Base/Math/Vector/hkSimdFloat32.h Havok/Common/Base/Math/Vector/hkSimdReal.h Havok/Common/Base/Math/Vector/hkVector4.h diff --git a/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformf.h b/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformf.h index d762ce67..88234aa2 100644 --- a/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformf.h +++ b/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformf.h @@ -6,9 +6,31 @@ class hkSweptTransformf { public: hkSweptTransformf() {} + HK_FORCE_INLINE hkTime getBaseTime() const; + HK_FORCE_INLINE hkSimdFloat32 getBaseTimeSr() const; + + HK_FORCE_INLINE hkFloat32 getInvDeltaTime() const; + HK_FORCE_INLINE hkSimdFloat32 getInvDeltaTimeSr() const; + hkVector4f m_centerOfMass0; hkVector4f m_centerOfMass1; hkQuaternionf m_rotation0; hkQuaternionf m_rotation1; hkVector4f m_centerOfMassLocal; }; + +inline hkTime hkSweptTransformf::getBaseTime() const { + return static_cast(m_centerOfMass0(3)); +} + +inline hkSimdFloat32 hkSweptTransformf::getBaseTimeSr() const { + return m_centerOfMass0.getComponent<3>(); +} + +inline hkFloat32 hkSweptTransformf::getInvDeltaTime() const { + return m_centerOfMass1(3); +} + +inline hkSimdFloat32 hkSweptTransformf::getInvDeltaTimeSr() const { + return m_centerOfMass1.getComponent<3>(); +} diff --git a/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformfUtil.h b/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformfUtil.h new file mode 100644 index 00000000..e2a2751d --- /dev/null +++ b/lib/hkStubs/Havok/Common/Base/Math/SweptTransform/hkSweptTransformfUtil.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +class hkMotionState; + +namespace hkSweptTransformUtil { + +void freezeMotionState(hkSimdFloat32Parameter time, hkMotionState& motionState); + +} // namespace hkSweptTransformUtil diff --git a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkSimdFloat32.h b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkSimdFloat32.h index ebb3a3eb..2f5fa6e8 100644 --- a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkSimdFloat32.h +++ b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkSimdFloat32.h @@ -9,7 +9,7 @@ #include #endif -using hkSimdFloat32Parameter = class hkSimdFloat32; +using hkSimdFloat32Parameter = const class hkSimdFloat32&; class hkSimdFloat32 { public: @@ -19,7 +19,8 @@ public: using Storage = __attribute__((vector_size(4 * sizeof(float)))) float; #endif - hkSimdFloat32() = default; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,modernize-use-equals-default) + hkSimdFloat32() {} // NOLINTNEXTLINE(google-explicit-constructor) hkSimdFloat32(const Storage& x) { m_real = x; } @@ -60,6 +61,11 @@ public: void setAbs(hkSimdFloat32Parameter x); + HK_FORCE_INLINE void setReciprocal(hkSimdFloat32Parameter a); + HK_FORCE_INLINE hkSimdFloat32 reciprocal() const; + + HK_FORCE_INLINE hkBool32 isEqualZero() const; + HK_FORCE_INLINE m128 toQuad() const; Storage m_real; @@ -153,6 +159,29 @@ inline void hkSimdFloat32::setAbs(hkSimdFloat32Parameter x) { #endif } +inline void hkSimdFloat32::setReciprocal(hkSimdFloat32Parameter a) { +#ifdef HK_SIMD_FLOAT32_AARCH64_NEON + auto r0 = vrecpe_f32(a.m_real); + auto r1 = vmul_f32(r0, vrecps_f32(a.m_real, r0)); + auto r2 = vmul_f32(r1, vrecps_f32(a.m_real, r1)); + m_real = r2; +#else + for (int i = 0; i < 4; ++i) + m_real[i] = 1.0f / a.m_real[i]; +#endif +} + +inline hkSimdFloat32 hkSimdFloat32::reciprocal() const { + hkSimdFloat32 r; + r.setReciprocal(*this); + return r; +} + +inline hkBool32 hkSimdFloat32::isEqualZero() const { + auto cmp = m_real == 0.0; + return cmp[0]; +} + inline m128 hkSimdFloat32::toQuad() const { #ifdef HK_SIMD_FLOAT32_AARCH64_NEON return vcombine_f32(m_real, m_real); diff --git a/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h b/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h index bb7b480c..60ee0e29 100644 --- a/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h +++ b/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h @@ -540,3 +540,7 @@ public: hkEnum m_contactPointGeneration; hkBool m_useCompoundSpuElf; }; + +inline hkpSolverInfo* hkpWorld::getSolverInfo() { + return &m_dynamicsStepInfo.m_solverInfo; +} diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp index dd832e3b..f5112ace 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp @@ -1,4 +1,5 @@ #include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include #include #include #include @@ -176,6 +177,10 @@ sead::SafeString RigidBody::getHkBodyName() const { return name; } +hkpCollidable* RigidBody::getCollidable() const { + return getHkBody()->getCollidableRw(); +} + // NON_MATCHING: ldr w8, [x20, #0x68] should be ldr w8, [x22] (equivalent) void RigidBody::x_0() { // debug code that survived because mFlags is atomic @@ -350,6 +355,111 @@ MotionType RigidBody::getMotionType() const { return mRigidBodyAccessor.getMotionType(); } +void RigidBody::replaceMotionObject() { + auto* motion = getMotion(); + const hkMotionState motion_state = *motion->getMotionState(); + const auto linvel = mHkBody->getLinearVelocity(); + const auto angvel = mHkBody->getAngularVelocity(); + const auto counter = motion->m_deactivationIntegrateCounter; + const auto frame0 = motion->m_deactivationNumInactiveFrames[0]; + const auto frame1 = motion->m_deactivationNumInactiveFrames[1]; + + if (mMotionFlags.isOn(MotionFlag::Fixed)) { + const auto position = motion->getPosition(); + const auto rotation = motion->getRotation(); + new (motion) hkpFixedRigidMotion(position, rotation); + + // Restore relevant motion state. + *motion->getMotionState() = motion_state; + mHkBody->m_solverData = 0; + mHkBody->setQualityType(HK_COLLIDABLE_QUALITY_FIXED); + + mMotionFlags.reset(MotionFlag::Fixed); + + motion->m_deactivationIntegrateCounter = counter; + motion->m_deactivationNumInactiveFrames[0] = frame0; + motion->m_deactivationNumInactiveFrames[1] = frame1; + + // Freeze the motion state. + const auto inv_delta = motion_state.getSweptTransform().getInvDeltaTimeSr(); + if (!inv_delta.isEqualZero()) { + hkSimdReal time; + if (auto* world = mHkBody->getWorld()) { + time = world->getCurrentTime(); + } else { + time = inv_delta.reciprocal() + motion_state.getSweptTransform().getBaseTimeSr(); + } + hkSweptTransformUtil::freezeMotionState(time, *motion->getMotionState()); + } + + } else if (mMotionFlags.isOn(MotionFlag::Keyframed)) { + const auto position = motion->getPosition(); + const auto rotation = motion->getRotation(); + new (getMotion()) hkpKeyframedRigidMotion(position, rotation); + + // Restore relevant motion state. + *motion->getMotionState() = motion_state; + motion->m_linearVelocity = linvel; + motion->m_angularVelocity = angvel; + mHkBody->m_solverData = 0; + motion->m_deactivationIntegrateCounter = counter; + motion->m_deactivationNumInactiveFrames[0] = frame0; + motion->m_deactivationNumInactiveFrames[1] = frame1; + const bool is_entity = isEntity(); + mHkBody->setQualityType(is_entity && hasFlag(Flag::HighQualityCollidable) ? + HK_COLLIDABLE_QUALITY_MOVING : + HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING); + mMotionFlags.reset(MotionFlag::Keyframed); + + } else if (mMotionFlags.isOn(MotionFlag::Dynamic)) { + getEntityMotionAccessor()->updateRigidBodyMotionExceptStateAndVel(); + mHkBody->setQualityType(hasFlag(RigidBody::Flag::HighQualityCollidable) ? + HK_COLLIDABLE_QUALITY_BULLET : + HK_COLLIDABLE_QUALITY_DEBRIS_SIMPLE_TOI); + mMotionFlags.reset(MotionFlag::Dynamic); + } + + mHkBody->getCollidableRw()->setMotionState(getMotion()->getMotionState()); + // XXX: what the heck? + mHkBody->getCollidableRw()->setMotionState(getMotion()->getMotionState()); + + if (auto* shape = mHkBody->getCollidable()->getShape()) { + hkVector4 extent_out; + mHkBody->updateCachedShapeInfo(shape, extent_out); + } + + if (auto* world = mHkBody->getWorld()) { + hkpSolverInfo* solver_info = world->getSolverInfo(); + getMotion()->setWorldSelectFlagsNeg( + solver_info->m_deactivationNumInactiveFramesSelectFlag[0], + solver_info->m_deactivationNumInactiveFramesSelectFlag[1], + solver_info->m_deactivationIntegrateCounter); + } +} + +void RigidBody::x_10() { + auto lock = makeScopedLock(isFlag8Set()); + + if (isEntity()) { + if (mMotionAccessor && + getEntityMotionAccessor()->hasFlag(RigidBodyMotionEntity::Flag::_2)) { + mFlags.reset(Flag::_20); + getEntityMotionAccessor()->deregisterAllAccessors(); + } + } else { // isSensor() + auto* accessor = getSensorMotionAccessor(); + if (accessor && accessor->getLinkedRigidBody() != nullptr) { + mFlags.reset(Flag::_20); + resetLinkedRigidBody(); + } + } + + mFlags.set(Flag::_20); + mFlags.set(Flag::_4); + + x_8(nullptr); +} + void RigidBody::setContactPoints(RigidContactPoints* points) { mContactPoints = points; if (isFlag8Set() && mContactPoints && !mContactPoints->isLinked()) @@ -442,6 +552,22 @@ void RigidBody::setCollidableQualityType(hkpCollidableQualityType quality) { getHkBody()->getCollidableRw()->setQualityType(quality); } +static int getLayerBit(int layer, ContactLayerType type) { + // This is layer for Entity layers and layer - 0x20 for Sensor layers. + // XXX: this should be using makeContactLayerMask. + return layer - ContactLayer::SensorObject * int(type); +} + +void RigidBody::addContactLayer(ContactLayer layer) { + assertLayerType(layer); + mContactMask.setBit(getLayerBit(layer, getLayerType())); +} + +void RigidBody::removeContactLayer(ContactLayer layer) { + assertLayerType(layer); + mContactMask.resetBit(getLayerBit(layer, getLayerType())); +} + void RigidBody::setContactMask(u32 value) { mContactMask.setDirect(value); } @@ -454,6 +580,73 @@ void RigidBody::setContactNone() { mContactMask.makeAllZero(); } +void RigidBody::enableGroundCollision(bool enabled) { + if (!isEntity() || isGroundCollisionEnabled() == enabled) + return; + + if (int(getContactLayer()) == ContactLayer::EntityRagdoll) + return; + + const auto current_info = getCollisionFilterInfo(); + auto info = current_info; + info.unk5 = false; + info.no_ground_collision.SetBit(!enabled); + if (current_info != info) + setCollisionFilterInfo(info.raw); +} + +bool RigidBody::isGroundCollisionEnabled() const { + if (!isEntity()) + return false; + + const auto info = getCollisionFilterInfo(); + + bool enabled = false; + enabled |= info.unk5; + enabled |= info.unk30; + enabled |= !info.no_ground_collision; + return enabled; +} + +void RigidBody::enableWaterCollision(bool enabled) { + if (!isEntity() || isWaterCollisionEnabled() == enabled) + return; + + if (int(getContactLayer()) == ContactLayer::EntityRagdoll) + return; + + const auto current_info = getCollisionFilterInfo(); + auto info = current_info; + info.no_water_collision = !enabled; + if (current_info != info) + setCollisionFilterInfo(info.raw); +} + +bool RigidBody::isWaterCollisionEnabled() const { + if (!isEntity()) + return false; + + const auto info = getCollisionFilterInfo(); + + bool enabled = false; + // unk30 enables all collisions? + enabled |= info.unk30; + enabled |= !info.no_water_collision; + return enabled; +} + +ContactLayer RigidBody::getContactLayer() const { + return getContactLayer(getCollisionFilterInfo()); +} + +ContactLayer RigidBody::getContactLayer(EntityCollisionFilterInfo info) const { + return isSensor() ? info.getLayerSensor() : info.getLayer(); +} + +EntityCollisionFilterInfo RigidBody::getCollisionFilterInfo() const { + return EntityCollisionFilterInfo(mHkBody->getCollisionFilterInfo()); +} + void RigidBody::setPosition(const sead::Vector3f& position, bool propagate_to_linked_motions) { if (isVectorInvalid(position)) { onInvalidParameter(); @@ -1137,6 +1330,12 @@ bool RigidBody::isEntityMotionFlag200On() const { return getEntityMotionAccessor()->hasFlag(RigidBodyMotionEntity::Flag::_200); } +void RigidBody::assertLayerType(ContactLayer layer) const { + const auto type = getContactLayerType(layer); + const auto expected_type = getLayerType(); + SEAD_ASSERT(type == expected_type); +} + void RigidBody::onInvalidParameter(int code) { sead::Vector3f pos, lin_vel, ang_vel; mRigidBodyAccessor.getPosition(&pos); diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index c1467df3..38b72156 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -15,6 +15,7 @@ enum hkpCollidableQualityType : int; class hkQuaternionf; class hkVector4f; +class hkpCollidable; class hkpRigidBody; class hkpMaxSizeMotion; class hkpMotion; @@ -130,6 +131,7 @@ public: const RigidBodyInstanceParam& param); sead::SafeString getHkBodyName() const; + hkpCollidable* getCollidable() const; void x_0(); @@ -139,7 +141,6 @@ public: bool isMotionFlag1Set() const; bool isMotionFlag2Set() const; void sub_7100F8D21C(); - // 0x0000007100f8d308 bool x_6(); /// Get the motion accessor if it is a RigidBodyMotionEntity. Returns nullptr otherwise. @@ -159,13 +160,11 @@ public: bool isSensorMotionFlag40000Set() const; // 0x0000007100f8d840 - void x_8(); + void x_8(void* arg); MotionType getMotionType() const; - // Motion functions - // 0x0000007100f8dcfc - void x_9(); + void replaceMotionObject(); // 0x0000007100f8e110 void x_10(); // 0x0000007100f8e3fc @@ -173,7 +172,6 @@ public: // 0x0000007100f8e72c void x_12(); - // 0x0000007100f8e7b4 void setContactPoints(RigidContactPoints* points); void freeze(bool should_freeze, bool preserve_velocities, bool preserve_max_impulse); @@ -183,13 +181,24 @@ public: void updateCollidableQualityType(bool high_quality); - u32 addContactLayer(ContactLayer); - u32 removeContactLayer(ContactLayer); + void addContactLayer(ContactLayer layer); + void removeContactLayer(ContactLayer layer); void setContactMask(u32); void setContactAll(); void setContactNone(); - void setCollideGround(bool); - void setCollideWater(bool); + + void enableGroundCollision(bool enabled); + bool isGroundCollisionEnabled() const; + + void enableWaterCollision(bool enabled); + bool isWaterCollisionEnabled() const; + + ContactLayer getContactLayer() const; + ContactLayer getContactLayer(EntityCollisionFilterInfo info) const; + EntityCollisionFilterInfo getCollisionFilterInfo() const; + // 0x0000007100f8f1c4 + void setCollisionFilterInfo(u32 info); + void sub_7100F8F51C(); void sub_7100F8F8CC(ContactLayer, GroundHit, void*); void sub_7100F8F9E8(ReceiverMask*, void*); @@ -379,6 +388,7 @@ public: private: void createMotionAccessor(sead::Heap* heap); + void assertLayerType(ContactLayer layer) const; void onInvalidParameter(int code = 0); void notifyUserTag(int code); void updateDeactivation(); diff --git a/src/KingSystem/Physics/System/physDefines.h b/src/KingSystem/Physics/System/physDefines.h index 96058c7c..e5bd72ba 100644 --- a/src/KingSystem/Physics/System/physDefines.h +++ b/src/KingSystem/Physics/System/physDefines.h @@ -189,6 +189,54 @@ union ReceiverMask { util::BitField<31, 1, u32> unk_flag; }; +union EntityCollisionFilterInfo { + union Data { + ContactLayer getLayer() const { return int(layer); } + ContactLayer getLayerSensor() const { return int(layer + ContactLayer::SensorObject); } + GroundHit getGroundHit() const { return int(ground_hit); } + + util::BitField<0, 5, u32> layer; + util::BitField<24, 1, u32> unk24; + util::BitField<25, 1, u32> unk25; + util::BitField<26, 4, u32> ground_hit; + }; + + union GroundHitMask { + ContactLayer getLayer() const { return int(layer); } + + util::BitField<0, 1, u32> unk; + util::BitField<8, 16, u32> ground_hit_types; + util::BitField<24, 1, u32> unk24; + util::BitField<25, 5, u32> layer; + }; + + explicit EntityCollisionFilterInfo(u32 raw_ = 0) : raw(raw_) {} + + bool operator==(EntityCollisionFilterInfo rhs) const { return raw == rhs.raw; } + bool operator!=(EntityCollisionFilterInfo rhs) const { return raw != rhs.raw; } + + ContactLayer getLayer() const { + return is_ground_hit_mask ? ground_hit.getLayer() : data.getLayer(); + } + + ContactLayer getLayerSensor() const { + return is_ground_hit_mask ? ContactLayer(ContactLayer::SensorCustomReceiver) : + data.getLayerSensor(); + } + + u32 raw; + Data data; + GroundHitMask ground_hit; + util::BitField<5, 1, bool, u32> unk5; + /// Whether ground collision is disabled. + util::BitField<6, 1, bool, u32> no_ground_collision; + /// Whether water collision is disabled. + util::BitField<7, 1, bool, u32> no_water_collision; + util::BitField<30, 1, bool, u32> unk30; + util::BitField<31, 1, bool, u32> is_ground_hit_mask; +}; +static_assert(sizeof(EntityCollisionFilterInfo) == sizeof(u32)); + ContactLayerType getContactLayerType(ContactLayer layer); u32 makeContactLayerMask(ContactLayer layer); u32 getContactLayerBase(ContactLayerType type); diff --git a/src/KingSystem/Physics/System/physEntityGroupFilter.cpp b/src/KingSystem/Physics/System/physEntityGroupFilter.cpp index e6879ca0..b048bd62 100644 --- a/src/KingSystem/Physics/System/physEntityGroupFilter.cpp +++ b/src/KingSystem/Physics/System/physEntityGroupFilter.cpp @@ -17,42 +17,6 @@ namespace ksys::phys { constexpr int NumEntityHandlersInList0 = 0x10; constexpr int NumEntityHandlers = 0x400; -namespace { - -/// Internal representation of collision masks for entities. -/// This is exposed as a u32 externally. -union EntityCollisionFilterInfo { - union Data { - ContactLayer getLayer() const { return int(layer); } - GroundHit getGroundHit() const { return int(ground_hit); } - - util::BitField<0, 5, u32> layer; - util::BitField<24, 1, u32> unk24; - util::BitField<25, 1, u32> unk25; - util::BitField<26, 4, u32> ground_hit; - util::BitField<30, 1, u32> unk30; - }; - - union GroundHitMask { - ContactLayer getLayer() const { return int(layer); } - - util::BitField<0, 8, u32> unk; - util::BitField<8, 16, u32> ground_hit_types; - util::BitField<24, 1, u32> unk24; - util::BitField<25, 5, u32> layer; - }; - - explicit EntityCollisionFilterInfo(u32 raw_ = 0) : raw(raw_) {} - - u32 raw; - Data data; - GroundHitMask ground_hit; - util::BitField<31, 1, u32> is_ground_hit_mask; -}; -static_assert(sizeof(EntityCollisionFilterInfo) == sizeof(u32)); - -} // namespace - void receiverMaskEnableLayer(ReceiverMask* mask, ContactLayer layer) { mask->raw |= 1 << getContactLayerBaseRelativeValue(layer); } diff --git a/src/KingSystem/Physics/System/physInstanceSet.cpp b/src/KingSystem/Physics/System/physInstanceSet.cpp index 932bcb29..01e568c7 100644 --- a/src/KingSystem/Physics/System/physInstanceSet.cpp +++ b/src/KingSystem/Physics/System/physInstanceSet.cpp @@ -136,8 +136,8 @@ void InstanceSet::sub_7100FBB00C(phys::RigidBody* body, phys::RigidBodyParam* pa body->sub_7100F8F8CC(instance_params.contact_layer, instance_params.groundhit, _188[body->isSensor()]); } - body->setCollideGround(instance_params.no_hit_ground == 0); - body->setCollideWater(instance_params.no_hit_water == 0); + body->enableGroundCollision(instance_params.no_hit_ground == 0); + body->enableWaterCollision(instance_params.no_hit_water == 0); body->sub_7100F8F51C(); } diff --git a/src/KingSystem/Utils/BitField.h b/src/KingSystem/Utils/BitField.h index 4e28e675..315817fc 100644 --- a/src/KingSystem/Utils/BitField.h +++ b/src/KingSystem/Utils/BitField.h @@ -130,6 +130,12 @@ struct BitField { (storage & ~GetMask()) | ((static_cast(val) << position) & GetMask()); } + template > + inline constexpr void SetBit(bool set) { + const auto mask = set ? ((static_cast(1) << position) & GetMask()) : 0; + storage = (storage & ~GetMask()) | mask; + } + /// @warning This does *not* check whether the value fits within the mask, /// so this might overwrite unrelated fields! Using Set() is preferred. inline constexpr void SetUnsafe(T val) {