From bc66305e3d8c537f446dde96d607e63f5e4d3f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 12 Feb 2022 12:06:43 +0100 Subject: [PATCH] ksys/phys: Add ListShape --- data/uking_functions.csv | 42 +-- .../Common/Base/Container/Array/hkArray.h | 3 + src/KingSystem/Physics/CMakeLists.txt | 5 + .../RigidBody/Shape/Box/physBoxShape.cpp | 2 +- .../RigidBody/Shape/Box/physBoxShape.h | 1 + .../Shape/Capsule/physCapsuleShape.h | 1 + .../CharacterPrism/physCharacterPrismShape.h | 10 + .../RigidBody/Shape/List/physListShape.cpp | 260 ++++++++++++++++++ .../RigidBody/Shape/List/physListShape.h | 107 +++++++ .../Shape/List/physListShapeRigidBody.cpp | 1 + .../Shape/List/physListShapeRigidBody.h | 13 + .../Shape/Polytope/physPolytopeShape.cpp | 12 +- .../RigidBody/Shape/Sphere/physSphereShape.h | 8 + .../Physics/RigidBody/Shape/physShape.h | 8 + src/KingSystem/Physics/physHeapUtil.h | 21 ++ 15 files changed, 463 insertions(+), 31 deletions(-) create mode 100644 src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp create mode 100644 src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h create mode 100644 src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp create mode 100644 src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h create mode 100644 src/KingSystem/Physics/physHeapUtil.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 34ee9c0b..0ea66e7b 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83603,27 +83603,27 @@ Address,Quality,Size,Name 0x0000007100fabf40,O,000204,_ZNK4ksys4phys12CapsuleShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100fac00c,O,000092,_ZNK4ksys4phys12CapsuleShape18getRuntimeTypeInfoEv 0x0000007100fac068,O,000008,_ZNK4ksys4phys12CapsuleShape7getTypeEv -0x0000007100fac070,U,000420, -0x0000007100fac214,U,000192, -0x0000007100fac2d4,U,000884, -0x0000007100fac648,U,000316, -0x0000007100fac784,U,000036, -0x0000007100fac7a8,U,000156, -0x0000007100fac844,U,000156, -0x0000007100fac8e0,U,000156, -0x0000007100fac97c,U,000156, -0x0000007100faca18,U,000156, -0x0000007100facab4,U,000156, -0x0000007100facb50,U,001052, -0x0000007100facf6c,U,001044, -0x0000007100fad380,U,000152, -0x0000007100fad418,U,000008, -0x0000007100fad420,U,000008, -0x0000007100fad428,U,000796, -0x0000007100fad744,U,000160, -0x0000007100fad7e4,U,000204, -0x0000007100fad8b0,U,000092, -0x0000007100fad90c,U,000008, +0x0000007100fac070,O,000420,_ZN4ksys4phys9ListShape4makeERKNS0_14ListShapeParamEPN4sead4HeapE +0x0000007100fac214,O,000192,_ZNK4ksys4phys9ListShape5cloneEPN4sead4HeapE +0x0000007100fac2d4,O,000884,_ZN4ksys4phys9ListShape16replaceWithCloneEiPKNS0_5ShapeEPN4sead4HeapE +0x0000007100fac648,O,000316,_ZN4ksys4phys9ListShapeD1Ev +0x0000007100fac784,O,000036,_ZN4ksys4phys9ListShapeD0Ev +0x0000007100fac7a8,O,000156,_ZN4ksys4phys9ListShape20replaceWithNewSphereEiRKNS0_16SphereShapeParamEPN4sead4HeapE +0x0000007100fac844,O,000156,_ZN4ksys4phys9ListShape21replaceWithNewCapsuleEiRKNS0_17CapsuleShapeParamEPN4sead4HeapE +0x0000007100fac8e0,O,000156,_ZN4ksys4phys9ListShape22replaceWithNewCylinderEiRKNS0_18CylinderShapeParamEPN4sead4HeapE +0x0000007100fac97c,O,000156,_ZN4ksys4phys9ListShape17replaceWithNewBoxEiRKNS0_13BoxShapeParamEPN4sead4HeapE +0x0000007100faca18,O,000156,_ZN4ksys4phys9ListShape22replaceWithNewPolytopeEiRKNS0_18PolytopeShapeParamEPN4sead4HeapE +0x0000007100facab4,O,000156,_ZN4ksys4phys9ListShape28replaceWithNewCharacterPrismEiRKNS0_24CharacterPrismShapeParamEPN4sead4HeapE +0x0000007100facb50,O,001052,_ZN4ksys4phys9ListShape15setMaterialMaskERKNS0_12MaterialMaskEi +0x0000007100facf6c,O,001044,_ZNK4ksys4phys9ListShape15getMaterialMaskEi +0x0000007100fad380,O,000152,_ZNK4ksys4phys9ListShape9getVolumeEv +0x0000007100fad418,O,000008,_ZN4ksys4phys9ListShape13getHavokShapeEv +0x0000007100fad420,O,000008,_ZNK4ksys4phys9ListShape13getHavokShapeEv +0x0000007100fad428,O,000796,_ZN4ksys4phys9ListShape16updateHavokShapeEv +0x0000007100fad744,O,000160,_ZN4ksys4phys9ListShape8setScaleEf +0x0000007100fad7e4,O,000204,_ZNK4ksys4phys9ListShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fad8b0,O,000092,_ZNK4ksys4phys9ListShape18getRuntimeTypeInfoEv +0x0000007100fad90c,O,000008,_ZNK4ksys4phys9ListShape7getTypeEv 0x0000007100fad914,O,000344,_ZN4ksys4phys13CylinderShape4makeERKNS0_18CylinderShapeParamEPN4sead4HeapE 0x0000007100fada6c,O,000032,_ZN4ksys4phys13CylinderShape15setMaterialMaskERKNS0_12MaterialMaskE 0x0000007100fada8c,O,000064,_ZN4ksys4phys13CylinderShapeD1Ev diff --git a/lib/hkStubs/Havok/Common/Base/Container/Array/hkArray.h b/lib/hkStubs/Havok/Common/Base/Container/Array/hkArray.h index 554a5f81..3a56e09b 100644 --- a/lib/hkStubs/Havok/Common/Base/Container/Array/hkArray.h +++ b/lib/hkStubs/Havok/Common/Base/Container/Array/hkArray.h @@ -34,6 +34,9 @@ public: HK_FORCE_INLINE int getCapacityAndFlags() const; HK_FORCE_INLINE hkBool isEmpty() const; + HK_FORCE_INLINE T* data() { return m_data; } + HK_FORCE_INLINE const T* data() const { return m_data; } + HK_FORCE_INLINE T& operator[](int i); HK_FORCE_INLINE const T& operator[](int i) const; diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 65cbc4b5..268622b4 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -64,6 +64,10 @@ target_sources(uking PRIVATE RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h RigidBody/Shape/CylinderWater/physCylinderWaterShape.cpp RigidBody/Shape/CylinderWater/physCylinderWaterShape.h + RigidBody/Shape/List/physListShape.cpp + RigidBody/Shape/List/physListShape.h + RigidBody/Shape/List/physListShapeRigidBody.cpp + RigidBody/Shape/List/physListShapeRigidBody.h RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp RigidBody/Shape/Polytope/physPolytopeRigidBody.h RigidBody/Shape/Polytope/physPolytopeShape.cpp @@ -133,4 +137,5 @@ target_sources(uking PRIVATE System/physUserTag.h physConversions.h + physHeapUtil.h ) diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp index e03df7ed..1226372b 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp @@ -145,7 +145,7 @@ const hkpShape* BoxShape::updateHavokShape() { if (mFlags.isOn(Flag::DirtyTransform)) { mFlags.reset(Flag::DirtyTransform); - return std::as_const(*this).getHavokShape(); + return getHavokShapeConst(); } return nullptr; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h index 561454ee..9c8497dd 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h @@ -42,6 +42,7 @@ public: bool setExtents(const sead::Vector3f& extents); bool setTranslate(const sead::Vector3f& translate); void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return mMaterialMask; } ShapeType getType() const override { return ShapeType::Box; } float getVolume() const override; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h index 375e480d..04cf1d3a 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h @@ -50,6 +50,7 @@ public: bool setVertices(const sead::Vector3f& va, const sead::Vector3f& vb); void transformVertices(sead::Vector3f* veca, sead::Vector3f* vecb, const hkTransformf& rb_vec); void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return material_mask; } sead::Vector3f vertex_a; sead::TypedBitFlag> flags{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h index 737026cf..2d528659 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h @@ -12,4 +12,14 @@ struct CharacterPrismShapeParam { CommonShapeParam common; }; +class CharacterPrismShape : public Shape { + SEAD_RTTI_OVERRIDE(CharacterPrismShape, Shape) +public: + static CharacterPrismShape* make(const CharacterPrismShapeParam& param, sead::Heap* heap); + CharacterPrismShape* clone(sead::Heap* heap) const; + + void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const; +}; + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp new file mode 100644 index 00000000..fbffbb46 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp @@ -0,0 +1,260 @@ +#include "KingSystem/Physics/RigidBody/Shape/List/physListShape.h" +#include +#include +#include +#include +#include "KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h" +#include "KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" +#include "KingSystem/Physics/physHeapUtil.h" + +namespace ksys::phys { + +ListShape* ListShape::make(const ListShapeParam& param, sead::Heap* heap) { + auto* sphere = new hkpSphereShape(1.0); + if (!sphere) + return nullptr; + + auto shapes = sead::toArray({sphere}); + auto* list_shape = new hkpListShape(shapes.getBufferPtr(), shapes.size()); + sphere->removeReference(); + + if (!list_shape) + return nullptr; + + return new (heap) ListShape(param, list_shape, heap); +} + +ListShape* ListShape::clone(sead::Heap* heap) const { + ListShapeParam param; + param.num_shapes = static_cast(mShapes.size()); + + auto* cloned = make(param, heap); + if (!cloned) + return nullptr; + + for (int i = 0, n = mShapes.size(); i < n; ++i) + cloned->replaceWithClone(i, mShapes[i], heap); + + return cloned; +} + +ListShape::ListShape(const ListShapeParam& param, hkpListShape* shape, sead::Heap* heap) + : mHavokShape(shape) { + mShapes.allocBufferAssert(param.num_shapes, heap); + for (int i = 0; i < int(param.num_shapes); ++i) + mShapes[i] = nullptr; +} + +ListShape::~ListShape() { + deleteRefCountedHavokObject(mHavokShape); + + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) { + delete mShapes[i]; + mShapes[i] = nullptr; + } + } + + mShapes.freeBuffer(); +} + +Shape* ListShape::replaceWithClone(int index, const Shape* shape_to_clone, sead::Heap* heap) { + delete mShapes[index]; + + switch (shape_to_clone->getType()) { + case ShapeType::Sphere: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::Capsule: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::Box: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::Cylinder: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::Polytope: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::CharacterPrism: + mShapes[index] = sead::DynamicCast(shape_to_clone)->clone(heap); + break; + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } + + mFlags.set(Flag::NeedsHavokShapeUpdate); + return mShapes[index]; +} + +Shape* ListShape::replaceWithNewSphere(int index, const SphereShapeParam& param, sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +Shape* ListShape::replaceWithNewCapsule(int index, const CapsuleShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +Shape* ListShape::replaceWithNewCylinder(int index, const CylinderShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +Shape* ListShape::replaceWithNewBox(int index, const BoxShapeParam& param, sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +Shape* ListShape::replaceWithNewPolytope(int index, const PolytopeShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +Shape* ListShape::replaceWithNewCharacterPrism(int index, const CharacterPrismShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape(index, param, heap); +} + +void ListShape::setMaterialMask(const MaterialMask& mask, int index) { + switch (mShapes[index]->getType()) { + case ShapeType::Sphere: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Capsule: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Box: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Cylinder: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Polytope: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::CharacterPrism: + sead::DynamicCast(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } +} + +const MaterialMask& ListShape::getMaterialMask(int index) const { + if (index >= mShapes.size()) + index = 0; + + switch (mShapes[index]->getType()) { + case ShapeType::Sphere: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::Capsule: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::Box: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::Cylinder: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::Polytope: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::CharacterPrism: + return sead::DynamicCast(mShapes[index])->getMaterialMask(); + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } + return sead::DynamicCast(mShapes[index])->getMaterialMask(); +} + +float ListShape::getVolume() const { + float volume = 0.0; + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) + volume += mShapes[i]->getVolume(); + } + return volume; +} + +hkpShape* ListShape::getHavokShape() { + return mHavokShape; +} + +const hkpShape* ListShape::getHavokShape() const { + return mHavokShape; +} + +const hkpShape* ListShape::updateHavokShape() { + bool updated = false; + + if (mFlags.isOn(Flag::NeedsHavokShapeUpdate)) { + hkArray havok_shapes; + int num_shapes = 0; + + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (!mShapes[i]) + continue; + + const hkpShape* havok_shape = mShapes[i]->updateHavokShape(); + if (havok_shape) { + // If one of the shapes was recreated, then we need to recreate the list shape. + havok_shapes.pushBack(havok_shape); + updated = true; + } else { + havok_shape = mShapes[i]->getHavokShapeConst(); + havok_shapes.pushBack(havok_shape); + + // Otherwise, we only need to recreate the list shape if the list has changed. + if (!updated && mHavokShape->m_childInfo.getSize() > num_shapes && + mHavokShape->getChildShapeInl(num_shapes) != havok_shapes[num_shapes]) { + updated = true; + } + } + + ++num_shapes; + } + + if (updated) { + const auto collision_filter_info = + mHavokShape->getCollisionFilterInfo(mHavokShape->getFirstKey()); + + mHavokShape->removeReference(); + mHavokShape = new hkpListShape(havok_shapes.data(), num_shapes); + + for (auto key = mHavokShape->getFirstKey(); key != HK_INVALID_SHAPE_KEY; + key = mHavokShape->getNextKey(key)) { + mHavokShape->setCollisionFilterInfo(key, collision_filter_info); + } + } else { + mHavokShape->recalcAabbExtents(); + } + + mFlags.reset(Flag::NeedsHavokShapeUpdate); + } + + return updated ? mHavokShape : nullptr; +} + +void ListShape::setScale(float scale) { + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) + mShapes[i]->setScale(scale); + } + + mFlags.set(Flag::NeedsHavokShapeUpdate); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h new file mode 100644 index 00000000..eb66a258 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Physics/RigidBody/Shape/physShape.h" +#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" + +class hkpListShape; + +namespace ksys::phys { + +struct BoxShapeParam; +struct CapsuleShapeParam; +struct CharacterPrismShapeParam; +struct CylinderShapeParam; +struct PolytopeShapeParam; +struct SphereShapeParam; + +class MaterialMask; + +struct ListShapeParam { + u8 num_shapes = 1; +}; + +class ListShape : public Shape { + SEAD_RTTI_OVERRIDE(ListShape, Shape) +public: + static ListShape* make(const ListShapeParam& param, sead::Heap* heap); + ListShape* clone(sead::Heap* heap) const; + + ListShape(const ListShapeParam& param, hkpListShape* shape, sead::Heap* heap); + ~ListShape() override; + + /// Replace the shape at the specified index with a clone of `shape_to_clone`. + /// The shape that is being replaced will be deleted. + /// @return the cloned heap + Shape* replaceWithClone(int index, const Shape* shape_to_clone, sead::Heap* heap); + + /// Replace the shape at the specified index with a new sphere shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewSphere(int index, const SphereShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new capsule shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCapsule(int index, const CapsuleShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new cylinder shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCylinder(int index, const CylinderShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new box shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewBox(int index, const BoxShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new polytope shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewPolytope(int index, const PolytopeShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new character prism. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCharacterPrism(int index, const CharacterPrismShapeParam& param, + sead::Heap* heap); + + /// Set the material mask for the shape at the specified index. + void setMaterialMask(const MaterialMask& mask, int index); + + /// Get the material mask for the shape at the specified index. + const MaterialMask& getMaterialMask(int index) const; + + ShapeType getType() const override { return ShapeType::List; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + void setScale(float scale) override; + +private: + enum class Flag { + /// Whether the Havok list shape needs to be recreated. + NeedsHavokShapeUpdate = 1 << 0, + }; + + template + Shape* replaceWithNewShape(int index, const ParamType& param, sead::Heap* heap) { + delete mShapes[index]; + auto* shape = T::make(param, heap); + mShapes[index] = shape; + mFlags.set(Flag::NeedsHavokShapeUpdate); + return shape; + } + + /// Child shapes. These are owned by this class. + sead::Buffer mShapes; + /// The Havok list shape. This is owned by this class. + hkpListShape* mHavokShape{}; + sead::TypedBitFlag> mFlags{Flag::NeedsHavokShapeUpdate}; +}; + +class ListShapeRigidBodyParam : public RigidBodyInstanceParam { + SEAD_RTTI_OVERRIDE(ListShapeRigidBodyParam, RigidBodyInstanceParam) +public: + u8 _90; + ListShapeParam shape; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp new file mode 100644 index 00000000..8dff51a3 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp @@ -0,0 +1 @@ +#include "KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h" diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h new file mode 100644 index 00000000..6b61a7d4 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h @@ -0,0 +1,13 @@ +#pragma once + +#include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" + +namespace ksys::phys { + +class ListShapeRigidBody : public RigidBodyFromShape { + SEAD_RTTI_OVERRIDE(ListShapeRigidBody, RigidBodyFromShape) +public: + static ListShapeRigidBody* make(RigidBodyInstanceParam* param, sead::Heap* heap); +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp index 9ac2f120..8ce7f93d 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp @@ -4,6 +4,7 @@ #include #include #include +#include "KingSystem/Physics/physHeapUtil.h" #include "KingSystem/Utils/HeapUtil.h" #include "KingSystem/Utils/SafeDelete.h" @@ -71,14 +72,7 @@ PolytopeShape::PolytopeShape(const PolytopeShapeParam& param) } PolytopeShape::~PolytopeShape() { - if (mHavokShape) { - /// @bug This is not how reference counting is supposed to work. - for (int i = 0, n = mHavokShape->getReferenceCount(); i < n; ++i) - mHavokShape->removeReference(); - - mHavokShape = nullptr; - } - + deleteRefCountedHavokObject(mHavokShape); util::deallocateObjectUnsafe(mTransformShape); mVertices.freeBuffer(); } @@ -147,7 +141,7 @@ const hkpShape* PolytopeShape::updateHavokShape() { return nullptr; } - return std::as_const(*this).getHavokShape(); + return getHavokShapeConst(); } void PolytopeShape::setScale(float scale) { diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h index 1c24a50f..fd5e7c0f 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h @@ -19,6 +19,14 @@ class SphereShape : public Shape { SEAD_RTTI_OVERRIDE(SphereShape, Shape) public: static SphereShape* make(const SphereShapeParam& param, sead::Heap* heap); + SphereShape* clone(sead::Heap* heap) const; + + void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return mMaterialMask; } + +private: + char _8[0x28 - 0x8]; + MaterialMask mMaterialMask; }; class SphereParam : public RigidBodyInstanceParam { diff --git a/src/KingSystem/Physics/RigidBody/Shape/physShape.h b/src/KingSystem/Physics/RigidBody/Shape/physShape.h index 9f0f91e6..672c6cb4 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/physShape.h @@ -15,6 +15,7 @@ enum class ShapeType { Box = 2, Cylinder = 3, Polytope = 4, + List = 5, CharacterPrism = 6, BoxWater = 7, CylinderWater = 8, @@ -29,11 +30,18 @@ public: virtual ShapeType getType() const = 0; virtual float getVolume() const = 0; virtual ~Shape() = default; + virtual hkpShape* getHavokShape() = 0; virtual const hkpShape* getHavokShape() const = 0; + + /// Update the underlying Havok shape if necessary. This may recreate the Havok shape. + /// @return a pointer to the new underlying Havok shape if it was recreated, null otherwise virtual const hkpShape* updateHavokShape() = 0; + /// @param scale New scale (relative to the current scale) virtual void setScale(float scale) = 0; + + const hkpShape* getHavokShapeConst() const { return getHavokShape(); } }; struct CommonShapeParam { diff --git a/src/KingSystem/Physics/physHeapUtil.h b/src/KingSystem/Physics/physHeapUtil.h new file mode 100644 index 00000000..06890a95 --- /dev/null +++ b/src/KingSystem/Physics/physHeapUtil.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace ksys::phys { + +template +inline std::enable_if_t, void> +deleteRefCountedHavokObject(T*& object) { + if (!object) + return; + + /// @bug This should just be a delete expression. Decrementing the reference count + /// n times (with n = the reference count) is not how reference counting is supposed to work. + for (int i = 0, n = object->getReferenceCount(); i < n; ++i) + object->removeReference(); + + object = nullptr; +} + +} // namespace ksys::phys