ksys/phys: Add RigidBodyFromResource

This commit is contained in:
Léo Lam 2022-02-07 14:58:48 +01:00
parent a3e72dd6f8
commit 635be7c1e4
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
21 changed files with 271 additions and 29 deletions

View File

@ -83258,20 +83258,20 @@ Address,Quality,Size,Name
0x0000007100f9899c,O,000068,_ZN4ksys4phys22CylinderWaterRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksE
0x0000007100f989e0,O,000288,_ZNK4ksys4phys22CylinderWaterRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x0000007100f98b00,O,000092,_ZNK4ksys4phys22CylinderWaterRigidBody18getRuntimeTypeInfoEv
0x0000007100f98b5c,U,000168,RigidBodyFromResource::ctor
0x0000007100f98c04,U,000004,j_RigidBody::dtor_0
0x0000007100f98c08,U,000008,
0x0000007100f98c10,U,000036,
0x0000007100f98c34,U,000040,
0x0000007100f98c5c,U,000108,
0x0000007100f98cc8,U,000048,
0x0000007100f98cf8,U,000312,
0x0000007100f98e30,U,000076,
0x0000007100f98e7c,U,000076,
0x0000007100f98ec8,U,000392,
0x0000007100f99050,U,000008,
0x0000007100f99058,U,000204,
0x0000007100f99124,U,000092,
0x0000007100f98b5c,O,000168,_ZN4ksys4phys21RigidBodyFromResourceC1EfP12hkpRigidBodyNS0_16ContactLayerTypeEPN4sead4HeapENS0_9RigidBody4TypeE
0x0000007100f98c04,O,000004,_ZN4ksys4phys21RigidBodyFromResourceD1Ev
0x0000007100f98c08,O,000008,_ZThn32_N4ksys4phys21RigidBodyFromResourceD1Ev
0x0000007100f98c10,O,000036,_ZN4ksys4phys21RigidBodyFromResourceD0Ev
0x0000007100f98c34,O,000040,_ZThn32_N4ksys4phys21RigidBodyFromResourceD0Ev
0x0000007100f98c5c,O,000108,_ZN4ksys4phys21RigidBodyFromResource4initERKNS0_22RigidBodyInstanceParamEPN4sead4HeapE
0x0000007100f98cc8,O,000048,_ZNK4ksys4phys21RigidBodyFromResource24isBvTreeOrStaticCompoundEv
0x0000007100f98cf8,O,000312,_ZNK4ksys4phys21RigidBodyFromResource10isMaterialENS0_8MaterialE
0x0000007100f98e30,O,000076,_ZN4ksys4phys21RigidBodyFromResource17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj
0x0000007100f98e7c,O,000076,_ZN4ksys4phys21RigidBodyFromResource12updateScale_Eff
0x0000007100f98ec8,O,000392,_ZN4ksys4phys21RigidBodyFromResource17getNewHavokShape_Ev
0x0000007100f99050,O,000008,_ZN4ksys4phys21RigidBodyFromResource9getVolumeEv
0x0000007100f99058,O,000204,_ZNK4ksys4phys21RigidBodyFromResource27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x0000007100f99124,O,000092,_ZNK4ksys4phys21RigidBodyFromResource18getRuntimeTypeInfoEv
0x0000007100f99180,O,000188,_ZN4ksys4phys16RigidBodyFactory12createSphereEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE
0x0000007100f9923c,O,000188,_ZN4ksys4phys16RigidBodyFactory13createCapsuleEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE
0x0000007100f992f8,O,000188,_ZN4ksys4phys16RigidBodyFactory14createCylinderEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE

Can't render this file because it is too large.

View File

