summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2022-02-12 12:06:43 +0100
committerLéo Lam <leo@leolam.fr>2022-02-12 16:43:48 +0100
commitbc66305e3d8c537f446dde96d607e63f5e4d3f2e (patch)
treebf792dc3a7584bafe6b5bd384e93faf37d3774bd /src
parent4a1bb88bd565a54b71b95744f504d6de4ea7f6e3 (diff)
ksys/phys: Add ListShape
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Physics/CMakeLists.txt5
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp2
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h1
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h1
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h10
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp260
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h107
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp1
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h13
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp12
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h8
-rw-r--r--src/KingSystem/Physics/RigidBody/Shape/physShape.h8
-rw-r--r--src/KingSystem/Physics/physHeapUtil.h21
13 files changed, 439 insertions, 10 deletions
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<Flag, sead::Atomic<u32>> 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 <Havok/Physics2012/Collide/Shape/Compound/Collection/List/hkpListShape.h>
+#include <Havok/Physics2012/Collide/Shape/Convex/Sphere/hkpSphereShape.h>
+#include <basis/seadRawPrint.h>
+#include <container/seadSafeArray.h>
+#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<const hkpShape*>({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<decltype(param.num_shapes)>(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<const SphereShape>(shape_to_clone)->clone(heap);
+ break;
+ case ShapeType::Capsule:
+ mShapes[index] = sead::DynamicCast<const CapsuleShape>(shape_to_clone)->clone(heap);
+ break;
+ case ShapeType::Box:
+ mShapes[index] = sead::DynamicCast<const BoxShape>(shape_to_clone)->clone(heap);
+ break;
+ case ShapeType::Cylinder:
+ mShapes[index] = sead::DynamicCast<const CylinderShape>(shape_to_clone)->clone(heap);
+ break;
+ case ShapeType::Polytope:
+ mShapes[index] = sead::DynamicCast<const PolytopeShape>(shape_to_clone)->clone(heap);
+ break;
+ case ShapeType::CharacterPrism:
+ mShapes[index] = sead::DynamicCast<const CharacterPrismShape>(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<SphereShape, SphereShapeParam>(index, param, heap);
+}
+
+Shape* ListShape::replaceWithNewCapsule(int index, const CapsuleShapeParam& param,
+ sead::Heap* heap) {
+ return replaceWithNewShape<CapsuleShape, CapsuleShapeParam>(index, param, heap);
+}
+
+Shape* ListShape::replaceWithNewCylinder(int index, const CylinderShapeParam& param,
+ sead::Heap* heap) {
+ return replaceWithNewShape<CylinderShape, CylinderShapeParam>(index, param, heap);
+}
+
+Shape* ListShape::replaceWithNewBox(int index, const BoxShapeParam& param, sead::Heap* heap) {
+ return replaceWithNewShape<BoxShape, BoxShapeParam>(index, param, heap);
+}
+
+Shape* ListShape::replaceWithNewPolytope(int index, const PolytopeShapeParam& param,
+ sead::Heap* heap) {
+ return replaceWithNewShape<PolytopeShape, PolytopeShapeParam>(index, param, heap);
+}
+
+Shape* ListShape::replaceWithNewCharacterPrism(int index, const CharacterPrismShapeParam& param,
+ sead::Heap* heap) {
+ return replaceWithNewShape<CharacterPrismShape, CharacterPrismShapeParam>(index, param, heap);
+}
+
+void ListShape::setMaterialMask(const MaterialMask& mask, int index) {
+ switch (mShapes[index]->getType()) {
+ case ShapeType::Sphere:
+ sead::DynamicCast<SphereShape>(mShapes[index])->setMaterialMask(mask);
+ break;
+ case ShapeType::Capsule:
+ sead::DynamicCast<CapsuleShape>(mShapes[index])->setMaterialMask(mask);
+ break;
+ case ShapeType::Box:
+ sead::DynamicCast<BoxShape>(mShapes[index])->setMaterialMask(mask);
+ break;
+ case ShapeType::Cylinder:
+ sead::DynamicCast<CylinderShape>(mShapes[index])->setMaterialMask(mask);
+ break;
+ case ShapeType::Polytope:
+ sead::DynamicCast<PolytopeShape>(mShapes[index])->setMaterialMask(mask);
+ break;
+ case ShapeType::CharacterPrism:
+ sead::DynamicCast<CharacterPrismShape>(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<SphereShape>(mShapes[index])->getMaterialMask();
+ case ShapeType::Capsule:
+ return sead::DynamicCast<CapsuleShape>(mShapes[index])->getMaterialMask();
+ case ShapeType::Box:
+ return sead::DynamicCast<BoxShape>(mShapes[index])->getMaterialMask();
+ case ShapeType::Cylinder:
+ return sead::DynamicCast<CylinderShape>(mShapes[index])->getMaterialMask();
+ case ShapeType::Polytope:
+ return sead::DynamicCast<PolytopeShape>(mShapes[index])->getMaterialMask();
+ case ShapeType::CharacterPrism:
+ return sead::DynamicCast<CharacterPrismShape>(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<SphereShape>(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<const hkpShape*> 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 <container/seadBuffer.h>
+#include <prim/seadTypedBitFlag.h>
+#include <thread/seadAtomic.h>
+#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 <typename T, typename ParamType>
+ 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<Shape*> mShapes;
+ /// The Havok list shape. This is owned by this class.
+ hkpListShape* mHavokShape{};
+ sead::TypedBitFlag<Flag, sead::Atomic<u32>> 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 <Havok/Physics2012/Collide/Shape/Convex/ConvexVertices/hkpConvexVerticesShape.h>
#include <math/seadMathCalcCommon.h>
#include <prim/seadScopedLock.h>
+#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 <Havok/Common/Base/Object/hkReferencedObject.h>
+
+namespace ksys::phys {
+
+template <typename T>
+inline std::enable_if_t<std::is_base_of_v<hkReferencedObject, 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