From 9c1f0808843a7f7a6af19bb344d78e9d7a6bc015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Wed, 9 Feb 2022 22:00:33 +0100 Subject: [PATCH] ksys/phys: Add most of PolytopeShape --- data/uking_functions.csv | 28 +-- .../Base/Types/Geometry/hkStridedVertices.h | 32 ++++ src/KingSystem/Physics/CMakeLists.txt | 2 + .../Shape/Polytope/physPolytopeRigidBody.cpp | 1 + .../Shape/Polytope/physPolytopeRigidBody.h | 13 ++ .../Shape/Polytope/physPolytopeShape.cpp | 174 ++++++++++++++++++ .../Shape/Polytope/physPolytopeShape.h | 71 +++++++ .../RigidBody/physRigidBodyFactory.cpp | 6 + .../Physics/RigidBody/physRigidBodyFactory.h | 3 +- 9 files changed, 315 insertions(+), 15 deletions(-) create mode 100644 lib/hkStubs/Havok/Common/Base/Types/Geometry/hkStridedVertices.h create mode 100644 src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp create mode 100644 src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index a983b920..ddbc434b 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83665,21 +83665,21 @@ Address,Quality,Size,Name 0x0000007100faecd0,O,000152,_ZNK4ksys4phys23HavokCylinderWaterShape20castRayWithCollectorERK20hkpShapeRayCastInputRK9hkpCdBodyR18hkpRayHitCollector 0x0000007100faed68,U,000316, 0x0000007100faeea4,O,000004,_ZNK4ksys4phys23HavokCylinderWaterShape10castSphereERKN19hkpHeightFieldShape18hkpSphereCastInputERK9hkpCdBodyR18hkpRayHitCollector -0x0000007100faeea8,U,000276, -0x0000007100faefbc,U,000520, -0x0000007100faf1c4,U,000480, -0x0000007100faf3a4,U,000228, -0x0000007100faf4b8,U,000232, -0x0000007100faf5a0,U,000036, -0x0000007100faf5c4,U,000028, -0x0000007100faf5e0,U,000028, +0x0000007100faeea8,O,000276,_ZN4ksys4phys13PolytopeShape4makeERKNS0_18PolytopeShapeParamEPN4sead4HeapE +0x0000007100faefbc,O,000520,_ZN4ksys4phys13PolytopeShape4initERKNS0_18PolytopeShapeParamEPN4sead4HeapE +0x0000007100faf1c4,O,000480,_ZNK4ksys4phys13PolytopeShape5cloneEPN4sead4HeapE +0x0000007100faf3a4,O,000228,_ZN4ksys4phys13PolytopeShape9setVertexEiRKN4sead7Vector3IfEE +0x0000007100faf4b8,O,000232,_ZN4ksys4phys13PolytopeShapeD1Ev +0x0000007100faf5a0,O,000036,_ZN4ksys4phys13PolytopeShapeD0Ev +0x0000007100faf5c4,O,000028,_ZN4ksys4phys13PolytopeShape13getHavokShapeEv +0x0000007100faf5e0,O,000028,_ZNK4ksys4phys13PolytopeShape13getHavokShapeEv 0x0000007100faf5fc,U,001028, -0x0000007100fafa00,U,000372, -0x0000007100fafb74,U,000032, -0x0000007100fafb94,U,000008, -0x0000007100fafb9c,U,000204, -0x0000007100fafc68,U,000092, -0x0000007100fafcc4,U,000008, +0x0000007100fafa00,O,000372,_ZN4ksys4phys13PolytopeShape8setScaleEf +0x0000007100fafb74,O,000032,_ZN4ksys4phys13PolytopeShape9setVolumeEf +0x0000007100fafb94,O,000008,_ZNK4ksys4phys13PolytopeShape9getVolumeEv +0x0000007100fafb9c,O,000204,_ZNK4ksys4phys13PolytopeShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fafc68,O,000092,_ZNK4ksys4phys13PolytopeShape18getRuntimeTypeInfoEv +0x0000007100fafcc4,O,000008,_ZNK4ksys4phys13PolytopeShape7getTypeEv 0x0000007100fafccc,U,000144, 0x0000007100fafd5c,U,000200, 0x0000007100fafe24,U,000304, diff --git a/lib/hkStubs/Havok/Common/Base/Types/Geometry/hkStridedVertices.h b/lib/hkStubs/Havok/Common/Base/Types/Geometry/hkStridedVertices.h new file mode 100644 index 00000000..3c075685 --- /dev/null +++ b/lib/hkStubs/Havok/Common/Base/Types/Geometry/hkStridedVertices.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +struct hkStridedVertices { + HK_DECLARE_CLASS_ALLOCATOR(hkStridedVertices) + + hkStridedVertices() : m_numVertices(0) {} + explicit hkStridedVertices(const hkArrayBase& vertices) { set(vertices); } + hkStridedVertices(const hkVector4* vertices, int count) { set(vertices, count); } + + int getSize() const { return m_numVertices; } + + void getVertex(int index, hkVector4& vertexOut) const { + const auto* v = reinterpret_cast( + reinterpret_cast(m_vertices) + m_striding * index); + vertexOut.set(v[0], v[1], v[2], m_striding >= int(sizeof(hkVector4)) ? v[3] : 0); + } + + void set(const hkArrayBase& vertices) { set(vertices.begin(), vertices.getSize()); } + + template + void set(const T* vertices, int numVertices) { + m_vertices = reinterpret_cast(vertices); + m_numVertices = numVertices; + m_striding = sizeof(T); + } + + const hkReal* m_vertices; + int m_numVertices; + int m_striding; +}; diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 871a52bb..0d559bea 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -64,6 +64,8 @@ target_sources(uking PRIVATE RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h RigidBody/Shape/CylinderWater/physCylinderWaterShape.cpp RigidBody/Shape/CylinderWater/physCylinderWaterShape.h + RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp + RigidBody/Shape/Polytope/physPolytopeRigidBody.h RigidBody/Shape/Polytope/physPolytopeShape.cpp RigidBody/Shape/Polytope/physPolytopeShape.h RigidBody/Shape/Sphere/physSphereShape.cpp diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp new file mode 100644 index 00000000..256ab6f6 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp @@ -0,0 +1 @@ +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h" diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h new file mode 100644 index 00000000..d830d793 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h @@ -0,0 +1,13 @@ +#pragma once + +#include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" + +namespace ksys::phys { + +class PolytopeRigidBody : public RigidBodyFromShape { + SEAD_RTTI_OVERRIDE(PolytopeRigidBody, RigidBodyFromShape) +public: + // TODO +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp index d6c699a6..0c373862 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp @@ -1 +1,175 @@ #include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" +#include +#include +#include +#include +#include "KingSystem/Utils/HeapUtil.h" +#include "KingSystem/Utils/SafeDelete.h" + +namespace ksys::phys { + +PolytopeShape* PolytopeShape::make(const PolytopeShapeParam& param, sead::Heap* heap) { + auto* shape = new (heap) PolytopeShape(param); + + if (!shape->init(param, heap)) { + delete shape; + return nullptr; + } + + return shape; +} + +PolytopeShape* PolytopeShape::clone(sead::Heap* heap) const { + PolytopeShapeParam param; + param.vertex_num = u16(mVertices.size()); + + auto* cloned = make(param, heap); + + for (int i = 0; i < int(param.vertex_num); ++i) { + cloned->setVertex(i, getVertex(i)); + } + cloned->setNumVertices(getNumVertices()); + cloned->updateHavokShape(); + cloned->setMaterialMask(getMaterialMask()); + return cloned; +} + +bool PolytopeShape::setVertex(int vertex_idx, const sead::Vector3f& vertex) { + if (mFlags.isOn(Flag::HasCustomScale)) { + mScale = 1.0; + mFlags.reset(Flag::HasCustomScale); + mFlags.set(Flag::_4); + mFlags.set(Flag::_10); + } + + if (vertex != mVertices[vertex_idx]) { + mVertices[vertex_idx] = vertex; + mFlags.set(Flag::_1 | Flag::InvalidVolume); + mVolume = -1.0; + return true; + } + + return false; +} + +void PolytopeShape::setNumVertices(u16 num) { + if (mNumVertices == num) + return; + + mNumVertices = num; + mVolume = -1.0; + mFlags.set(Flag::_1 | Flag::InvalidVolume); +} + +PolytopeShape::PolytopeShape(const PolytopeShapeParam& param) + : mMaterialMask(param.common.getMaterialMask()), mNumVertices(param.vertex_num) { + if (param.common.item_code_disable_stick) + mMaterialMask.getData().setCustomFlag(MaterialMaskData::CustomFlag::_0); + + setMaterialMask(mMaterialMask); +} + +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; + } + + util::deallocateObjectUnsafe(mTransformShape); + mVertices.freeBuffer(); +} + +hkpShape* PolytopeShape::getHavokShape() { + if (mFlags.isOn(Flag::HasCustomScale)) + return mTransformShape; + return mHavokShape; +} + +const hkpShape* PolytopeShape::getHavokShape() const { + if (mFlags.isOn(Flag::HasCustomScale)) + return mTransformShape; + return mHavokShape; +} + +const hkpShape* PolytopeShape::updateHavokShape() { + // TODO + return nullptr; +} + +void PolytopeShape::setScale(float scale) { + const bool invalid_volume = mFlags.isOn(Flag::InvalidVolume); + const float volume = mVolume; + + mScale *= scale; + mFlags.set(Flag::_4); + if (sead::Mathf::equalsEpsilon(mScale, 1.0)) { + mScale = 1.0; + } + + // Rescale all vertices. + for (int i = 0, n = int(mNumVertices); i < n; ++i) { + mVertices[i] = scale * getVertex(i); + } + + const bool had_custom_scale = mFlags.isOn(Flag::HasCustomScale); + const bool has_custom_scale = mScale != 1.0; + mFlags.change(Flag::HasCustomScale, has_custom_scale); + mFlags.change(Flag::_10, had_custom_scale != has_custom_scale); + + if (!invalid_volume) { + setVolume(scale * scale * scale * volume); + } +} + +void PolytopeShape::setVolume(float volume) { + mVolume = volume; + mFlags.reset(Flag::InvalidVolume); +} + +float PolytopeShape::getVolume() const { + return mVolume; +} + +void PolytopeShape::setMaterialMask(const MaterialMask& mask) { + mMaterialMask = mask; + + if (mHavokShape) + mHavokShape->setUserData(mask.getRawData()); + + if (mTransformShape) + mTransformShape->setUserData(mask.getRawData()); +} + +bool PolytopeShape::init(const PolytopeShapeParam& param, sead::Heap* heap) { + mVertices.allocBufferAssert(param.vertex_num, heap); + mNumVertices = param.vertex_num; + + for (int i = 0; i < int(param.vertex_num); ++i) { + sead::Mathf::sinCosIdx(&mVertices[i].y, &mVertices[i].z, + (sead::Mathu::maxNumber() / mNumVertices) * i); + mVertices[i].x = static_cast(i % 2); + } + + // Alloc the vertices shape. + hkStridedVertices vertices; + vertices.set(mVertices.getBufferPtr(), mNumVertices); + mHavokShape = new hkpConvexVerticesShape(vertices); + if (!mHavokShape) { + return false; + } + + // Alloc the transform shape. + if (auto* storage = util::allocStorage(heap)) { + mTransformShape = + new (storage) hkpConvexTransformShape(mHavokShape, hkQsTransform::IdentityInitializer(), + hkpShapeContainer::REFERENCE_POLICY_IGNORE); + } + + setMaterialMask(mMaterialMask); + return true; +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h index 9aee9be2..9913fc99 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h @@ -1,13 +1,84 @@ #pragma once #include +#include +#include +#include +#include +#include #include "KingSystem/Physics/RigidBody/Shape/physShape.h" +#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" +#include "KingSystem/Physics/System/physMaterialMask.h" + +class hkpConvexTransformShape; +class hkpConvexVerticesShape; namespace ksys::phys { struct PolytopeShapeParam { + /// Number of vertices. u16 vertex_num; CommonShapeParam common; }; +class PolytopeShape : public Shape { + SEAD_RTTI_OVERRIDE(PolytopeShape, Shape) +public: + enum class Flag { + _1 = 1 << 0, + InvalidVolume = 1 << 1, + _4 = 1 << 2, + HasCustomScale = 1 << 3, + _10 = 1 << 4, + }; + + static PolytopeShape* make(const PolytopeShapeParam& param, sead::Heap* heap); + PolytopeShape* clone(sead::Heap* heap) const; + + explicit PolytopeShape(const PolytopeShapeParam& param); + ~PolytopeShape() override; + + const sead::Vector3f& getVertex(int vertex_idx) const { return mVertices[vertex_idx]; } + bool setVertex(int vertex_idx, const sead::Vector3f& vertex); + u16 getNumVertices() const { return mNumVertices; } + void setNumVertices(u16 num); + + ShapeType getType() const override { return ShapeType::Polytope; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + + void setScale(float scale) override; + float getScale() const { return mScale; } + + void setVolume(float volume); + + void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return mMaterialMask; } + +private: + bool init(const PolytopeShapeParam& param, sead::Heap* heap); + + sead::CriticalSection mCS; + hkpConvexVerticesShape* mHavokShape{}; + hkpConvexTransformShape* mTransformShape{}; + sead::TypedBitFlag> mFlags; + MaterialMask mMaterialMask; + float mVolume = -1.0; + float mScale = 1.0; + sead::Buffer mVertices; + u16 mNumVertices{}; +}; + +constexpr PolytopeShape::Flag operator|(PolytopeShape::Flag a, PolytopeShape::Flag b) { + return PolytopeShape::Flag(u32(a) | u32(b)); +} + +class PolytopeParam : public RigidBodyInstanceParam { + SEAD_RTTI_OVERRIDE(PolytopeParam, RigidBodyInstanceParam) +public: + PolytopeShapeParam shape; +}; + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp index 8bd1d621..77f758da 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp @@ -7,6 +7,7 @@ #include "KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderShape.h" #include "KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h" #include "KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" #include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" #include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" @@ -55,4 +56,9 @@ BoxWaterRigidBody* RigidBodyFactory::createBoxWater(RigidBodyInstanceParam* para return createRigidBody(params, heap); } +PolytopeRigidBody* RigidBodyFactory::createPolytope(RigidBodyInstanceParam* params, + sead::Heap* heap) { + return createRigidBody(params, heap); +} + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h index 2e3b2927..c435218f 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h @@ -13,6 +13,7 @@ class BoxWaterRigidBody; class CapsuleRigidBody; class CylinderRigidBody; class CylinderWaterRigidBody; +class PolytopeRigidBody; class RigidBody; struct RigidBodyInstanceParam; @@ -25,7 +26,7 @@ public: sead::Heap* heap); static BoxRigidBody* createBox(RigidBodyInstanceParam* params, sead::Heap* heap); static BoxWaterRigidBody* createBoxWater(RigidBodyInstanceParam* params, sead::Heap* heap); - static RigidBody* createPolytope(RigidBodyInstanceParam* params, sead::Heap* heap); + static PolytopeRigidBody* createPolytope(RigidBodyInstanceParam* params, sead::Heap* heap); static RigidBody* createCollection(RigidBodyInstanceParam* params, sead::Heap* heap); };