From 0c3ee0dd841026ca5221f5f3493c0a86d5030437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 12 Feb 2022 17:31:54 +0100 Subject: [PATCH] ksys/phys: Finish RigidBodyFromShape --- data/uking_functions.csv | 18 +- .../Shape/Sphere/physSphereRigidBody.h | 18 ++ .../Physics/RigidBody/physRigidBody.h | 4 +- .../RigidBody/physRigidBodyFactory.cpp | 2 +- .../RigidBody/physRigidBodyFromShape.cpp | 167 ++++++++++++++++++ .../RigidBody/physRigidBodyFromShape.h | 9 +- .../Physics/RigidBody/physRigidBodyParam.h | 6 +- 7 files changed, 207 insertions(+), 17 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 0fa25dd2..f3d665f8 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83312,19 +83312,19 @@ Address,Quality,Size,Name 0x0000007100f9ccd0,O,000104,_ZThn32_N4ksys4phys18RigidBodyFromShapeD1Ev 0x0000007100f9cd38,O,000108,_ZN4ksys4phys18RigidBodyFromShapeD0Ev 0x0000007100f9cda4,O,000112,_ZThn32_N4ksys4phys18RigidBodyFromShapeD0Ev -0x0000007100f9ce14,U,000948, +0x0000007100f9ce14,O,000948,_ZNK4ksys4phys18RigidBodyFromShape18tryGetMaterialMaskEv 0x0000007100f9d1c8,O,000036,_ZN4ksys4phys18RigidBodyFromShape17getNewHavokShape_Ev 0x0000007100f9d1ec,O,000244,_ZN4ksys4phys18RigidBodyFromShape12updateScale_Eff 0x0000007100f9d2e0,O,000204,_ZNK4ksys4phys18RigidBodyFromShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f9d3ac,O,000092,_ZNK4ksys4phys18RigidBodyFromShape18getRuntimeTypeInfoEv -0x0000007100f9d408,U,000904, -0x0000007100f9d790,U,000904, -0x0000007100f9db18,U,000904, -0x0000007100f9dea0,U,000904, -0x0000007100f9e228,U,000904, -0x0000007100f9e5b0,U,000904, -0x0000007100f9e938,U,000904, -0x0000007100f9ecc0,U,000904, +0x0000007100f9d408,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_15SphereRigidBodyENS0_11SphereShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9d790,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_16CapsuleRigidBodyENS0_12CapsuleShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9db18,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_17CylinderRigidBodyENS0_13CylinderShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9dea0,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_22CylinderWaterRigidBodyENS0_18CylinderWaterShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9e228,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_12BoxRigidBodyENS0_8BoxShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9e5b0,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_17BoxWaterRigidBodyENS0_13BoxWaterShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9e938,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_17PolytopeRigidBodyENS0_13PolytopeShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100f9ecc0,O,000904,_ZN4ksys4phys18RigidBodyFromShape4makeINS0_18ListShapeRigidBodyENS0_9ListShapeEEEPT_PT0_bRKNS0_22RigidBodyInstanceParamEPN4sead4HeapE 0x0000007100f9f048,U,000204, 0x0000007100f9f114,U,000092, 0x0000007100f9f170,O,000064,_ZN4ksys4phys14RigidBodyParamC1Ev diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h index 63deed17..4b4b0eab 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h @@ -4,10 +4,28 @@ namespace ksys::phys { +class SphereShape; + class SphereRigidBody : public RigidBodyFromShape { SEAD_RTTI_OVERRIDE(SphereRigidBody, RigidBodyFromShape) public: static SphereRigidBody* make(RigidBodyInstanceParam* param, sead::Heap* heap); + + SphereRigidBody(hkpRigidBody* hk_body, SphereShape* shape, ContactLayerType layer_type, + const sead::SafeString& name, bool set_flag_10, sead::Heap* heap); + ~SphereRigidBody() override; + + const MaterialMask& getMaterialMask() const; + + float getVolume() override; + +protected: + Shape* getShape_() override; + const Shape* getShape_() const override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + +private: + SphereShape* mShape{}; }; } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index 7c4f27dd..cdf99692 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -90,7 +90,7 @@ public: _2000000 = 1 << 25, _4000000 = 1 << 26, _8000000 = 1 << 27, - _10000000 = 1 << 28, + NoCharStandingOn = 1 << 28, _20000000 = 1 << 29, _40000000 = 1 << 30, _80000000 = 1 << 31, @@ -549,6 +549,8 @@ public: void setFlag400000(bool set) { mFlags.change(Flag::_400000, set); } // Internal. void setUpdateRequestedFlag() { mFlags.set(Flag::UpdateRequested); } + // Internal. + void setFlag20() { mFlags.set(Flag::_20); } // Internal. void onCollisionAdded() { diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp index 0e98c947..f598c51c 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp @@ -21,7 +21,7 @@ static RigidBodyType* createRigidBody(RigidBodyInstanceParam* param, sead::Heap* auto* v = sead::DynamicCast(param); auto* shape = ShapeType::make(v->shape, heap); - return RigidBodyFromShape::make(*shape, true, *param, heap); + return RigidBodyFromShape::make(shape, true, *param, heap); } SphereRigidBody* RigidBodyFactory::createSphere(RigidBodyInstanceParam* params, sead::Heap* heap) { diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp index 5e0e297b..4e387eaf 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp @@ -1,6 +1,27 @@ #include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" #include +#include +#include +#include "KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h" +#include "KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterShape.h" +#include "KingSystem/Physics/RigidBody/Shape/List/physListShape.h" +#include "KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" #include "KingSystem/Physics/RigidBody/Shape/physShape.h" +#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" +#include "KingSystem/Physics/System/physDefines.h" +#include "KingSystem/Physics/physConversions.h" +#include "KingSystem/Utils/HeapUtil.h" namespace ksys::phys { @@ -18,6 +39,32 @@ RigidBodyFromShape::~RigidBodyFromShape() { operator delete(mHkBody); } +const MaterialMask* RigidBodyFromShape::tryGetMaterialMask() const { + switch (getShape_()->getType()) { + case ShapeType::Sphere: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::Capsule: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::Box: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::Cylinder: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::Polytope: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::List: + return &sead::DynamicCast(this)->getMaterialMask(0); + case ShapeType::BoxWater: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::CylinderWater: + return &sead::DynamicCast(this)->getMaterialMask(); + case ShapeType::CharacterPrism: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } + return &sead::DynamicCast(this)->getMaterialMask(); +} + const hkpShape* RigidBodyFromShape::getNewHavokShape_() { return getShape_()->updateHavokShape(); } @@ -45,4 +92,124 @@ float RigidBodyFromShape::updateScale_(float scale, float old_scale) { return scale; } +template +RigidBodyT* RigidBodyFromShape::make(ShapeT* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, sead::Heap* heap) { + const auto layer_type = getContactLayerType(param.contact_layer); + + hkMatrix3 inertia_mtx; + const auto inertia = toHkVec4(param.inertia); + inertia_mtx.m_col0.setMul(inertia, hkVector4f::getConstant()); + inertia_mtx.m_col1.setMul(inertia, hkVector4f::getConstant()); + inertia_mtx.m_col2.setMul(inertia, hkVector4f::getConstant()); + + // Set up construction info for the Havok rigid body. + hkpRigidBodyCinfo cinfo; + cinfo.m_shape = shape->getHavokShapeConst(); + cinfo.m_centerOfMass = toHkVec4(param.center_of_mass); + cinfo.m_mass = param.mass; + cinfo.m_inertiaTensor = inertia_mtx; + cinfo.m_linearDamping = param.linear_damping; + cinfo.m_angularDamping = param.angular_damping; + cinfo.m_gravityFactor = param.gravity_factor; + cinfo.m_timeFactor = param.time_factor; + cinfo.m_maxLinearVelocity = param.max_linear_velocity; + cinfo.m_maxAngularVelocity = param.max_angular_velocity_rad; + cinfo.m_enableDeactivation = param.enable_deactivation; + cinfo.m_numShapeKeysInContactPointProperties = -1; + + switch (param.motion_type) { + case MotionType::Dynamic: + cinfo.m_motionType = hkpMotion::MOTION_DYNAMIC; + break; + case MotionType::Fixed: + cinfo.m_motionType = hkpMotion::MOTION_FIXED; + break; + case MotionType::Keyframed: + cinfo.m_motionType = hkpMotion::MOTION_KEYFRAMED; + break; + case MotionType::Unknown: + case MotionType::Invalid: + break; + } + + void* hk_body_storage = util::allocStorage(heap); + if (!hk_body_storage) + return nullptr; + + auto* hk_body = new (hk_body_storage) hkpRigidBody(cinfo); + + RigidBodyFromShape* body = + new (heap) RigidBodyT(hk_body, shape, layer_type, param.name, set_flag_10, heap); + + body->mFlags.set(Flag::UpdateRequested); + + if (param.motion_type == MotionType::Keyframed) { + hk_body->setCenterOfMassLocal(cinfo.m_centerOfMass); + hk_body->setMaxLinearVelocity(cinfo.m_maxLinearVelocity); + hk_body->setMaxAngularVelocity(cinfo.m_maxAngularVelocity); + } + + if (param._90) { + body->setFlag20(); + } else if (!body->initMotionAccessor(param, heap, false)) { + delete body; + return nullptr; + } + + if (param.contact_layer == ContactLayer::SensorCustomReceiver) { + body->setSensorCustomReceiver(param.receiver_mask, param.system_group_handler); + } else if (param.groundhit_mask != 0) { + body->setGroundHitMask(param.contact_layer, param.groundhit_mask); + } else { + body->setContactLayerAndGroundHitAndHandler(param.contact_layer, param.groundhit, + param.system_group_handler); + } + + body->updateCollidableQualityType(param.toi); + body->updateShape(); + body->clearEntityMotionFlag20(!param.ignore_normal_for_impulse); + body->enableGroundCollision(!param.no_hit_ground); + body->enableWaterCollision(!param.no_hit_water); + body->mFlags.change(Flag::NoCharStandingOn, param.no_char_standing_on); + body->setContactMask(param.contact_mask); + body->setEntityMotionFlag1(param.always_character_mass_scaling); + body->processUpdateRequests(nullptr, nullptr); + + return static_cast(body); +} + +template SphereRigidBody* RigidBodyFromShape::make(SphereShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template CapsuleRigidBody* RigidBodyFromShape::make(CapsuleShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template CylinderRigidBody* RigidBodyFromShape::make(CylinderShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template CylinderWaterRigidBody* RigidBodyFromShape::make(CylinderWaterShape* shape, + bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template BoxRigidBody* RigidBodyFromShape::make(BoxShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template BoxWaterRigidBody* RigidBodyFromShape::make(BoxWaterShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template PolytopeRigidBody* RigidBodyFromShape::make(PolytopeShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + +template ListShapeRigidBody* RigidBodyFromShape::make(ListShape* shape, bool set_flag_10, + const RigidBodyInstanceParam& param, + sead::Heap* heap); + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.h b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.h index 2d3cacb1..2ea94cbd 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.h @@ -10,10 +10,11 @@ class Shape; class RigidBodyFromShape : public RigidBody { SEAD_RTTI_OVERRIDE(RigidBodyFromShape, RigidBody) public: - // TODO - template - static RigidBodyType* make(const ShapeType& shape, bool set_flag_10, - const RigidBodyInstanceParam& param, sead::Heap* heap); + /// Create a RigidBodyFromShape with the specified shape and rigid body parameters. + /// @param shape Must not be null. + template + static RigidBodyT* make(ShapeT* shape, bool set_flag_10, const RigidBodyInstanceParam& param, + sead::Heap* heap); RigidBodyFromShape(hkpRigidBody* hkp_rigid_body, ContactLayerType layer_type, const sead::SafeString& name, bool set_flag_10, sead::Heap* heap); diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h b/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h index 46638668..c253d5db 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h @@ -10,6 +10,8 @@ namespace ksys::phys { +class SystemGroupHandler; + // TODO: maybe move this to NavMesh/? enum class NavMeshType { NOT_USE, @@ -68,10 +70,10 @@ public: float water_buoyancy_scale = 1.0f; float water_flow_effective_rate = 1.0f; float magne_mass_scaling_factor = 1.0f; - bool gap68 = true; + bool enable_deactivation = true; bool toi = false; bool always_character_mass_scaling = false; - void* p = nullptr; + SystemGroupHandler* system_group_handler = nullptr; ContactLayer contact_layer = ContactLayer::EntityObject; GroundHit groundhit = GroundHit::HitAll; u32 groundhit_mask = 0;