From 90c34d80feabe1849a7e668edfd705eee8b33444 Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Wed, 7 Jul 2021 20:29:45 +0200 Subject: [PATCH] ksys/phys: Add SupportBoneResource [committer's note: rebased] --- data/uking_functions.csv | 50 ++-- lib/sead | 2 +- src/KingSystem/Physics/CMakeLists.txt | 3 + .../SupportBone/physSupportBoneResource.cpp | 254 ++++++++++++++++++ .../SupportBone/physSupportBoneResource.h | 120 +++++++++ .../physSupportBoneResourceMainBone.cpp | 8 + 6 files changed, 411 insertions(+), 26 deletions(-) create mode 100644 src/KingSystem/Physics/SupportBone/physSupportBoneResource.cpp create mode 100644 src/KingSystem/Physics/SupportBone/physSupportBoneResource.h create mode 100644 src/KingSystem/Physics/SupportBone/physSupportBoneResourceMainBone.cpp diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 8e317d94..1770d702 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -93670,30 +93670,30 @@ Address,Quality,Size,Name 0x0000007101228a24,O,000208,_ZN4ksys4phys16SupportBoneParamC1Ev 0x0000007101228af4,O,000048,_ZN4ksys4phys16SupportBoneParamD2Ev 0x0000007101228b24,O,000004,_ZN4ksys4phys16SupportBoneParamD0Ev -0x0000007101228b28,U,000876, -0x0000007101228e94,U,000164, -0x0000007101228f38,U,000688, -0x00000071012291e8,U,000172, -0x0000007101229294,U,000172, -0x0000007101229340,U,000180, -0x00000071012293f4,U,000064, -0x0000007101229434,U,003872, -0x000000710122a354,U,000388, -0x000000710122a4d8,U,000064, -0x000000710122a518,U,000492, -0x000000710122a704,U,000036, -0x000000710122a728,U,000004,j__ZdlPv_1248 -0x000000710122a72c,U,000040, -0x000000710122a754,U,000004,j__ZdlPv_1249 -0x000000710122a758,U,000056, -0x000000710122a790,U,000004,j__ZdlPv_1250 -0x000000710122a794,U,000040, -0x000000710122a7bc,U,000004,j__ZdlPv_1251 -0x000000710122a7c0,U,000296, -0x000000710122a8e8,U,000048, -0x000000710122a918,U,000004,j__ZdlPv_1252 -0x000000710122a91c,U,000056, -0x000000710122a954,U,000088, +0x0000007101228b28,O,000876,_ZN4ksys4phys19SupportBoneResourceC1Ev +0x0000007101228e94,O,000164,_ZN4ksys4phys19SupportBoneResourceD1Ev +0x0000007101228f38,O,000688,_ZN4ksys4phys19SupportBoneResource11freeBuffersEv +0x00000071012291e8,O,000172,_ZThn32_N4ksys4phys19SupportBoneResourceD1Ev +0x0000007101229294,O,000172,_ZN4ksys4phys19SupportBoneResourceD0Ev +0x0000007101229340,O,000180,_ZThn32_N4ksys4phys19SupportBoneResourceD0Ev +0x00000071012293f4,O,000064,_ZN4ksys4phys19SupportBoneResource9doCreate_EPhjPN4sead4HeapE +0x0000007101229434,O,003872,_ZN4ksys4phys19SupportBoneResource4initEN3agl3utl19ResParameterArchiveEPN4sead4HeapE +0x000000710122a354,O,000388,_ZN4ksys4phys19SupportBoneResource25getSupportBoneIndexByNameERKN4sead14SafeStringBaseIcEE +0x000000710122a4d8,O,000064,_ZN4ksys4phys19SupportBoneResource28somethingGetLinearConnectionEjf +0x000000710122a518,O,000492,_ZN4ksys4phys19SupportBoneResource30getInterpolatedConnectionCurveEjf +0x000000710122a704,O,000036,_ZN4ksys4phys19SupportBoneResource4BoneD2Ev +0x000000710122a728,O,000004,_ZN4ksys4phys19SupportBoneResource4BoneD0Ev +0x000000710122a72c,O,000040,_ZN4ksys4phys19SupportBoneResource16ConnectionLinearD2Ev +0x000000710122a754,O,000004,_ZN4ksys4phys19SupportBoneResource16ConnectionLinearD0Ev +0x000000710122a758,O,000056,_ZN4ksys4phys19SupportBoneResource15ConnectionCurveD2Ev +0x000000710122a790,O,000004,_ZN4ksys4phys19SupportBoneResource15ConnectionCurveD0Ev +0x000000710122a794,O,000040,_ZN4ksys4phys19SupportBoneResource12OutputSingleD2Ev +0x000000710122a7bc,O,000004,_ZN4ksys4phys19SupportBoneResource12OutputSingleD0Ev +0x000000710122a7c0,O,000296,_ZN4ksys4phys25uninlineAllocDoubleBufferEPN4sead6BufferINS0_19SupportBoneResource12OutputDoubleEEEiPNS1_4HeapEi +0x000000710122a8e8,O,000048,_ZN4ksys4phys19SupportBoneResource12OutputDoubleD2Ev +0x000000710122a918,O,000004,_ZN4ksys4phys19SupportBoneResource12OutputDoubleD0Ev +0x000000710122a91c,O,000056,_ZN4ksys4phys19SupportBoneResource11SupportBoneD2Ev +0x000000710122a954,O,000088,_ZN4ksys4phys19SupportBoneResource11SupportBoneD0Ev 0x000000710122a9ac,U,000904, 0x000000710122ad34,U,000628, 0x000000710122afa8,U,000064, @@ -97076,7 +97076,7 @@ Address,Quality,Size,Name 0x0000007101309094,U,000004,nullsub_4856 0x0000007101309098,U,000644, 0x000000710130931c,U,000004,j__ZdlPv_1325 -0x0000007101309320,U,000668, +0x0000007101309320,O,000668,_ZN4ksys4phys19SupportBoneResource8BaseBone9postRead_Ev 0x00000071013095bc,U,000048, 0x00000071013095ec,U,000492, 0x00000071013097d8,U,000056, diff --git a/lib/sead b/lib/sead index 0367e0ef..207ccfb3 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 0367e0ef1726f670c24c69d13cc2ce079ee02693 +Subproject commit 207ccfb3f530a0e329c30791c290ec274c52bf4f diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index d41ebf28..738ff5d9 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -13,6 +13,9 @@ target_sources(uking PRIVATE RigidBody/physRigidBodySetParam.h SupportBone/physSupportBoneParam.cpp SupportBone/physSupportBoneParam.h + SupportBone/physSupportBoneResource.cpp + SupportBone/physSupportBoneResource.h + SupportBone/physSupportBoneResourceMainBone.cpp System/physCharacterControllerParam.cpp System/physCharacterControllerParam.h System/physContactInfoParam.cpp diff --git a/src/KingSystem/Physics/SupportBone/physSupportBoneResource.cpp b/src/KingSystem/Physics/SupportBone/physSupportBoneResource.cpp new file mode 100644 index 00000000..3b885129 --- /dev/null +++ b/src/KingSystem/Physics/SupportBone/physSupportBoneResource.cpp @@ -0,0 +1,254 @@ +#include "KingSystem/Physics/SupportBone/physSupportBoneResource.h" + +#include + +namespace ksys::phys { + +SupportBoneResource::Bone::~Bone() = default; + +SupportBoneResource::BaseBone::BaseBone() + : bone(-1, "bone", "bone", this), aim(sead::Vector3f::ez, "aim", "aim", this), + up(sead::Vector3f::ey, "up", "up", this), space(-1, "space", "space", this), + base_rotate(sead::Quatf::unit, "base_rotate", "base_rotate", this), + base_translate(sead::Vector3f::zero, "base_translate", "base_translate", this) {} + +SupportBoneResource::SupportBone::SupportBone() + : bendH(-1, "bendH", "bendH", this), bendV(-1, "bendV", "bendV", this), + roll(-1, "roll", "roll", this), translateX(-1, "translateX", "translateX", this), + translateY(-1, "translateY", "translateY", this), + translateZ(-1, "translateZ", "translateZ", this) {} + +SupportBoneResource::SupportBoneResource() + : IParameterIO("physsb", 0), mBoneNum(0, "bone_num", "bone_num", &mSupportBoneHeader), + mConnectionLinearNum(0, "connection_linear_num", "connection_linear_num", + &mSupportBoneHeader), + mConnectionCurveNum(0, "connection_curve_num", "connection_curve_num", &mSupportBoneHeader), + mOutputSingleNum(0, "output_single_num", "output_single_num", &mSupportBoneHeader), + mOutputDoubleNum(0, "output_double_num", "output_double_num", &mSupportBoneHeader), + // labels have two underscores instead of a single one + mMainBoneNum(0, "main_bone_num", "main_bone__num" /* sic */, &mSupportBoneHeader), + mSupportBoneNum(0, "support_bone_num", "support_bone__num" /* sic */, &mSupportBoneHeader) { + addObj(&mSupportBoneHeader, "support_bone_header"); + addList(&mSupportBoneData, "support_bone_data"); +} + +SupportBoneResource::~SupportBoneResource() { + freeBuffers(); +} + +void SupportBoneResource::freeBuffers() { + boneBuffer.freeBuffer(); + mConnectionLinearBuffer.freeBuffer(); + mConnectionCurveBuffer.freeBuffer(); + mOutputSingleBuffer.freeBuffer(); + mOutputDoubleBuffer.freeBuffer(); + mMainBoneBuffer.freeBuffer(); + mSupportBoneBuffer.freeBuffer(); +} + +bool uninlineAllocDoubleBuffer(sead::Buffer* buffer, + int size, sead::Heap* heap, s32 alignment = sizeof(void*)) { + return buffer->allocBufferAssert(size, heap, alignment); +} + +void SupportBoneResource::doCreate_(u8* data, u32 actualFileSize, sead::Heap* heap) { + init(agl::utl::ResParameterArchive(data), heap); +} + +float SupportBoneResource::somethingGetLinearConnection(u32 a2, float a3) { + sead::Vector2f slope_intercept = mConnectionLinearBuffer[a2].slope_intercept.ref(); + float result = slope_intercept.x * a3 + slope_intercept.y; + return std::isnan(result) ? 0.0f : result; +} + +int SupportBoneResource::getSupportBoneIndexByName(const sead::SafeString& name) { + s32 support_bone_num = mSupportBoneNum.ref(); + for (s32 i = 0; i < support_bone_num; i++) { + int bone_index = mSupportBoneBuffer[i].bone.ref(); + sead::SafeString bone_name = boneBuffer[bone_index].name.ref().cstr(); + if (name == bone_name) + return i; + } + return -1; +} + +bool SupportBoneResource::init(agl::utl::ResParameterArchive archive, sead::Heap* heap) { + agl::utl::ResParameterList param_list = archive.getRootList(); + const auto support_bone_list = param_list.getResParameterList(0); + mSupportBoneHeader.applyResParameterObj(param_list.getResParameterObj(0)); + + int bone_num = mBoneNum.ref(); + if (bone_num < 1) + return false; + mSupportBoneData.addList(&mBoneList, "bone_list"); + boneBuffer.allocBufferAssert(bone_num, heap); + for (int i = 0; i < bone_num; i++) { + auto bone_name = sead::FormatFixedSafeString<32>("bone_%d", i); + mBoneList.addObj(&boneBuffer[i], bone_name); + boneBuffer[i].name.init(sead::FixedSafeString<64>::cEmptyString, "name", "name", + &boneBuffer[i]); + } + + int connection_linear_num = mConnectionLinearNum.ref(); + if (connection_linear_num > 0) { + mSupportBoneData.addList(&mConnectionLinearList, "connection_linear_list"); + mConnectionLinearBuffer.allocBufferAssert(connection_linear_num, heap); + + for (int i = 0; i < connection_linear_num; i++) { + auto connection_name = sead::FormatFixedSafeString<32>("connection_linear_%d", i); + mConnectionLinearList.addObj(&mConnectionLinearBuffer[i], connection_name); + mConnectionLinearBuffer[i].bone_attribute.init( + 0, "bone_attribute", "bone_attribute", + &mConnectionLinearBuffer[i]); // initialised with 0 instead of -1 + mConnectionLinearBuffer[i].slope_intercept.init( + {1, -1}, "slope_intercept", "slope_intercept", &mConnectionLinearBuffer[i]); + } + } + + int connection_curve_num = mConnectionCurveNum.ref(); + if (connection_curve_num > 0) { + mSupportBoneData.addList(&mConnectionCurveList, "connection_curve_list"); + mConnectionCurveBuffer.allocBufferAssert(connection_curve_num, heap); + + for (int i = 0; i < connection_curve_num; i++) { + auto connection_name = sead::FormatFixedSafeString<32>("connection_curve_%d", i); + mConnectionCurveList.addObj(&mConnectionCurveBuffer[i], connection_name); + mConnectionCurveBuffer[i].bone_attribute.init(-1, "bone_attribute", "bone_attribute", + &mConnectionCurveBuffer[i]); + mConnectionCurveBuffer[i].constant_in.init(true, "constant_in", "constant_in", + &mConnectionCurveBuffer[i]); + mConnectionCurveBuffer[i].constant_out.init(true, "constant_out", "constant_out", + &mConnectionCurveBuffer[i]); + mConnectionCurveBuffer[i].key0.init({0, 0, 1, 1}, "key_0", "key_0", + &mConnectionCurveBuffer[i]); + mConnectionCurveBuffer[i].key1.init({0.5, 0.5, 1, 1}, "key_1", "key_1", + &mConnectionCurveBuffer[i]); + mConnectionCurveBuffer[i].key2.init({1, 1, 1, 1}, "key_2", "key_2", + &mConnectionCurveBuffer[i]); + } + } + + int output_single_num = mOutputSingleNum.ref(); + if (output_single_num > 0) { + mSupportBoneData.addList(&mOutputSingleList, "output_single_list"); + mOutputSingleBuffer.allocBufferAssert(output_single_num, heap); + + for (int i = 0; i < output_single_num; i++) { + auto output_name = sead::FormatFixedSafeString<32>("output_single_%d", i); + mOutputSingleList.addObj(&mOutputSingleBuffer[i], output_name); + mOutputSingleBuffer[i].connection.init(0, "connection", "connection", + &mOutputSingleBuffer[i]); + mOutputSingleBuffer[i].weight.init(0, "weight", "weight", &mOutputSingleBuffer[i]); + } + } + + int output_double_num = mOutputDoubleNum.ref(); + if (output_double_num > 0) { + mSupportBoneData.addList(&mOutputDoubleList, "output_double_list"); + uninlineAllocDoubleBuffer(&mOutputDoubleBuffer, output_double_num, heap); + + for (int i = 0; i < output_double_num; i++) { + auto output_name = sead::FormatFixedSafeString<32>("output_double_%d", i); + mOutputDoubleList.addObj(&mOutputDoubleBuffer[i], output_name); + mOutputDoubleBuffer[i].connection_0.init(0, "connection_0", "connection_0", + &mOutputDoubleBuffer[i]); + mOutputDoubleBuffer[i].weight_0.init(0, "weight_0", "weight_0", + &mOutputDoubleBuffer[i]); + mOutputDoubleBuffer[i].connection_1.init(0, "connection_1", "connection_1", + &mOutputDoubleBuffer[i]); + mOutputDoubleBuffer[i].weight_1.init(0, "weight_1", "weight_1", + &mOutputDoubleBuffer[i]); + } + } + + int main_bone_num = mMainBoneNum.ref(); + if (main_bone_num < 1) + return false; + mSupportBoneData.addList(&mMainBoneList, "main_bone_list"); + mMainBoneBuffer.allocBufferAssert(main_bone_num, heap); + for (int i = 0; i < main_bone_num; i++) { + auto name = sead::FormatFixedSafeString<32>("main_bone_%d", i); + mMainBoneList.addObj(&mMainBoneBuffer[i], name); + } + + int support_bone_num = mSupportBoneNum.ref(); + if (support_bone_num < 1) + return false; + mSupportBoneData.addList(&mSupportBoneList, "support_bone_list"); + mSupportBoneBuffer.allocBufferAssert(support_bone_num, heap); + for (int i = 0; i < support_bone_num; i++) { + auto name = sead::FormatFixedSafeString<32>("support_bone_%d", i); + mSupportBoneList.addObj(&mSupportBoneBuffer[i], name); + } + + mSupportBoneData.applyResParameterList(support_bone_list); + return true; +} + +inline float cubicHermiteInterpolate(const sead::Vector4f& key1, const sead::Vector4f& key2, + float lookup) { + if (key1.x == key2.x) { + return key2.y; + } + float diff = key2.x - key1.x; + float t = (lookup - key1.x) / diff; + float h00 = (2 * t * t * t) - (3 * t * t) + 1; + float h01 = (-2 * t * t * t) + (3 * t * t); + float h10 = (t * t * t) - (2 * t * t) + t; + float h10_scaled = h10 * diff; + float h11 = (t * t * t) - (t * t); + float h11_scaled = h11 * diff; + return (h00 * key1.y) + (h01 * key2.y) + (h10_scaled * key1.w) + (h11_scaled * key2.z); +} + +float SupportBoneResource::getInterpolatedConnectionCurve(u32 index, float lookup) { + auto& connection_curve = mConnectionCurveBuffer[index]; + float result; + float x0 = connection_curve.key0->x; // lowest (always minus pi?) + float x1 = connection_curve.key1->x; // middle (0 in most cases) + float x2 = connection_curve.key2->x; // highest + if (x0 == lookup) { + result = connection_curve.key0->y; + } else if (x1 == lookup) { + result = connection_curve.key1->y; + } else if (x2 == lookup) { + result = connection_curve.key2->y; + } else if (x0 > lookup) { + result = connection_curve.key0->y; + if (!connection_curve.constant_in.ref()) + result -= (x0 - lookup) * connection_curve.key0->z; + } else if (x1 > lookup) { + result = cubicHermiteInterpolate(connection_curve.key0.ref(), connection_curve.key1.ref(), + lookup); + } else if (x2 > lookup) { + result = cubicHermiteInterpolate(connection_curve.key1.ref(), connection_curve.key2.ref(), + lookup); + } else { + if (!connection_curve.constant_out.ref()) + result = connection_curve.key2->y + ((lookup - x2) * connection_curve.key2->z); + else + result = connection_curve.key2->y; + } + + return std::isnan(result) ? 0.0f : result; +} + +// NON_MATCHING: Due to seadQuat::normalize() mismatch, this function does not match. +void SupportBoneResource::BaseBone::postRead_() { + sead::Vector3f aim_local = aim.ref(); + sead::Vector3f up_local = up.ref(); + aim_local.normalize(); + + side = sead::cross(aim_local, up_local); + side.normalize(); + + up_local = sead::cross(side, aim_local); + up_local.normalize(); + aim = aim_local; + up = up_local; + + base_rotate->normalize(); + reverse_rotate = base_rotate->inverse(); +} + +} // namespace ksys::phys \ No newline at end of file diff --git a/src/KingSystem/Physics/SupportBone/physSupportBoneResource.h b/src/KingSystem/Physics/SupportBone/physSupportBoneResource.h new file mode 100644 index 00000000..21401c6b --- /dev/null +++ b/src/KingSystem/Physics/SupportBone/physSupportBoneResource.h @@ -0,0 +1,120 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "KingSystem/Utils/Types.h" + +namespace ksys::phys { + +class SupportBoneResource : public sead::DirectResource, agl::utl::IParameterIO { +public: + struct Bone : public agl::utl::ParameterObj { + ~Bone(); + + agl::utl::Parameter> name; + }; + + struct ConnectionLinear : public agl::utl::ParameterObj { + agl::utl::Parameter bone_attribute; // TODO enum? + agl::utl::Parameter slope_intercept; + }; + + struct ConnectionCurve : public agl::utl::ParameterObj { + ~ConnectionCurve() = default; + + agl::utl::Parameter bone_attribute; // TODO enum? + agl::utl::Parameter constant_in; + agl::utl::Parameter constant_out; + agl::utl::Parameter key0; + agl::utl::Parameter key1; + agl::utl::Parameter key2; + }; + + struct OutputSingle : public agl::utl::ParameterObj { + agl::utl::Parameter connection; + agl::utl::Parameter weight; + }; + + struct OutputDouble : public agl::utl::ParameterObj { + ~OutputDouble() = default; + + agl::utl::Parameter connection_0; + agl::utl::Parameter weight_0; + agl::utl::Parameter connection_1; + agl::utl::Parameter weight_1; + }; + + struct BaseBone : public agl::utl::ParameterObj { + BaseBone(); + ~BaseBone(); + void postRead_() override; + + agl::utl::Parameter bone; + agl::utl::Parameter aim; + agl::utl::Parameter up; + agl::utl::Parameter space; + agl::utl::Parameter base_rotate; + agl::utl::Parameter base_translate; + sead::Quatf reverse_rotate; + sead::Vector3 side; + }; + + struct MainBone : public BaseBone { + MainBone(); + }; + + struct SupportBone : public BaseBone { + SupportBone(); + ~SupportBone() = default; + + agl::utl::Parameter bendH; + agl::utl::Parameter bendV; + agl::utl::Parameter roll; + agl::utl::Parameter translateX; + agl::utl::Parameter translateY; + agl::utl::Parameter translateZ; + }; + + SupportBoneResource(); + ~SupportBoneResource(); + + void freeBuffers(); + int getSupportBoneIndexByName(const sead::SafeString& name); + virtual void doCreate_(u8* data, u32 actualFileSize, sead::Heap* heap); + bool init(agl::utl::ResParameterArchive archive, sead::Heap* heap); + + float getInterpolatedConnectionCurve(u32 index, float lookup); + float somethingGetLinearConnection(u32 a2, float a3); + +private: + agl::utl::ParameterObj mSupportBoneHeader; + agl::utl::ParameterList mSupportBoneData; + agl::utl::Parameter mBoneNum; + agl::utl::ParameterList mBoneList; + sead::Buffer boneBuffer; + agl::utl::Parameter mConnectionLinearNum; + agl::utl::ParameterList mConnectionLinearList; + sead::Buffer mConnectionLinearBuffer; + agl::utl::Parameter mConnectionCurveNum; + agl::utl::ParameterList mConnectionCurveList; + sead::Buffer mConnectionCurveBuffer; + agl::utl::Parameter mOutputSingleNum; + agl::utl::ParameterList mOutputSingleList; + sead::Buffer mOutputSingleBuffer; + agl::utl::Parameter mOutputDoubleNum; + agl::utl::ParameterList mOutputDoubleList; + sead::Buffer mOutputDoubleBuffer; + agl::utl::Parameter mMainBoneNum; + agl::utl::ParameterList mMainBoneList; + sead::Buffer mMainBoneBuffer; + agl::utl::Parameter mSupportBoneNum; + agl::utl::ParameterList mSupportBoneList; + sead::Buffer mSupportBoneBuffer; +}; +KSYS_CHECK_SIZE_NX150(SupportBoneResource, 0x5B0); + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/SupportBone/physSupportBoneResourceMainBone.cpp b/src/KingSystem/Physics/SupportBone/physSupportBoneResourceMainBone.cpp new file mode 100644 index 00000000..3f55d0c5 --- /dev/null +++ b/src/KingSystem/Physics/SupportBone/physSupportBoneResourceMainBone.cpp @@ -0,0 +1,8 @@ +#include "KingSystem/Physics/SupportBone/physSupportBoneResource.h" + +namespace ksys::phys { + +SupportBoneResource::MainBone::MainBone() = default; +SupportBoneResource::BaseBone::~BaseBone() = default; + +} // namespace ksys::phys