ksys/phys: Implement more RagdollController functions

This commit is contained in:
Léo Lam 2022-12-18 18:35:29 +01:00
parent 20be3a197a
commit bdd2015a08
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
10 changed files with 340 additions and 94 deletions

View File

@ -83840,7 +83840,7 @@ Address,Quality,Size,Name
0x0000007100fb630c,O,000048,_ZN4ksys4phys17EntityGroupFilter31getCollisionFilterInfoLayerTextEj
0x0000007100fb633c,O,000036,_ZN4ksys4phys17EntityGroupFilter18setLayerCustomMaskENS0_12ContactLayerEj
0x0000007100fb6360,O,000008,_ZN4ksys4phys17EntityGroupFilter37getCollisionFilterInfoGroupHandlerIdxEj
0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj
0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter30makeRagdollCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj
0x0000007100fb6394,O,000028,_ZN4ksys4phys17EntityGroupFilter34setEntityLayerCollisionEnabledMaskENS0_12ContactLayerEj
0x0000007100fb63b0,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys11GroupFilterEE9isDerivedEPKNS0_9InterfaceE
0x0000007100fb643c,O,000108,_ZN4ksys4phys21EntityContactListener4makeEPNS0_10ContactMgrEPN4sead4HeapE
@ -93578,7 +93578,8 @@ Address,Quality,Size,Name
0x000000710121e358,O,000020,_ZN4ksys4phys17RagdollControllerD1Ev
0x000000710121e36c,O,000572,_ZN4ksys4phys17RagdollController8finalizeEv
0x000000710121e5a8,O,000052,_ZN4ksys4phys17RagdollControllerD0Ev
0x000000710121e5dc,U,001660,makeRagdollRigidBody
0x000000710121e5dc,O,000004,_ZN4ksys4phys17RagdollController4initEPKNS0_12RagdollParamEPN4sead14DirectResourceEPN4gsys5ModelEPNS5_4HeapE
0x000000710121e5e0,O,001656,_ZN4ksys4phys17RagdollController6doInitEPKNS0_12RagdollParamEPN4sead14DirectResourceEPN4gsys5ModelEPNS5_4HeapE
0x000000710121ec58,O,000032,_ZNK4ksys4phys17RagdollController14isAddedToWorldEv
0x000000710121ec78,O,000512,_ZN4ksys4phys17RagdollController26removeFromWorldImmediatelyEv
0x000000710121ee78,O,000120,_ZN4ksys4phys17RagdollController15removeFromWorldEv
@ -93602,26 +93603,27 @@ Address,Quality,Size,Name
0x0000007101220dac,U,001460,
0x0000007101221360,O,000004,_ZN4ksys4phys17RagdollController2m3Ev
0x0000007101221364,O,000116,_ZN4ksys4phys17RagdollController10setUserTagEPNS0_7UserTagE
0x00000071012213d8,U,000076,
0x00000071012213d8,O,000076,_ZN4ksys4phys17RagdollController21setSystemGroupHandlerEPNS0_18SystemGroupHandlerE
0x0000007101221424,U,000632,
0x000000710122169c,O,000068,_ZN4ksys4phys17RagdollController19setContactPointInfoEPNS0_16ContactPointInfoE
0x00000071012216e0,U,000072,
0x0000007101221728,U,000072,
0x0000007101221770,U,000056,
0x00000071012217a8,U,000056,
0x00000071012217e0,U,000032,
0x00000071012216e0,O,000072,_ZN4ksys4phys17RagdollController18enableContactLayerENS0_12ContactLayerE
0x0000007101221728,O,000072,_ZN4ksys4phys17RagdollController19disableContactLayerENS0_12ContactLayerE
0x0000007101221770,O,000056,_ZN4ksys4phys17RagdollController13setContactAllEv
0x00000071012217a8,O,000056,_ZN4ksys4phys17RagdollController14setContactNoneEv
0x00000071012217e0,O,000032,_ZN4ksys4phys17RagdollController13setContactAllEi
0x0000007101221800,O,000032,_ZN4ksys4phys17RagdollController14setContactNoneEi
0x0000007101221820,U,001188,
0x0000007101221cc4,U,000016,
0x0000007101221cd4,U,000012,
0x0000007101221ce0,U,000068,
0x0000007101221cd4,O,000012,_ZN4ksys4phys17RagdollController17setExtraRigidBodyEPNS0_9RigidBodyEi
0x0000007101221ce0,O,000068,_ZN4ksys4phys17RagdollController16setGravityFactorEf
0x0000007101221d24,U,000032,
0x0000007101221d44,U,000324,
0x0000007101221e88,U,000300,
0x0000007101221fb4,U,000380,
0x0000007101221d44,O,000324,_ZNK4ksys4phys17RagdollController22getBoneRigidBodyByNameERKN4sead14SafeStringBaseIcEE
0x0000007101221e88,O,000300,_ZNK4ksys4phys17RagdollController18getBoneIndexByNameERKN4sead14SafeStringBaseIcEE
0x0000007101221fb4,O,000380,_ZNK4ksys4phys17RagdollController22getBoneIndexByModelKeyERKN4gsys13BoneAccessKeyE
0x0000007101222130,O,000020,_ZNK4ksys4phys17RagdollController15getParentOfBoneEi
0x0000007101222144,U,000132,
0x00000071012221c8,U,000132,
0x000000710122224c,U,000156,
0x0000007101222144,O,000132,_ZNK4ksys4phys17RagdollController22getParentBoneRigidBodyEPKNS0_9RigidBodyE
0x00000071012221c8,O,000132,_ZNK4ksys4phys17RagdollController16getNumChildBonesEPKNS0_9RigidBodyE
0x000000710122224c,O,000156,_ZNK4ksys4phys17RagdollController21getChildBoneRigidBodyEPKNS0_9RigidBodyEi
0x00000071012222e8,U,001268,
0x00000071012227dc,U,001844,
0x0000007101222f10,U,000340,

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