@ -108,8 +108,9 @@ add_library(hkStubs OBJECT
Havok/Physics2012/Collide/Query/CastUtil/hkpWorldRayCastInput.h
Havok/Physics2012/Collide/Shape/hkpShape.h
Havok/Physics2012/Collide/Shape/hkpShapeBase.h
Havok/Physics2012/Collide/Shape/hkpShapeType.h
Havok/Physics2012/Collide/Shape/hkpShapeBuffer.h
Havok/Physics2012/Collide/Shape/hkpShapeContainer.h
Havok/Physics2012/Collide/Shape/hkpShapeType.h
Havok/Physics2012/Collide/Shape/Compound/Collection/hkpShapeCollection.h
Havok/Physics2012/Collide/Shape/Compound/Collection/List/hkpListShape.h
Havok/Physics2012/Collide/Shape/Compound/Tree/hkpBvTreeShape.h
@ -168,6 +169,8 @@ add_library(hkStubs OBJECT
Havok/Physics2012/Internal/Collide/Mopp/Code/hkpMoppCode.h
Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeScaling/hkpShapeScalingUtility.h
Havok/Physics2012/Utilities/Dynamics/ScaleSystem/hkpSystemScalingUtility.h
Havok/Physics2012/Utilities/Serialize/hkpPhysicsData.h
)

View File

@ -0,0 +1,14 @@
#pragma once
constexpr int HK_SHAPE_BUFFER_SIZE = 512;
struct hkpShapeBufferStorage {
alignas(16) char m_storage[HK_SHAPE_BUFFER_SIZE];
template <typename T>
operator T*() { // NOLINT(google-explicit-constructor)
return reinterpret_cast<T*>(m_storage);
}
};
using hkpShapeBuffer = hkpShapeBufferStorage;

View File

@ -2,8 +2,7 @@
#include <Havok/Common/Base/hkBase.h>
#include <Havok/Physics2012/Collide/Shape/hkpShape.h>
class hkpShapeBuffer;
#include <Havok/Physics2012/Collide/Shape/hkpShapeBuffer.h>
class hkpShapeContainer {
public:

View File

@ -0,0 +1,25 @@
#pragma once
#include <Havok/Common/Base/hkBase.h>
class hkpShape;
class hkpShapeScalingUtility {
public:
HK_DECLARE_CLASS_ALLOCATOR(hkpShapeScalingUtility)
struct ShapePair {
HK_DECLARE_CLASS_ALLOCATOR(ShapePair)
hkpShape* originalShape;
hkpShape* newShape;
};
static hkpShape* scaleShapeSimd(hkpShape* shape, hkSimdRealParameter scale,
hkArray<ShapePair>* doneShapes = nullptr);
static hkpShape* scaleShape(hkpShape* shape, hkReal scale,
hkArray<ShapePair>* doneShapes = nullptr) {
return scaleShapeSimd(shape, hkSimdReal(scale), doneShapes);
}
};

View File

@ -0,0 +1,17 @@
#pragma once
#include <Havok/Common/Base/hkBase.h>
#include <Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeScaling/hkpShapeScalingUtility.h>
class hkpPhysicsSystem;
class hkpSystemScalingUtility {
public:
static void scaleSystemSimd(hkpPhysicsSystem* system, hkSimdRealParameter scale,
hkArray<hkpShapeScalingUtility::ShapePair>* doneShapes = nullptr);
static void scaleSystem(hkpPhysicsSystem* system, hkReal scale,
hkArray<hkpShapeScalingUtility::ShapePair>* doneShapes = nullptr) {
scaleSystemSimd(system, hkSimdReal(scale), doneShapes);
}
};

View File

@ -23,6 +23,8 @@ target_sources(uking PRIVATE
RigidBody/physRigidBodyAccessor.h
RigidBody/physRigidBodyFactory.cpp
RigidBody/physRigidBodyFactory.h
RigidBody/physRigidBodyFromResource.cpp
RigidBody/physRigidBodyFromResource.h
RigidBody/physRigidBodyFromShape.cpp
RigidBody/physRigidBodyFromShape.h
RigidBody/physRigidBodyMotionEntity.cpp

View File

@ -65,7 +65,7 @@ const Shape* BoxRigidBody::getShape_() const {
return mShape;
}
u32 BoxRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks) {
u32 BoxRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask.getDirect();
masks->collision_filter_info = getCollisionFilterInfo();
masks->material_mask = getMaterialMask().getRawData();

View File

@ -33,7 +33,7 @@ public:
protected:
Shape* getShape_() override;
const Shape* getShape_() const override;
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
BoxShape* mShape;
};

View File

@ -55,7 +55,7 @@ const Shape* BoxWaterRigidBody::getShape_() const {
return mShape;
}
u32 BoxWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks) {
u32 BoxWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask.getDirect();
masks->collision_filter_info = getCollisionFilterInfo();
masks->material_mask = getMaterialMask().getRawData();

View File

@ -31,7 +31,7 @@ public:
protected:
Shape* getShape_() override;
const Shape* getShape_() const override;
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
BoxWaterShape* mShape;
u32 _d8{};

View File

@ -66,7 +66,7 @@ const Shape* CapsuleRigidBody::getShape_() const {
return mShape;
}
u32 CapsuleRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks) {
u32 CapsuleRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask.getDirect();
masks->collision_filter_info = getCollisionFilterInfo();
masks->material_mask = getMaterialMask().getRawData();

View File

@ -31,7 +31,7 @@ public:
protected:
Shape* getShape_() override;
const Shape* getShape_() const override;
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
CapsuleShape* mShape{};
};

View File

@ -65,7 +65,7 @@ const Shape* CylinderRigidBody::getShape_() const {
return mShape;
}
u32 CylinderRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks) {
u32 CylinderRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask.getDirect();
masks->collision_filter_info = getCollisionFilterInfo();
masks->material_mask = getMaterialMask().getRawData();

View File

@ -30,7 +30,7 @@ public:
protected:
Shape* getShape_() override;
const Shape* getShape_() const override;
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
private:
CylinderShape* mShape;

View File

@ -59,7 +59,7 @@ const Shape* CylinderWaterRigidBody::getShape_() const {
return mShape;
}
u32 CylinderWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks) {
u32 CylinderWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask.getDirect();
masks->collision_filter_info = getCollisionFilterInfo();
masks->material_mask = getMaterialMask().getRawData();

View File

@ -30,7 +30,7 @@ public:
protected:
Shape* getShape_() override;
const Shape* getShape_() const override;
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
private:
CylinderWaterShape* mShape{};

View File

@ -9,7 +9,7 @@ class TeraMeshRigidBody : public RigidBody {
public:
TeraMeshRigidBody(hkpRigidBody* hk_body, sead::Heap* heap);
u32 getCollisionMasks(CollisionMasks* masks) override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
};
} // namespace ksys::phys

