From 6ca1c6fd5ae79d3d074bca2e86eb8772f7193b30 Mon Sep 17 00:00:00 2001 From: ConorB <11508137+ConorBobbleHat@users.noreply.github.com> Date: Wed, 13 Apr 2022 22:35:04 +0000 Subject: [PATCH] ksys/phys: Implement `SphereShape` and `SphereRigidBody` (#92) --- data/uking_functions.csv | 72 ++++---- lib/hkStubs/CMakeLists.txt | 1 + .../ConvexTranslate/hkpConvexTranslateShape.h | 69 ++++++++ .../Shape/Sphere/physSphereRigidBody.cpp | 75 ++++++++ .../Shape/Sphere/physSphereRigidBody.h | 12 +- .../Shape/Sphere/physSphereShape.cpp | 160 ++++++++++++++++++ .../RigidBody/Shape/Sphere/physSphereShape.h | 40 ++++- 7 files changed, 389 insertions(+), 40 deletions(-) create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 031fe6c2..f4354395 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83519,25 +83519,25 @@ Address,Quality,Size,Name 0x0000007100fa986c,O,000084,_ZN4ksys4phys12RigidBodySet28removeFromWorldAndResetLinksEv 0x0000007100fa98c0,O,000120,_ZN4ksys4phys12RigidBodySet23hasNoRigidBodyWithFlag8Eb 0x0000007100fa9938,O,000072,_ZN4ksys4phys12RigidBodySet17callRigidBody_x_7Eh -0x0000007100fa9980,U,000004,SphereRigidBody::make -0x0000007100fa9984,U,000084,makeSphereRigidBody -0x0000007100fa99d8,U,000088,SphereRigidBody::dtor -0x0000007100fa9a30,U,000088, -0x0000007100fa9a88,U,000096,SphereRigidBody::dtord -0x0000007100fa9ae8,U,000096, -0x0000007100fa9b48,U,000056, -0x0000007100fa9b80,U,000056, -0x0000007100fa9bb8,U,000012, -0x0000007100fa9bc4,U,000012, -0x0000007100fa9bd0,U,000072, -0x0000007100fa9c18,U,000008, -0x0000007100fa9c20,U,000012, -0x0000007100fa9c2c,U,000016,SphereRigidBody::getVolume -0x0000007100fa9c3c,U,000008,SphereRigidBody::getShape -0x0000007100fa9c44,U,000008,SphereRigidBody::getShape_0 -0x0000007100fa9c4c,U,000068,SphereRigidBody::getCollisionMasks -0x0000007100fa9c90,U,000288,SphereRigidBody::rtti1 -0x0000007100fa9db0,U,000092,SphereRigidBody::rtti2 +0x0000007100fa9980,O,000004,_ZN4ksys4phys15SphereRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE +0x0000007100fa9984,O,000084,_ZN4ksys4phys15SphereRigidBodyC1EP12hkpRigidBodyPNS0_11SphereShapeENS0_16ContactLayerTypeERKN4sead14SafeStringBaseIcEEbPNS7_4HeapE +0x0000007100fa99d8,O,000088,_ZN4ksys4phys15SphereRigidBodyD1Ev +0x0000007100fa9a30,O,000088,_ZThn32_N4ksys4phys15SphereRigidBodyD1Ev +0x0000007100fa9a88,O,000096,_ZN4ksys4phys15SphereRigidBodyD0Ev +0x0000007100fa9ae8,O,000096,_ZThn32_N4ksys4phys15SphereRigidBodyD0Ev +0x0000007100fa9b48,O,000056,_ZN4ksys4phys15SphereRigidBody12setTranslateERKN4sead7Vector3IfEE +0x0000007100fa9b80,O,000056,_ZN4ksys4phys15SphereRigidBody9setRadiusEf +0x0000007100fa9bb8,O,000012,_ZNK4ksys4phys15SphereRigidBody9getRadiusEv +0x0000007100fa9bc4,O,000012,_ZNK4ksys4phys15SphereRigidBody12getTranslateEv +0x0000007100fa9bd0,O,000072,_ZN4ksys4phys15SphereRigidBody23getTransformedTranslateEPN4sead7Vector3IfEE +0x0000007100fa9c18,O,000008,_ZN4ksys4phys15SphereRigidBody15setMaterialMaskERKNS0_12MaterialMaskE +0x0000007100fa9c20,O,000012,_ZNK4ksys4phys15SphereRigidBody15getMaterialMaskEv +0x0000007100fa9c2c,O,000016,_ZN4ksys4phys15SphereRigidBody9getVolumeEv +0x0000007100fa9c3c,O,000008,_ZN4ksys4phys15SphereRigidBody9getShape_Ev +0x0000007100fa9c44,O,000008,_ZNK4ksys4phys15SphereRigidBody9getShape_Ev +0x0000007100fa9c4c,O,000068,_ZN4ksys4phys15SphereRigidBody17getCollisionMasksEPNS0_23RigidBodyCollisionMasksEPKjRKN4sead7Vector3IfEE +0x0000007100fa9c90,O,000288,_ZNK4ksys4phys15SphereRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fa9db0,O,000092,_ZNK4ksys4phys15SphereRigidBody18getRuntimeTypeInfoEv 0x0000007100fa9e0c,O,000024,_ZN4ksys4phys17RigidBodyAccessorC1EP12hkpRigidBody 0x0000007100fa9e24,O,000004,_ZN4ksys4phys17RigidBodyAccessorD1Ev 0x0000007100fa9e28,O,000004,_ZN4ksys4phys17RigidBodyAccessorD0Ev @@ -83687,23 +83687,23 @@ Address,Quality,Size,Name 0x0000007100fafcc4,O,000008,_ZNK4ksys4phys13PolytopeShape7getTypeEv 0x0000007100fafccc,U,000144, 0x0000007100fafd5c,U,000200, -0x0000007100fafe24,U,000304,makeSphereShape -0x0000007100faff54,U,000176,SphereShape::clone -0x0000007100fb0004,U,000048,SphereShape::setMaterialMask -0x0000007100fb0034,U,000300, -0x0000007100fb0160,U,000080,SphereShape::dtor -0x0000007100fb01b0,U,000088,SphereShape::dtord -0x0000007100fb0208,U,000060, -0x0000007100fb0244,U,000260, -0x0000007100fb0348,U,000028,SphereShape::getVol -0x0000007100fb0364,U,000028,SphereShape::getHavokShape -0x0000007100fb0380,U,000028,SphereShape::getHavokShape_0 -0x0000007100fb039c,U,000408,SphereShape::updateHavokShape -0x0000007100fb0534,U,000240,SphereShape::setScale -0x0000007100fb0624,U,000120, -0x0000007100fb069c,U,000204,SphereShape::rtti1 -0x0000007100fb0768,U,000092,SphereShape::rtti2 -0x0000007100fb07c4,U,000008,SphereShape::getType +0x0000007100fafe24,O,000304,_ZN4ksys4phys11SphereShape4makeERKNS0_16SphereShapeParamEPN4sead4HeapE +0x0000007100faff54,O,000176,_ZNK4ksys4phys11SphereShape5cloneEPN4sead4HeapE +0x0000007100fb0004,O,000048,_ZN4ksys4phys11SphereShape15setMaterialMaskERKNS0_12MaterialMaskE +0x0000007100fb0034,O,000300,_ZN4ksys4phys11SphereShapeC1ERKNS0_16SphereShapeParamEP14hkpSphereShapeP23hkpConvexTranslateShape +0x0000007100fb0160,O,000080,_ZN4ksys4phys11SphereShapeD1Ev +0x0000007100fb01b0,O,000088,_ZN4ksys4phys11SphereShapeD0Ev +0x0000007100fb0208,O,000060,_ZN4ksys4phys11SphereShape9setRadiusEf +0x0000007100fb0244,O,000260,_ZN4ksys4phys11SphereShape12setTranslateERKN4sead7Vector3IfEE +0x0000007100fb0348,O,000028,_ZNK4ksys4phys11SphereShape9getVolumeEv +0x0000007100fb0364,O,000028,_ZN4ksys4phys11SphereShape13getHavokShapeEv +0x0000007100fb0380,O,000028,_ZNK4ksys4phys11SphereShape13getHavokShapeEv +0x0000007100fb039c,O,000408,_ZN4ksys4phys11SphereShape16updateHavokShapeEv +0x0000007100fb0534,O,000240,_ZN4ksys4phys11SphereShape8setScaleEf +0x0000007100fb0624,O,000120,_ZNK4ksys4phys11SphereShape12getTranslateEPN4sead7Vector3IfEERK12hkTransformf +0x0000007100fb069c,O,000204,_ZNK4ksys4phys11SphereShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fb0768,O,000092,_ZNK4ksys4phys11SphereShape18getRuntimeTypeInfoEv +0x0000007100fb07c4,O,000008,_ZNK4ksys4phys11SphereShape7getTypeEv 0x0000007100fb07cc,O,000084,_ZN4ksys4phys17ClosestPointQueryC1EPNS0_9RigidBodyEPNS0_21QueryContactPointInfoE 0x0000007100fb0820,O,000004,_ZN4ksys4phys17ClosestPointQueryD1Ev 0x0000007100fb0824,O,000004,_ZN4ksys4phys17ClosestPointQueryD0Ev diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index b1303f0a..44473760 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -150,6 +150,7 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Shape/Convex/Box/hkpBoxShape.h Havok/Physics2012/Collide/Shape/Convex/Capsule/hkpCapsuleShape.h Havok/Physics2012/Collide/Shape/Convex/ConvexTransform/hkpConvexTransformShape.h + Havok/Physics2012/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h Havok/Physics2012/Collide/Shape/Convex/ConvexVertices/hkpConvexVerticesShape.h Havok/Physics2012/Collide/Shape/Convex/Cylinder/hkpCylinderShape.h Havok/Physics2012/Collide/Shape/Convex/Sphere/hkpSphereShape.h diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h b/lib/hkStubs/Havok/Physics2012/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h new file mode 100644 index 00000000..07f70c63 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +class hkpConvexTranslateShape : public hkpConvexTransformShapeBase { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpConvexTranslateShape) + HK_DECLARE_REFLECTION() + HKCD_DECLARE_SHAPE_TYPE(hkcdShapeType::CONVEX_TRANSLATE) + + HK_FORCE_INLINE hkpConvexTranslateShape() {} + HK_FORCE_INLINE hkpConvexTranslateShape( + const hkpConvexShape* childShape, const hkVector4& translation, + hkpShapeContainer::ReferencePolicy ref = hkpShapeContainer::REFERENCE_POLICY_INCREMENT); + + void getSupportingVertex(hkVector4Parameter direction, + hkcdVertex& supportingVertexOut) const override; + void convertVertexIdsToVertices(const hkpVertexId* ids, int numIds, + hkcdVertex* verticesOut) const override; + void getCentre(hkVector4& centreOut) const override; + HK_FORCE_INLINE int getNumCollisionSpheres() const override; + const hkSphere* getCollisionSpheres(hkSphere* sphereBuffer) const override; + void getAabb(const hkTransform& localToWorld, hkReal tolerance, hkAabb& out) const override; + hkBool castRay(const hkpShapeRayCastInput& input, + hkpShapeRayCastOutput& results) const override; + void castRayWithCollector(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const override; + void getFirstVertex(hkVector4& v) const override; + hkReal getMaximumProjection(const hkVector4& direction) const override; + const hkpShapeContainer* getContainer() const override; + int calcSizeForSpu(const CalcSizeForSpuInput& input, int spuBufferSizeLeft) const override; + + inline const hkpConvexShape* getChildShape() const; + inline hkVector4& getTranslation(); + inline const hkVector4& getTranslation() const; + + hkpConvexTranslateShape(class hkFinishLoadedObjectFlag flag); + +protected: + hkVector4 m_translation; +}; + +HK_FORCE_INLINE +hkpConvexTranslateShape::hkpConvexTranslateShape(const hkpConvexShape* childShape, + const hkVector4& translation, + hkpShapeContainer::ReferencePolicy ref) + : hkpConvexTransformShapeBase(HKCD_SHAPE_TYPE_FROM_CLASS(hkpConvexTranslateShape), + childShape->getRadius(), childShape, ref) { + hkVector4 t = translation; + t.setW(0); + m_translation = t; + m_childShapeSizeForSpu = 0; +} + +inline const hkpConvexShape* hkpConvexTranslateShape::getChildShape() const { + return static_cast(m_childShape.getChild()); +} + +inline const hkVector4& hkpConvexTranslateShape::getTranslation() const { + return m_translation; +} + +inline hkVector4& hkpConvexTranslateShape::getTranslation() { + return m_translation; +} + +HK_FORCE_INLINE int hkpConvexTranslateShape::getNumCollisionSpheres() const { + return getChildShape()->getNumCollisionSpheres(); +} \ No newline at end of file diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.cpp index 816b793a..2ed40ff9 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.cpp @@ -1 +1,76 @@ #include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h" +#include +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" + +namespace ksys::phys { + +SphereRigidBody* SphereRigidBody::make(RigidBodyInstanceParam* param, sead::Heap* heap) { + return createSphere(param, heap); +} + +SphereRigidBody::SphereRigidBody(hkpRigidBody* hk_body, SphereShape* shape, + ContactLayerType layer_type, const sead::SafeString& name, + bool set_flag_10, sead::Heap* heap) + : RigidBodyFromShape(hk_body, layer_type, name, set_flag_10, heap), mShape(shape) {} + +SphereRigidBody::~SphereRigidBody() { + if (hasFlag(RigidBody::Flag::_10) && mShape) { + delete mShape; + mShape = nullptr; + } +} + +void SphereRigidBody::setRadius(float radius) { + if (mShape->setRadius(radius)) + updateShape(); +} + +void SphereRigidBody::setTranslate(const sead::Vector3f& translate) { + if (mShape->setTranslate(translate)) + updateShape(); +} + +float SphereRigidBody::getRadius() const { + return mShape->mRadius; +} + +const sead::Vector3f& SphereRigidBody::getTranslate() const { + return mShape->mTranslate; +} + +void SphereRigidBody::getTransformedTranslate(sead::Vector3f* translate) { + lock(); + const auto& transform = getHkBody()->getMotion()->getMotionState()->getTransform(); + unlock(); + mShape->getTranslate(translate, transform); +} + +void SphereRigidBody::setMaterialMask(const MaterialMask& mask) { + mShape->setMaterialMask(mask); +} + +const MaterialMask& SphereRigidBody::getMaterialMask() const { + return mShape->mMaterialMask; +} + +float SphereRigidBody::getVolume() { + return mShape->getVolume(); +} + +Shape* SphereRigidBody::getShape_() { + return mShape; +} + +const Shape* SphereRigidBody::getShape_() const { + return mShape; +} + +u32 SphereRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { + masks->ignored_layers = ~mContactMask.getDirect(); + masks->collision_filter_info = getCollisionFilterInfo(); + masks->material_mask = getMaterialMask().getRawData(); + return 0; +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h index dfc29094..20896b9a 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h @@ -15,12 +15,20 @@ public: const sead::SafeString& name, bool set_flag_10, sead::Heap* heap); ~SphereRigidBody() override; + /// Set the sphere radius and trigger a shape update. + void setRadius(float radius); + /// Set the sphere translation and trigger a shape update. + void setTranslate(const sead::Vector3f& translate); + + float getRadius() const; + const sead::Vector3f& getTranslate() const; + void getTransformedTranslate(sead::Vector3f* translate); + + void setMaterialMask(const MaterialMask& mask); const MaterialMask& getMaterialMask() const; float getVolume() override; - void setRadius(float radius); - protected: Shape* getShape_() override; const Shape* getShape_() const override; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.cpp index ff497871..46f211de 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.cpp @@ -1 +1,161 @@ #include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" +#include "KingSystem/Physics/physConversions.h" +#include "KingSystem/Utils/HeapUtil.h" +#include "KingSystem/Utils/SafeDelete.h" +#include "math/seadMathCalcCommon.h" + +#include +#include + +namespace ksys::phys { + +SphereShape* SphereShape::make(const SphereShapeParam& param, sead::Heap* heap) { + hkpSphereShape* sphere = nullptr; + if (auto* storage = heap->alloc(sizeof(hkpSphereShape), 0x10)) { + sphere = new (storage) hkpSphereShape(param.radius); + } + + hkpConvexTranslateShape* translate_shape = nullptr; + if (auto* storage = util::allocStorage(heap)) { + translate_shape = new (storage) hkpConvexTranslateShape(sphere, toHkVec4(param.translate)); + + if (sphere != nullptr) { + return new (heap) SphereShape(param, sphere, translate_shape); + } + } + + if (sphere) { + delete reinterpret_cast(sphere); + } else if (translate_shape) { + delete reinterpret_cast(translate_shape); + } + + return nullptr; +} + +SphereShape* SphereShape::clone(sead::Heap* heap) const { + SphereShapeParam param; + + param.radius = mRadius; + param.translate = mTranslate; + + auto* cloned = make(param, heap); + cloned->setMaterialMask(mMaterialMask); + return cloned; +} + +SphereShape::SphereShape(const SphereShapeParam& param, hkpSphereShape* shape, + hkpConvexTranslateShape* translate_shape) + : mRadius(param.radius), mHavokShape(shape), mTranslate(param.translate), + mMaterialMask(param.common.getMaterialMask()), mTranslateShape(translate_shape) { + const bool no_transform = mTranslate == sead::Vector3f(0, 0, 0); + mFlags.change(Flag::HasTransform, !no_transform); + + if (param.common.item_code_disable_stick) + mMaterialMask.getData().setCustomFlag(MaterialMaskData::CustomFlag::_0); + + setMaterialMask(mMaterialMask); +} + +SphereShape::~SphereShape() { + util::deallocateObjectUnsafe(mHavokShape); + util::deallocateObjectUnsafe(mTranslateShape); +} + +void SphereShape::setMaterialMask(const MaterialMask& mask) { + mMaterialMask = mask; + + if (mHavokShape) + mHavokShape->setUserData(mask.getRawData()); + + if (mTranslateShape) + mTranslateShape->setUserData(mask.getRawData()); +} + +float SphereShape::getVolume() const { + return 4 / 3 * sead::Mathf::pi() * mRadius * mRadius * mRadius; +} + +hkpShape* SphereShape::getHavokShape() { + if (mFlags.isOn(Flag::HasTransform)) + return mTranslateShape; + + return mHavokShape; +}; + +const hkpShape* SphereShape::getHavokShape() const { + if (mFlags.isOn(Flag::HasTransform)) + return mTranslateShape; + return mHavokShape; +}; + +const hkpShape* SphereShape::updateHavokShape() { + if (mFlags.isOn(Flag::Dirty)) { + { + const auto ref_count = mHavokShape->getReferenceCount(); + mHavokShape = new (mHavokShape) hkpSphereShape(mRadius); + mHavokShape->setReferenceCount(ref_count); + } + { + const auto ref_count = mTranslateShape->getReferenceCount(); + mTranslateShape = + new (mTranslateShape) hkpConvexTranslateShape(mHavokShape, toHkVec4(mTranslate)); + mTranslateShape->setReferenceCount(ref_count); + } + + setMaterialMask(mMaterialMask); + mFlags.reset(Flag::Dirty); + } + + if (mFlags.isOn(Flag::DirtyTransform)) { + mFlags.reset(Flag::DirtyTransform); + return getHavokShapeConst(); + } + + return nullptr; +}; + +bool SphereShape::setRadius(float radius) { + if (radius == mRadius || radius <= 0.0f) { + return false; + } + + mRadius = radius; + mFlags.set(Flag::Dirty); + return true; +} + +void SphereShape::setScale(float scale) { + setRadius(mRadius * scale); + setTranslate(mTranslate * scale); +} + +bool SphereShape::setTranslate(const sead::Vector3f& translate) { + if (mTranslate == translate) + return false; + + mTranslate = translate; + + const bool had_transform = mFlags.isOn(Flag::HasTransform); + const bool no_transform = translate == sead::Vector3f(0, 0, 0); + + mFlags.change(Flag::HasTransform, !no_transform); + mFlags.change(Flag::DirtyTransform, had_transform != !no_transform); + mFlags.set(Flag::Dirty); + + return true; +} + +void SphereShape::getTranslate(sead::Vector3f* out, const hkTransformf& transform) const { + hkVector4f translate; + if (mFlags.isOn(Flag::HasTransform)) { + hkVector4f transformed; + transformed.setTransformedPos(transform, toHkVec4(mTranslate)); + translate = transformed; + } else { + translate = transform.getTranslation(); + } + storeToVec3(out, translate); +} + +} // namespace ksys::phys \ No newline at end of file diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h index f9453d67..2d3a2182 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h @@ -1,10 +1,16 @@ #pragma once #include +#include +#include #include "KingSystem/Physics/RigidBody/Shape/physShape.h" #include "KingSystem/Physics/RigidBody/physRigidBody.h" #include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" +class hkpSphereShape; +class hkpConvexTranslateShape; +class hkTransformf; + namespace ksys::phys { class SphereParam; @@ -18,15 +24,45 @@ struct SphereShapeParam { class SphereShape : public Shape { SEAD_RTTI_OVERRIDE(SphereShape, Shape) public: + enum class Flag { + /// Whether there is a pending change. + Dirty = 1 << 0, + /// Whether we have a transform (translation and/or rotation). + HasTransform = 1 << 1, + /// Whether there is a pending transform change. + DirtyTransform = 1 << 2, + }; + static SphereShape* make(const SphereShapeParam& param, sead::Heap* heap); + + SphereShape(const SphereShapeParam& param, hkpSphereShape* shape, + hkpConvexTranslateShape* translate_shape); + ~SphereShape() override; + SphereShape* clone(sead::Heap* heap) const; + bool setTranslate(const sead::Vector3f& translate); + bool setRadius(float radius); void setMaterialMask(const MaterialMask& mask); const MaterialMask& getMaterialMask() const { return mMaterialMask; } -private: - char _8[0x28 - 0x8]; + ShapeType getType() const override { return ShapeType::Sphere; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + void setScale(float scale) override; + + /// Get the transform's translation or mTranslate transformed by the matrix + /// (if we have a non-zero translation vector). + void getTranslate(sead::Vector3f* out, const hkTransformf& transform) const; + + float mRadius; + hkpSphereShape* mHavokShape{}; + sead::TypedBitFlag> mFlags; + sead::Vector3f mTranslate; MaterialMask mMaterialMask; + hkpConvexTranslateShape* mTranslateShape{}; }; class SphereParam : public RigidBodyInstanceParam, public SphereShapeParam {