View File

@ -7,7 +7,7 @@ class CharacterController {
public:
void sub_7100F5EC30();
void sub_7100F60604();
void enableCollisionMaybe_0(ContactLayer);
void disableContactLayer(ContactLayer);
};
} // namespace ksys::phys

View File

@ -1,21 +1,26 @@
#include "KingSystem/Physics/Ragdoll/physRagdollController.h"
#include <Havok/Animation/Animation/Mapper/hkaSkeletonMapper.h>
#include <Havok/Animation/Animation/Rig/hkaPose.h>
#include <Havok/Animation/Physics2012Bridge/Instance/hkaRagdollInstance.h>
#include <Havok/Common/Serialize/Util/hkNativePackfileUtils.h>
#include <Havok/Common/Serialize/Util/hkRootLevelContainer.h>
#include <Havok/Physics2012/Dynamics/Constraint/hkpConstraintInstance.h>
#include <Havok/Physics2012/Dynamics/Entity/hkpRigidBody.h>
#include <Havok/Physics2012/Dynamics/World/hkpPhysicsSystem.h>
#include <Havok/Physics2012/Dynamics/World/hkpWorld.h>
#include <Havok/Physics2012/Utilities/Dynamics/ScaleSystem/hkpSystemScalingUtility.h>
#include <math/seadMathCalcCommon.h>
#include <resource/seadResource.h>
#include "KingSystem/Physics/Ragdoll/physRagdollControllerMgr.h"
#include "KingSystem/Physics/Ragdoll/physRagdollRigidBody.h"
#include "KingSystem/Physics/Rig/physModelBoneAccessor.h"
#include "KingSystem/Physics/Rig/physSkeletonMapper.h"
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
#include "KingSystem/Physics/System/physEntityGroupFilter.h"
#include "KingSystem/Physics/System/physGroupFilter.h"
#include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Physics/physConversions.h"
#include "KingSystem/Utils/Debug.h"
#include "KingSystem/Utils/IteratorUtil.h"
#include "KingSystem/Utils/SafeDelete.h"
@ -34,8 +39,142 @@ RagdollController::~RagdollController() {
finalize();
}
bool RagdollController::init(const RagdollParam* param, sead::DirectResource* res,
gsys::Model* model, sead::Heap* heap) {
return doInit(param, res, model, heap);
}
bool RagdollController::doInit(const RagdollParam* param, sead::DirectResource* res,
gsys::Model* model, sead::Heap* heap) {
if (!res)
return false;
// Copy the ragdoll data from the resource and load it in place.
mRagdollDataSize = res->getRawSize();
mRagdollData = new (heap, 0x10) u8[mRagdollDataSize];
std::memcpy(mRagdollData, res->getRawData(), mRagdollDataSize);
{
const char* error = nullptr;
mRootLevelContainer = static_cast<hkRootLevelContainer*>(hkNativePackfileUtils::loadInPlace(
mRagdollData, static_cast<int>(mRagdollDataSize), nullptr, &error));
if (!mRootLevelContainer) {
util::safeDeleteArray(mRagdollData);
return false;
}
}
mRagdollInstance = mRootLevelContainer->findObject<hkaRagdollInstance>();
if (!mRagdollInstance)
return false;
const hkaSkeleton* skeleton = mRagdollInstance->getSkeleton();
const int num_bones = skeleton->m_bones.size();
// Initialise the skeleton mapper or model bone accessor.
if (mRootLevelContainer->findObject<hkaSkeletonMapper>()) {
mSkeletonMapper = new (heap) SkeletonMapper;
auto* skeleton_mapper = mRootLevelContainer->findObject<hkaSkeletonMapper>(nullptr);
auto* model_skeleton_mapper =
mRootLevelContainer->findObject<hkaSkeletonMapper>(skeleton_mapper);
if (!mSkeletonMapper ||
!mSkeletonMapper->init(skeleton_mapper, model_skeleton_mapper, model, heap)) {
return false;
}
} else {
mModelBoneAccessor = new (heap) ModelBoneAccessor;
if (!mModelBoneAccessor->init(skeleton, model, heap)) {
return false;
}
}
mBoneRigidBodies.allocBufferAssert(num_bones, heap);
{
static constexpr size_t Alignment = 0x20;
_b0 = sead::Mathu::roundUpPow2(sizeof(hkQsTransformf) * num_bones, Alignment);
auto* buffer = new (heap, Alignment) u8[_b0];
if (num_bones > 0 && buffer != nullptr) {
_a0 = num_bones;
_a8 = buffer;
}
}
mBoneVectors.allocBufferAssert(num_bones, heap);
mBoneStuff.allocBufferAssert(num_bones, heap);
// Create a RagdollRigidBody for each bone.
for (int i = 0; i < num_bones; ++i) {
const int parent_bone_idx = getParentOfBone(i) >= 0 ? getParentOfBone(i) : 0;
EntityCollisionMask mask;
if (mGroupHandler)
mask.regular.group_handler_index.SetUnsafe(mGroupHandler->getIndex());
mask.raw = makeEntityCollisionMask(mContactLayer, mask.raw);
mask.raw = setEntityCollisionMaskGroundHit(GroundHit::HitAll, mask.raw);
setBitFields(&mask.raw, //
std::make_pair(mask.regular.ragdoll_bone_index, i),
std::make_pair(mask.regular.ragdoll_parent_bone_index, parent_bone_idx),
std::make_pair(mask.is_ragdoll, true));
hkpRigidBody* const hkp_rigid_body = mRagdollInstance->getRigidBodyOfBone(i);
hkp_rigid_body->setCollisionFilterInfo(mask.raw);
sead::SafeString bone_name = skeleton->m_bones[i].m_name.cString();
int separator_index = bone_name.rfindIndex(":");
if (separator_index >= 0 && separator_index < bone_name.calcLength() - 1)
bone_name = bone_name.cstr() + separator_index + 1;
mBoneRigidBodies[i] = new (heap) RagdollRigidBody(bone_name, this, i, hkp_rigid_body, heap);
if (!mBoneRigidBodies[i]->initMotionAccessorForDynamicMotion(heap))
return false;
}
// Initialise each RagdollRigidBody. This must be done in a separate pass after all
// bodies have been created because each bone will store references to its neighbours.
for (int i = 0; i < num_bones; ++i) {
mBoneRigidBodies[i]->init(heap);
}
mTransform = new (heap, alignof(hkQsTransformf))
hkQsTransformf[1]{hkQsTransformf::IdentityInitializer{}};
mRagdollParam = param;
util::PrintDebugFmt("%s %s", sead::SafeString::cEmptyString.cstr(),
sead::SafeString::cEmptyString.cstr());
for (int i = 0, n = mRagdollInstance->m_constraints.size(); i < n; ++i) {
mRagdollInstance->m_constraints[i]->setPriority(hkpConstraintInstance::PRIORITY_TOI);
}
mBoneStuff2.allocBufferAssert(num_bones, heap);
for (int i = 0; i < num_bones; ++i) {
// XXX: this is probably an inlined function?
mBoneStuff2[i] = 0;
mFlags.set(Flag::_80);
}
mModel = model;
registerSelf();
return true;
}
void RagdollController::registerSelf() {
const bool registered = System::instance()->getRagdollControllerMgr()->addController(this);
mFlags.change(Flag::IsRegistered, registered);
}
void RagdollController::unregisterSelf() {
if (mFlags.isOn(Flag::IsRegistered)) {
System::instance()->getRagdollControllerMgr()->removeController(this);
mFlags.reset(Flag::IsRegistered);
}
}
void RagdollController::finalize() {
for (auto body : util::indexIter(mRigidBodies)) {
for (auto body : util::indexIter(mBoneRigidBodies)) {
body.get()->setCollisionInfo(nullptr);
body.get()->setContactPointInfo(nullptr);
}
@ -46,10 +185,10 @@ void RagdollController::finalize() {
if (mRagdollInstance != nullptr)
removeConstraints();
for (auto body : util::indexIter(mRigidBodies))
for (auto body : util::indexIter(mBoneRigidBodies))
delete body.get();
mRigidBodies.freeBuffer();
mBoneRigidBodies.freeBuffer();
if (mSkeletonMapper)
util::safeDelete(mSkeletonMapper);
@ -57,20 +196,20 @@ void RagdollController::finalize() {
if (mModelBoneAccessor)
util::safeDelete(mModelBoneAccessor);
if (mRawRagdollData) {
hkNativePackfileUtils::unloadInPlace(mRawRagdollData, mRawRagdollDataSize);
delete[] mRawRagdollData;
mRawRagdollData = nullptr;
if (mRagdollData) {
hkNativePackfileUtils::unloadInPlace(mRagdollData, static_cast<int>(mRagdollDataSize));
delete[] mRagdollData;
mRagdollData = nullptr;
mRootLevelContainer = nullptr;
mRagdollInstance = nullptr;
}
if (mRotations)
util::safeDeleteArray(mRotations);
if (mTransform)
util::safeDeleteArray(mTransform);
mBoneVectors.freeBuffer();
mBoneStuff.freeBuffer();
mBones.freeBuffer();
mBoneStuff2.freeBuffer();
if (_b0) {
delete[] _a8;
@ -89,37 +228,34 @@ void RagdollController::removeConstraints() {
}
bool RagdollController::isAddedToWorld() const {
return mRigidBodies.size() > 0 && mRigidBodies.back()->isAddedToWorld();
return mBoneRigidBodies.size() > 0 && mBoneRigidBodies.back()->isAddedToWorld();
}
void RagdollController::removeFromWorldImmediately() {
ScopedPhysicsLock lock{this};
removeConstraints();
for (auto body : util::indexIter(mRigidBodies))
for (auto body : util::indexIter(mBoneRigidBodies))
body.get()->removeFromWorldImmediately();
}
void RagdollController::removeFromWorld() {
for (auto body : util::indexIter(mRigidBodies))
for (auto body : util::indexIter(mBoneRigidBodies))
body.get()->removeFromWorld();
}
bool RagdollController::removeFromWorldAndResetLinks() {
bool removed = true;
for (auto body : util::indexIter(mRigidBodies))
for (auto body : util::indexIter(mBoneRigidBodies))
removed &= body.get()->removeFromWorldAndResetLinks();
if (mFlags.isOn(Flag::IsRegistered)) {
System::instance()->getRagdollControllerMgr()->removeController(this);
mFlags.reset(Flag::IsRegistered);
}
unregisterSelf();
return removed;
}
bool RagdollController::isAddingToWorld() const {
return mRigidBodies.size() > 0 && mRigidBodies.back()->isAddingBodyToWorld();
return mBoneRigidBodies.size() > 0 && mBoneRigidBodies.back()->isAddingBodyToWorld();
}
void RagdollController::setTransform(const sead::Matrix34f& transform) {
@ -139,7 +275,7 @@ void RagdollController::setTransform(const hkQsTransformf& transform) {
if (mExtraRigidBody) {
sead::Matrix34f old_transform;
mRigidBodies[mRigidBodyIndex]->getTransform(&old_transform);
mBoneRigidBodies[mBoneIndexForExtraRigidBody]->getTransform(&old_transform);
mExtraRigidBody->setTransform(old_transform);
if (mGroupHandler) {
@ -188,7 +324,7 @@ void RagdollController::setScale(float scale) {
pos.setAdd(body->getTransform().getTranslation(), translation);
body->setPosition(pos);
mRigidBodies[i]->updateShape();
mBoneRigidBodies[i]->updateShape();
}
}
@ -198,36 +334,36 @@ void RagdollController::setScale(float scale) {
void RagdollController::setFixedAndPreserveImpulse(Fixed fixed,
MarkLinearVelAsDirty mark_linear_vel_as_dirty) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setFixedAndPreserveImpulse(fixed, mark_linear_vel_as_dirty);
}
void RagdollController::resetFrozenState() {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->resetFrozenState();
}
void RagdollController::setUseSystemTimeFactor(bool use) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setUseSystemTimeFactor(use);
}
void RagdollController::clearFlag400000(bool clear) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->clearFlag400000(clear);
}
void RagdollController::setEntityMotionFlag200(bool set) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setEntityMotionFlag200(set);
}
void RagdollController::setFixed(Fixed fixed, PreserveVelocities preserve_velocities) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setFixed(fixed, preserve_velocities);
}
BoneAccessor* RagdollController::getModelBoneAccessor() const {
ModelBoneAccessor* RagdollController::getModelBoneAccessor() const {
if (mSkeletonMapper)
return &mSkeletonMapper->getModelBoneAccessor();
@ -237,32 +373,112 @@ BoneAccessor* RagdollController::getModelBoneAccessor() const {
void RagdollController::m3() {}
void RagdollController::setUserTag(UserTag* tag) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setUserTag(tag);
}
void RagdollController::setSystemGroupHandler(SystemGroupHandler* handler) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setSystemGroupHandler(handler);
mGroupHandler = handler;
}
void RagdollController::setContactPointInfo(ContactPointInfo* info) {
for (auto* body : mRigidBodies)
for (auto* body : mBoneRigidBodies)
body->setContactPointInfo(info);
}
void RagdollController::enableContactLayer(ContactLayer layer) {
for (auto* body : mBoneRigidBodies)
body->enableContactLayer(layer, false);
}
void RagdollController::disableContactLayer(ContactLayer layer) {
for (auto* body : mBoneRigidBodies)
body->disableContactLayer(layer, false);
}
void RagdollController::setContactAll() {
for (auto* body : mBoneRigidBodies)
body->setContactAll(false);
}
void RagdollController::setContactNone() {
for (auto* body : mBoneRigidBodies)
body->setContactNone(false);
}
void RagdollController::setContactAll(int bone_index) {
mBoneRigidBodies[bone_index]->setContactAll(false);
}
void RagdollController::setContactNone(int bone_index) {
mBoneRigidBodies[bone_index]->setContactNone(false);
}
void RagdollController::setExtraRigidBody(RigidBody* body, int bone_index) {
mExtraRigidBody = body;
mBoneIndexForExtraRigidBody = bone_index;
}
void RagdollController::setGravityFactor(float factor) {
for (auto* body : mBoneRigidBodies)
body->setGravityFactor(factor);
}
RagdollRigidBody* RagdollController::getBoneRigidBodyByName(const sead::SafeString& name) const {
const int index = getBoneIndexByName(name);
if (index < 0)
return nullptr;
return mBoneRigidBodies[index];
}
int RagdollController::getBoneIndexByModelKey(const gsys::BoneAccessKey& key) const {
const int model_bone_index = getModelBoneAccessor()->findBoneIndex(key);
const char* bone_name = getModelBoneAccessor()->getBoneName(model_bone_index);
if (bone_name == nullptr)
return -1;
return getBoneIndexByName(sead::FormatFixedSafeString<256>("Ragdoll_%s", bone_name));
}
int RagdollController::getBoneIndexByName(const sead::SafeString& name) const {
int index = 0;
for (auto* body : mBoneRigidBodies) {
if (name == body->getHkBodyName())
return index;
++index;
}
return -1;
}
int RagdollController::getParentOfBone(int index) const {
return mRagdollInstance->getParentOfBone(index);
}
RagdollRigidBody* RagdollController::getParentBoneRigidBody(const RigidBody* body) const {
return sead::DynamicCast<const RagdollRigidBody>(body)->getParentBody_();
}
int RagdollController::getNumChildBones(const RigidBody* body) const {
return sead::DynamicCast<const RagdollRigidBody>(body)->getChildBodies_().size();
}
RagdollRigidBody* RagdollController::getChildBoneRigidBody(const RigidBody* body, int index) const {
return sead::DynamicCast<const RagdollRigidBody>(body)->getChildBodies_()[index];
}
RagdollController::ScopedPhysicsLock::ScopedPhysicsLock(const RagdollController* ctrl)
: mCtrl{ctrl}, mWorldLock{ctrl->isAddedToWorld(), ContactLayerType::Entity} {
for (auto body : util::indexIter(ctrl->mRigidBodies))
for (auto body : util::indexIter(ctrl->mBoneRigidBodies))
body.get()->lock(RigidBody::AlsoLockWorld::No);
}
RagdollController::ScopedPhysicsLock::~ScopedPhysicsLock() {
for (auto body : util::indexIter(mCtrl->mRigidBodies))
for (auto body : util::indexIter(mCtrl->mBoneRigidBodies))
body.get()->unlock(RigidBody::AlsoLockWorld::No);
}

View File

@ -12,11 +12,11 @@
class hkaRagdollInstance;
class hkQsTransformf;
class hkRootLevelContainer;
class hkRotationf;
namespace gsys {
struct BoneAccessKey;
class Model;
}
} // namespace gsys
namespace sead {
class DirectResource;
@ -43,8 +43,7 @@ public:
explicit RagdollController(SystemGroupHandler* handler);
virtual ~RagdollController();
// 0x000000710121e5dc
void init(const RagdollParam* param, sead::DirectResource* res, gsys::Model* model,
bool init(const RagdollParam* param, sead::DirectResource* res, gsys::Model* model,
sead::Heap* heap);
// 0x0000007101223320
@ -65,11 +64,7 @@ public:
void setEntityMotionFlag200(bool set);
void setFixed(Fixed fixed, PreserveVelocities preserve_velocities);
BoneAccessor* getModelBoneAccessor() const;
u32 sub_7101221CC4();
void sub_7101221728(ContactLayer layer);
void sub_71012217A8();
ModelBoneAccessor* getModelBoneAccessor() const;
// TODO: rename
virtual void m3();
@ -79,22 +74,28 @@ public:
// 0x0000007101221424
void x_22(int index, float value);
void setContactPointInfo(ContactPointInfo* info);
// 0x00000071012216e0
void x_24();
// 0x0000007101221728
void x_25();
// 0x0000007101221770
void x_26();
// 0x00000071012217a8
void x_27();
// 0x00000071012217e0
void x_28();
void enableContactLayer(ContactLayer layer);
void disableContactLayer(ContactLayer layer);
void setContactAll();
void setContactNone();
void setContactAll(int bone_index);
void setContactNone(int bone_index);
u32 sub_7101221CC4();
void setExtraRigidBody(RigidBody* body, int bone_index);
void setGravityFactor(float factor);
RagdollRigidBody* getBoneRigidBodyByName(const sead::SafeString& name) const;
int getBoneIndexByModelKey(const gsys::BoneAccessKey& key) const;
int getBoneIndexByName(const sead::SafeString& name) const;
int getParentOfBone(int index) const;
RagdollRigidBody* getParentBoneRigidBody(const RigidBody* body) const;
int getNumChildBones(const RigidBody* body) const;
RagdollRigidBody* getChildBoneRigidBody(const RigidBody* body, int index) const;
static void setUnk1(u8 value);
auto& getRigidBodies_() { return mRigidBodies; }
auto& getRigidBodies_() { return mBoneRigidBodies; }
private:
class ScopedPhysicsLock {
@ -108,38 +109,46 @@ private:
};
enum class Flag {
_80 = 0x80,
/// Whether this controller has been registered with the RagdollControllerMgr.
IsRegistered = 0x100,
};
struct BoneVectors {
sead::Vector3f _0;
sead::Vector3f _c;
float _18;
sead::Vector3f _0 = sead::Vector3f::zero;
sead::Vector3f _c = sead::Vector3f::zero;
u16 _18 = -1;
u16 _1a = -1;
};
bool doInit(const RagdollParam* param, sead::DirectResource* res, gsys::Model* model,
sead::Heap* heap);
void finalize();
void removeConstraints();
void setTransform(const hkQsTransformf& transform);
void registerSelf();
void unregisterSelf();
BoneAccessor* getBoneAccessor() const;
SkeletonMapper* mSkeletonMapper = nullptr;
ModelBoneAccessor* mModelBoneAccessor = nullptr;
hkaRagdollInstance* mRagdollInstance = nullptr;
SystemGroupHandler* mGroupHandler = nullptr;
sead::Buffer<RagdollRigidBody*> mRigidBodies;
/// The rigid bodies of bones.
sead::Buffer<RagdollRigidBody*> mBoneRigidBodies;
// TODO: rename
sead::Buffer<BoneVectors> mBoneVectors;
// TODO: rename
sead::Buffer<u32> mBoneStuff;
hkRootLevelContainer* mRootLevelContainer = nullptr;
sead::SafeString mName;
u8* mRawRagdollData = nullptr;
int mRawRagdollDataSize = 0;
hkRotationf* mRotations = nullptr;
// TODO: type
sead::Buffer<void*> mBones;
u8* mRagdollData = nullptr;
u32 mRagdollDataSize = 0;
hkQsTransformf* mTransform = nullptr;
// TODO: rename
sead::Buffer<float> mBoneStuff2;
float _98 = 0.1;
float _9c = 1.0;
u32 _a0 = 0;
@ -157,8 +166,8 @@ private:
u8 _e8;
u8 _e9;
u8 _ea = 0;
u8 mRigidBodyIndex = 0;
u32 _ec = 5;
u8 mBoneIndexForExtraRigidBody = 0;
ContactLayer mContactLayer = ContactLayer::EntityRagdoll;
};
KSYS_CHECK_SIZE_NX150(RagdollController, 0xf0);

View File

@ -7,6 +7,7 @@ namespace ksys::phys {
class RagdollController;
/// The rigid body for a ragdoll bone.
class RagdollRigidBody : public RigidBody {
SEAD_RTTI_OVERRIDE(RagdollRigidBody, RigidBody)
public:
@ -25,6 +26,9 @@ public:
void setContactAll(bool alt_mask);
void setContactNone(bool alt_mask);
auto* getParentBody_() const { return mParentBody; }
auto& getChildBodies_() const { return mChildBodies; }
private:
void updateContactMask();

View File

@ -123,8 +123,8 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
return false;
}
} else if ((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift != 0) {
if (a.regular.ragdoll_bone_index == b.regular.ragdoll_bone_index2 ||
b.regular.ragdoll_bone_index == a.regular.ragdoll_bone_index2)
if (a.regular.ragdoll_bone_index == b.regular.ragdoll_parent_bone_index ||
b.regular.ragdoll_bone_index == a.regular.ragdoll_parent_bone_index)
return false;
}
return true;

View File

@ -52,8 +52,8 @@ public:
void setLayerCustomMask(ContactLayer layer, u32 mask) override;
u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) override;
virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5,
u32 unk10);
virtual u32 makeRagdollCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
u32 bone_index, u32 parent_bone_index);
/// @param layer An entity layer
virtual void setEntityLayerCollisionEnabledMask(ContactLayer layer, u32 mask);
@ -111,7 +111,8 @@ inline u32 EntitySystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLa
if (layer == ContactLayer::EntityRagdoll) {
result.regular.layer.Init(layer);
result.regular.ragdoll_bone_index.Init(current_info.regular.ragdoll_bone_index);
result.regular.ragdoll_bone_index2.Init(current_info.regular.ragdoll_bone_index2);
result.regular.ragdoll_parent_bone_index.Init(
current_info.regular.ragdoll_parent_bone_index);
result.regular.group_handler_index.Init(getIndex());
result.regular.ground_hit.Init(ground_hit);
result.is_ragdoll = true;
@ -196,12 +197,13 @@ inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
return EntityCollisionMask(info).regular.group_handler_index;
}
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
u32 unk5, u32 unk10) {
inline u32 EntityGroupFilter::makeRagdollCollisionFilterInfo(ContactLayer layer,
GroundHit ground_hit, u32 bone_index,
u32 parent_bone_index) {
EntityCollisionMask info;
info.regular.layer.Init(layer);
info.regular.ragdoll_bone_index.Init(unk5);
info.regular.ragdoll_bone_index2.Init(unk10);
info.regular.ragdoll_bone_index.Init(bone_index);
info.regular.ragdoll_parent_bone_index.Init(parent_bone_index);
info.regular.ground_hit.Init(ground_hit);
info.is_ragdoll = true;
return info.raw;

View File

@ -104,10 +104,10 @@ void InstanceSet::sub_7100FBACE0(phys::ContactLayer layer) {
return;
if (mRagdollController != nullptr)
mRagdollController->sub_7101221728(layer);
mRagdollController->disableContactLayer(layer);
if (mCharacterController != nullptr)
mCharacterController->enableCollisionMaybe_0(layer);
mCharacterController->disableContactLayer(layer);
}
void InstanceSet::sub_7100FBAD74() {
@ -115,7 +115,7 @@ void InstanceSet::sub_7100FBAD74() {
rb.disableAllContactLayers();
}
if (mRagdollController != nullptr) {
mRagdollController->sub_71012217A8();
mRagdollController->setContactNone();
}
if (mCharacterController != nullptr) {
mCharacterController->sub_7100F60604();

View File

@ -224,7 +224,7 @@ union EntityCollisionMask {
/// Only valid for ragdoll masks.
util::BitField<5, 5, u32> ragdoll_bone_index;
/// Only valid for ragdoll masks.
util::BitField<10, 5, u32> ragdoll_bone_index2;
util::BitField<10, 5, u32> ragdoll_parent_bone_index;
/// Only valid for CustomReceiver masks.
/// Layers to collide with for EntityQueryCustomReceiver entities.

View File

@ -223,4 +223,17 @@ constexpr void clearBitFields(Storage* storage, const BitFields&... fields) {
*storage &= ~mask;
}
/// Set several BitFields at once.
///
/// This can sometimes produce better codegen compared to setting each BitField individually.
/// (This function builds a mask for all the BitFields and clears those bits in one pass,
/// then ORs in the new values all at once.)
template <typename Storage, typename... BitFieldAndValuePairs>
constexpr void setBitFields(Storage* storage, const BitFieldAndValuePairs&... pairs) {
constexpr Storage mask =
getMaskForBitFields<Storage, typename BitFieldAndValuePairs::first_type...>();
*storage =
((static_cast<Storage>(pairs.second) << pairs.first.StartBit()) | ...) | (*storage & ~mask);
}
} // namespace ksys::util