mirror of
https://github.com/zeldaret/botw
synced 2026-06-27 18:13:02 -04:00
ksys/phys: Add RigidBodyFromResource
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user