From 7c25fd08eb4497c4413db0a44946b7f6f0e63b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 3 Feb 2022 12:18:20 +0100 Subject: [PATCH] ksys/phys: Implement CylinderShape --- data/uking_functions.csv | 34 ++--- src/KingSystem/Physics/CMakeLists.txt | 2 + .../RigidBody/Shape/physCylinderRigidBody.cpp | 1 + .../RigidBody/Shape/physCylinderRigidBody.h | 12 ++ .../RigidBody/Shape/physCylinderShape.cpp | 125 ++++++++++++++++++ .../RigidBody/Shape/physCylinderShape.h | 61 +++++++-- .../RigidBody/Shape/physShapeParamObj.cpp | 4 +- .../RigidBody/physRigidBodyFactory.cpp | 11 +- .../Physics/RigidBody/physRigidBodyFactory.h | 3 +- 9 files changed, 218 insertions(+), 35 deletions(-) create mode 100644 src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.cpp create mode 100644 src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 5eaf0933..9b1b2957 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83624,23 +83624,23 @@ Address,Quality,Size,Name 0x0000007100fad7e4,U,000204, 0x0000007100fad8b0,U,000092, 0x0000007100fad90c,U,000008, -0x0000007100fad914,U,000344, -0x0000007100fada8c,U,000064, -0x0000007100fadacc,U,000072, -0x0000007100fadb14,U,000052, -0x0000007100fadb48,U,000192, -0x0000007100fadc08,U,000192, -0x0000007100fadcc8,U,000008, -0x0000007100fadcd0,U,000052, -0x0000007100fadd04,U,000120, -0x0000007100fadd7c,U,000008, -0x0000007100fadd84,U,000008, -0x0000007100fadd8c,U,000264, -0x0000007100fade94,U,000148, -0x0000007100fadf28,U,000184, -0x0000007100fadfe0,U,000204, -0x0000007100fae0ac,U,000092, -0x0000007100fae108,U,000008, +0x0000007100fad914,O,000344,_ZN4ksys4phys13CylinderShape4makeERKNS0_18CylinderShapeParamEPN4sead4HeapE +0x0000007100fada8c,O,000064,_ZN4ksys4phys13CylinderShapeD1Ev +0x0000007100fadacc,O,000072,_ZN4ksys4phys13CylinderShapeD0Ev +0x0000007100fadb14,O,000052,_ZN4ksys4phys13CylinderShape9setRadiusEf +0x0000007100fadb48,O,000192,_ZN4ksys4phys13CylinderShape11setVerticesERKN4sead7Vector3IfEES6_ +0x0000007100fadc08,O,000192,_ZNK4ksys4phys13CylinderShape5cloneEPN4sead4HeapE +0x0000007100fadcc8,O,000008,_ZNK4ksys4phys13CylinderShape9getRadiusEv +0x0000007100fadcd0,O,000052,_ZN4ksys4phys13CylinderShape11getVerticesEPN4sead7Vector3IfEES5_ +0x0000007100fadd04,O,000120,_ZNK4ksys4phys13CylinderShape9getVolumeEv +0x0000007100fadd7c,O,000008,_ZN4ksys4phys13CylinderShape13getHavokShapeEv +0x0000007100fadd84,O,000008,_ZNK4ksys4phys13CylinderShape13getHavokShapeEv +0x0000007100fadd8c,O,000264,_ZN4ksys4phys13CylinderShape16updateHavokShapeEv +0x0000007100fade94,O,000148,_ZN4ksys4phys13CylinderShape8setScaleEf +0x0000007100fadf28,O,000184,_ZN4ksys4phys13CylinderShape17transformVerticesEPN4sead7Vector3IfEES5_RK12hkTransformf +0x0000007100fadfe0,O,000204,_ZNK4ksys4phys13CylinderShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fae0ac,O,000092,_ZNK4ksys4phys13CylinderShape18getRuntimeTypeInfoEv +0x0000007100fae108,O,000008,_ZNK4ksys4phys13CylinderShape7getTypeEv 0x0000007100fae110,U,000288, 0x0000007100fae230,U,000032, 0x0000007100fae250,U,000064, diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 26a8b211..da33ee49 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -54,6 +54,8 @@ target_sources(uking PRIVATE RigidBody/Shape/physCapsuleShape.h RigidBody/Shape/physCharacterPrismShape.cpp RigidBody/Shape/physCharacterPrismShape.h + RigidBody/Shape/physCylinderRigidBody.cpp + RigidBody/Shape/physCylinderRigidBody.h RigidBody/Shape/physCylinderShape.cpp RigidBody/Shape/physCylinderShape.h RigidBody/Shape/physCylinderWaterShape.cpp diff --git a/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.cpp new file mode 100644 index 00000000..610bf565 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.cpp @@ -0,0 +1 @@ +#include "KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h" diff --git a/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h new file mode 100644 index 00000000..f60324f7 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h @@ -0,0 +1,12 @@ +#pragma once + +#include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" + +namespace ksys::phys { + +// TODO +class CylinderRigidBody : public RigidBodyFromShape { + SEAD_RTTI_OVERRIDE(CylinderRigidBody, RigidBodyFromShape) +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.cpp index e69de29b..b167fcf5 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.cpp @@ -0,0 +1,125 @@ +#include "KingSystem/Physics/RigidBody/Shape/physCylinderShape.h" +#include +#include "KingSystem/Physics/physConversions.h" +#include "KingSystem/Utils/HeapUtil.h" +#include "KingSystem/Utils/SafeDelete.h" + +namespace ksys::phys { + +CylinderShape* CylinderShape::make(const CylinderShapeParam& param, sead::Heap* heap) { + void* storage = util::allocStorage(heap); + if (!storage) + return nullptr; + + auto* hk_shape = new (storage) + hkpCylinderShape(toHkVec4(param.vertex_a), toHkVec4(param.vertex_b), param.radius); + + return new (heap) CylinderShape(param, hk_shape); +} + +CylinderShape::CylinderShape(const CylinderShapeParam& param, hkpCylinderShape* hk_shape) + : mVertexA(param.vertex_a), mVertexB(param.vertex_b), mRadius(param.radius), + mMaterialMask(param.common.getMaterialMask()), mHavokShape(hk_shape) { + if (param.common.item_code_disable_stick) + mMaterialMask.getData().setCustomFlag(MaterialMaskData::CustomFlag::_0); + + setMaterialMask(mMaterialMask); +} + +CylinderShape::~CylinderShape() { + util::deallocateObjectUnsafe(mHavokShape); +} + +void CylinderShape::setMaterialMask(const MaterialMask& mask) { + mMaterialMask = mask; + + if (mHavokShape) + mHavokShape->setUserData(mask.getRawData()); +} + +bool CylinderShape::setRadius(float radius) { + if (mRadius == radius) + return false; + + mRadius = radius; + mFlags.set(Flag::Dirty); + return true; +} + +bool CylinderShape::setVertices(const sead::Vector3f& va, const sead::Vector3f& vb) { + if (mVertexA == va && mVertexB == vb) + return false; + + mVertexA = va; + mVertexB = vb; + mFlags.set(Flag::Dirty); + return true; +} + +CylinderShape* CylinderShape::clone(sead::Heap* heap) const { + CylinderShapeParam param; + param.radius = mRadius; + param.vertex_a = mVertexA; + param.vertex_b = mVertexB; + auto* cloned = make(param, heap); + cloned->setMaterialMask(mMaterialMask); + return cloned; +} + +float CylinderShape::getRadius() const { + return mRadius; +} + +void CylinderShape::getVertices(sead::Vector3f* va, sead::Vector3f* vb) { + *va = mVertexA; + *vb = mVertexB; +} + +float CylinderShape::getVolume() const { + const auto height = (mVertexA - mVertexB).length(); + return height * (sead::Mathf::pi() * mRadius * mRadius); +} + +hkpShape* CylinderShape::getHavokShape() { + return mHavokShape; +} + +const hkpShape* CylinderShape::getHavokShape() const { + return mHavokShape; +} + +const hkpShape* CylinderShape::updateHavokShape() { + if (!mFlags.isOn(Flag::Dirty)) + return nullptr; + + const auto ref_count = mHavokShape->getReferenceCount(); + mHavokShape = + new (mHavokShape) hkpCylinderShape(toHkVec4(mVertexA), toHkVec4(mVertexB), mRadius); + mHavokShape->setReferenceCount(ref_count); + + setMaterialMask(mMaterialMask); + + mFlags.reset(Flag::Dirty); + return nullptr; +} + +void CylinderShape::setScale(float scale) { + setRadius(mRadius * scale); + + sead::Vector3f va, vb; + getVertices(&va, &vb); + setVertices(va * scale, vb * scale); +} + +void CylinderShape::transformVertices(sead::Vector3f* va, sead::Vector3f* vb, + const hkTransformf& transform) { + hkVector4f vertex; + + vertex.setTransformedPos(transform, toHkVec4(mVertexA)); + storeToVec3(va, vertex); + + vertex.setTransformedPos(transform, toHkVec4(mVertexB)); + storeToVec3(vb, vertex); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.h b/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.h index 3f38af9e..35c08290 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/physCylinderShape.h @@ -1,27 +1,72 @@ #pragma once #include +#include +#include #include "KingSystem/Physics/RigidBody/Shape/physShape.h" #include "KingSystem/Physics/RigidBody/physRigidBody.h" #include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" +#include "KingSystem/Physics/System/physMaterialMask.h" + +class hkTransformf; +class hkpCylinderShape; namespace ksys::phys { class CylinderParam; +struct CylinderShapeParam; -struct CylinderShape { - virtual ~CylinderShape(); +class CylinderShape : public Shape { + SEAD_RTTI_OVERRIDE(CylinderShape, Shape) +public: + enum class Flag { + Dirty = 1 << 0, + }; - RigidBody* createBody(bool flag, const RigidBodyInstanceParam& params, sead::Heap* heap); + static CylinderShape* make(const CylinderShapeParam& param, sead::Heap* heap); + + CylinderShape(const CylinderShapeParam& param, hkpCylinderShape* hk_shape); + ~CylinderShape() override; + + const MaterialMask& getMaterialMask() const { return mMaterialMask; } + void setMaterialMask(const MaterialMask& mask); + + float getRadius() const; + bool setRadius(float radius); + + void getVertices(sead::Vector3f* va, sead::Vector3f* vb); + bool setVertices(const sead::Vector3f& va, const sead::Vector3f& vb); + + CylinderShape* clone(sead::Heap* heap) const; + + ShapeType getType() const override { return ShapeType::Cylinder; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + void setScale(float scale) override; + + void transformVertices(sead::Vector3f* va, sead::Vector3f* vb, const hkTransformf& transform); + +private: + sead::Vector3f mVertexA; + sead::TypedBitFlag> mFlags; + sead::Vector3f mVertexB; + float mRadius; + MaterialMask mMaterialMask; + hkpCylinderShape* mHavokShape; }; struct CylinderShapeParam { - CylinderShape* createShape(sead::Heap* heap); - - sead::Vector3f translate_0; + /// The center of the first circular base. + sead::Vector3f vertex_a; + /// The radius of the circular bases. float radius; - sead::Vector3f translate_1; - float convex_radius; + /// The center of the second circular base. + sead::Vector3f vertex_b; + /// Additional shell radius around the cylinder. + /// @warning This is ignored by CylinderShape. + float convex_radius = 0.05; CommonShapeParam common; }; diff --git a/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp b/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp index 8174d1e9..4d7c6753 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp @@ -84,8 +84,8 @@ void ShapeParamObj::getCapsule(CapsuleShapeParam* param) const { void ShapeParamObj::getCylinder(CylinderShapeParam* param) const { param->radius = *radius; param->convex_radius = *convex_radius; - param->translate_0 = *translate_0; - param->translate_1 = *translate_1; + param->vertex_a = *translate_0; + param->vertex_b = *translate_1; getCommon(¶m->common); } diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp index 05eb9a05..d5899396 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.cpp @@ -3,6 +3,7 @@ #include "KingSystem/Physics/RigidBody/Shape/physBoxWaterShape.h" #include "KingSystem/Physics/RigidBody/Shape/physCapsuleRigidBody.h" #include "KingSystem/Physics/RigidBody/Shape/physCapsuleShape.h" +#include "KingSystem/Physics/RigidBody/Shape/physCylinderRigidBody.h" #include "KingSystem/Physics/RigidBody/Shape/physCylinderShape.h" #include "KingSystem/Physics/RigidBody/Shape/physCylinderWaterShape.h" #include "KingSystem/Physics/RigidBody/Shape/physSphereShape.h" @@ -34,13 +35,9 @@ CapsuleRigidBody* RigidBodyFactory::createCapsule(RigidBodyInstanceParam* params return createRigidBody(params, heap); } -RigidBody* RigidBodyFactory::createCylinder(RigidBodyInstanceParam* params, sead::Heap* heap) { - if (params->isDynamicSensor()) - params->motion_type = MotionType::Keyframed; - - auto* v = sead::DynamicCast(params); - auto* shape = v->shape.createShape(heap); - return shape->createBody(true, *params, heap); +CylinderRigidBody* RigidBodyFactory::createCylinder(RigidBodyInstanceParam* params, + sead::Heap* heap) { + return createRigidBody(params, heap); } RigidBody* RigidBodyFactory::createCylinderWater(RigidBodyInstanceParam* params, sead::Heap* heap) { diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h index 4808bd1e..e3da1c1e 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFactory.h @@ -11,6 +11,7 @@ namespace ksys::phys { class BoxRigidBody; class BoxWaterRigidBody; class CapsuleRigidBody; +class CylinderRigidBody; class RigidBody; struct RigidBodyInstanceParam; @@ -18,7 +19,7 @@ class RigidBodyFactory { public: static RigidBody* createSphere(RigidBodyInstanceParam* params, sead::Heap* heap); static CapsuleRigidBody* createCapsule(RigidBodyInstanceParam* params, sead::Heap* heap); - static RigidBody* createCylinder(RigidBodyInstanceParam* params, sead::Heap* heap); + static CylinderRigidBody* createCylinder(RigidBodyInstanceParam* params, sead::Heap* heap); static RigidBody* createCylinderWater(RigidBodyInstanceParam* params, sead::Heap* heap); static BoxRigidBody* createBox(RigidBodyInstanceParam* params, sead::Heap* heap); static BoxWaterRigidBody* createBoxWater(RigidBodyInstanceParam* params, sead::Heap* heap);