summaryrefslogtreecommitdiff
path: root/src/KingSystem/Physics/Rig/physBoneAccessor.cpp
blob: dcd42708ae5b037f25f80505c8c6a38d6586ede1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "KingSystem/Physics/Rig/physBoneAccessor.h"
#include <Havok/Animation/Animation/Playback/Utilities/hkaSampleAndCombineUtils.h>
#include <Havok/Animation/Animation/Rig/hkaPose.h>
#include <Havok/Animation/Animation/Rig/hkaSkeleton.h>
#include <math/seadMathCalcCommon.h>
#include <prim/seadMemUtil.h>

namespace ksys::phys {

BoneAccessor::BoneAccessor() = default;

BoneAccessor::~BoneAccessor() {
    BoneAccessor::finalize();
}

bool BoneAccessor::init(const hkaSkeleton* skeleton, sead::Heap* heap) {
    static constexpr int Alignment = 0x20;

    mPoseDataSize = sead::Mathu::roundUp(u32(hkaPose::getRequiredMemorySize(skeleton)), Alignment);
    if (mPoseDataSize == 0)
        return false;

    mPoseData = new (heap, Alignment) u8[mPoseDataSize];
    if (!mPoseData)
        return false;

    mPose = new hkaPose(skeleton, mPoseData);
    if (!mPose)
        return false;

    mPose->setToReferencePose();
    return true;
}

void BoneAccessor::finalize() {
    if (!mPose)
        return;

    delete mPose;
    mPose = nullptr;

    delete[] mPoseData;
    mPoseData = nullptr;
}

void BoneAccessor::resetPoseData() {
    sead::MemUtil::fillZero(mPoseData, mPoseDataSize);
}

const hkaSkeleton* BoneAccessor::getSkeleton() const {
    return mPose->getSkeleton();
}

hkaPose* BoneAccessor::getPoseInternal() const {
    return mPose;
}

hkaPose* BoneAccessor::getPose() const {
    return mPose;
}

void BoneAccessor::setScale(float scale) {
    hkaSampleAndCombineUtils::scaleTranslations(
        scale, const_cast<hkQsTransform*>(getSkeleton()->m_referencePose.data()),
        getSkeleton()->m_bones.getSize());
}

BoneAccessor::Indices BoneAccessor::getBoneIndex(const sead::SafeString& name) const {
    const sead::SafeString actual_name = getBoneName(name);

    for (int i = 0, n = getSkeleton()->m_bones.getSize(); i < n; ++i) {
        if (actual_name == getBoneName(getSkeleton()->m_bones[i].m_name.cString()))
            return {0, static_cast<s16>(i)};
    }

    return {-1, -1};
}

void BoneAccessor::setBoneLocalSpace(const BoneAccessor::Indices& index,
                                     const hkQsTransformf& bone) {
    mPose->setBoneLocalSpace(index.havok_index, bone);
}

const hkQsTransformf& BoneAccessor::getBoneLocalSpace(const BoneAccessor::Indices& index) const {
    return mPose->getBoneLocalSpace(index.havok_index);
}

// NON_MATCHING: regalloc
void BoneAccessor::setBoneModelSpace(const BoneAccessor::Indices& index,
                                     const hkQsTransformf& bone_model, Propagate propagate) {
    const auto havok_index = index.havok_index;
    mPose->setBoneModelSpace(havok_index, bone_model, hkaPose::PropagateOrNot(propagate));
}

const hkQsTransformf& BoneAccessor::getBoneModelSpace(const BoneAccessor::Indices& index) const {
    return mPose->getBoneModelSpace(index.havok_index);
}

#ifdef MATCHING_HACK_NX_CLANG
[[gnu::noinline]]
#endif
sead::SafeString BoneAccessor::getBoneName(const sead::SafeString& name) {
    int substr_index = 0;

    int separator_index = name.rfindIndex(":");
    if (separator_index < 0) {
        substr_index = 0;
    } else if (separator_index < name.calcLength() - 1) {
        substr_index = separator_index + 1;
    }

    return name.cstr() + substr_index;
}

}  // namespace ksys::phys