View File

@ -520,7 +520,7 @@ public:
protected:
// FIXME: return type
virtual u32 getCollisionMasks(CollisionMasks* masks) = 0;
virtual u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) = 0;
/// Called whenever a shape update is requested.
/// @return the new shape to use for the Havok rigid body or null to keep the current hkpShape

View File

@ -0,0 +1,149 @@
#include "KingSystem/Physics/RigidBody/physRigidBodyFromResource.h"
#include <Havok/Physics2012/Collide/Shape/hkpShapeContainer.h>
#include <Havok/Physics2012/Dynamics/Entity/hkpRigidBody.h>
#include <Havok/Physics2012/Dynamics/World/hkpPhysicsSystem.h>
#include <Havok/Physics2012/Utilities/Dynamics/ScaleSystem/hkpSystemScalingUtility.h>
#include <math/seadMathCalcCommon.h>
#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h"
#include "KingSystem/Physics/System/physMaterialMask.h"
#include "KingSystem/Physics/physConversions.h"
namespace ksys::phys {
static const char* getRigidBodyResourceName(const hkpRigidBody* hk_body) {
if (const char* name = hk_body->getName())
return name;
return "RigidBodyFromResource";
}
RigidBodyFromResource::RigidBodyFromResource(float volume, hkpRigidBody* hk_body,
ContactLayerType layer_type, sead::Heap* heap,
RigidBody::Type type)
: RigidBody(type, layer_type, hk_body, getRigidBodyResourceName(hk_body), heap, true),
mShape(hk_body->getCollidable()->getShape()), mVolume(volume) {}
RigidBodyFromResource::~RigidBodyFromResource() = default;
bool RigidBodyFromResource::init(const RigidBodyInstanceParam& param, sead::Heap* heap) {
if (!initMotionAccessor(param, heap, true))
return false;
updateCollidableQualityType(param.toi);
getHkBody()->getCollidableRw()->setMotionState(getHkBody()->getMotion()->getMotionState());
if (auto* shape = getHkBody()->getCollidable()->getShape()) {
hkVector4 extent_out;
getHkBody()->updateCachedShapeInfo(shape, extent_out);
}
return true;
}
bool RigidBodyFromResource::isBvTreeOrStaticCompound() const {
switch (mShape->getType()) {
case hkcdShapeType::TRI_SAMPLED_HEIGHT_FIELD_BV_TREE:
case hkcdShapeType::MOPP:
case hkcdShapeType::STATIC_COMPOUND:
case hkcdShapeType::BV_COMPRESSED_MESH:
case hkcdShapeType::BV_TREE:
return true;
default:
return false;
}
}
bool RigidBodyFromResource::isMaterial(Material material) const {
if (isBvTreeOrStaticCompound())
return false;
bool found_child_shape_with_material = false;
if (auto* container = mShape->getContainer()) {
for (auto key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY;
key = container->getNextKey(key)) {
hkpShapeBuffer buffer;
auto* shape = container->getChildShape(key, buffer);
if (!shape)
return false;
MaterialMask shape_material{MaterialMaskData(shape->getUserData())};
if (int(shape_material.getMaterial()) == material) {
found_child_shape_with_material = true;
break;
}
}
} else {
MaterialMask shape_material{MaterialMaskData(mShape->getUserData())};
if (int(shape_material.getMaterial()) == material)
return true;
}
return found_child_shape_with_material;
}
// FIXME: move this to the appropriate header
// 0x0000007100fd0a1c
u32 getCollisionFilterInfoFromCollidable(u32* material_mask, u32* collision_filter_info,
const hkpCollidable* collidable, const u32* unk);
u32 RigidBodyFromResource::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) {
masks->ignored_layers = ~mContactMask;
auto* collidable = getHkBody()->getCollidable();
if (unk != nullptr) {
return getCollisionFilterInfoFromCollidable(&masks->material_mask,
&masks->collision_filter_info, collidable, unk);
}
masks->material_mask = collidable->getShape()->getUserData();
masks->collision_filter_info = collidable->getCollisionFilterInfo();
return 0;
}
float RigidBodyFromResource::updateScale_(float scale, float old_scale) {
if (getHkBody()->getCollidable()->getShape()->getType() == hkcdShapeType::BV_COMPRESSED_MESH) {
static_cast<void>(getPosition());
return old_scale;
}
mNewScale = scale;
updateShape();
return scale;
}
const hkpShape* RigidBodyFromResource::getNewHavokShape_() {
if (sead::Mathf::equalsEpsilon(mCurrentScale, mNewScale))
return nullptr;
const float ratio = mNewScale / mCurrentScale;
mVolume = ratio * ratio * ratio * mVolume;
const hkTransformf saved_transform = getHkBody()->getTransform();
hkTransformf identity;
identity.setIdentity();
getHkBody()->setTransform(identity);
// Actually scale it now.
// XXX: hkpSystemScalingUtility is not supposed to be used at runtime.
hkpPhysicsSystem system;
system.addRigidBody(getHkBody());
hkpSystemScalingUtility::scaleSystem(&system, ratio);
getHkBody()->setTransform(saved_transform);
if (getHkBody()->getMass() > 0) {
setMass(getHkBody()->getMass());
setCenterOfMassInLocal(toVec3(getHkBody()->getCenterOfMassLocal()));
hkMatrix3 inertia;
getHkBody()->getInertiaLocal(inertia);
setInertiaLocal({inertia.get<0, 0>(), inertia.get<1, 1>(), inertia.get<2, 2>()});
}
mCurrentScale = mNewScale;
return nullptr;
}
float RigidBodyFromResource::getVolume() {
return mVolume;
}
} // namespace ksys::phys

View File

@ -0,0 +1,33 @@
#pragma once
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
namespace ksys::phys {
class RigidBodyFromResource : public RigidBody {
SEAD_RTTI_OVERRIDE(RigidBodyFromResource, RigidBody)
public:
RigidBodyFromResource(float volume, hkpRigidBody* hk_body, ContactLayerType layer_type,
sead::Heap* heap, Type type);
~RigidBodyFromResource() override;
bool init(const RigidBodyInstanceParam& param, sead::Heap* heap);
bool isBvTreeOrStaticCompound() const;
bool isMaterial(Material material) const;
float getVolume() override;
u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override;
protected:
float updateScale_(float scale, float old_scale) override;
const hkpShape* getNewHavokShape_() override;
private:
const hkpShape* mShape = nullptr;
float mVolume = 1.0;
float mCurrentScale = 1.0;
float mNewScale = 1.0;
};
} // namespace ksys::phys