summaryrefslogtreecommitdiff
path: root/src/KingSystem/Physics/Rig/physSkeletonMapper.cpp
blob: d554b7f7f312c57391654efc05734b350b4bac2a (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
#include "KingSystem/Physics/Rig/physSkeletonMapper.h"
#include <Havok/Animation/Animation/Mapper/hkaSkeletonMapper.h>
#include <Havok/Animation/Animation/Rig/hkaPose.h>

namespace ksys::phys {

SkeletonMapper::SkeletonMapper() = default;

SkeletonMapper::~SkeletonMapper() {
    mModelBoneAccessor.finalize();
    mBoneAccessor.finalize();
}

bool SkeletonMapper::init(hkaSkeletonMapper* skeleton_mapper,
                          hkaSkeletonMapper* model_skeleton_mapper, gsys::Model* model,
                          sead::Heap* heap) {
    if (!model || !skeleton_mapper || !model_skeleton_mapper)
        return false;

    hkaSkeleton* skel_a = skeleton_mapper->m_mapping.m_skeletonA.val();
    if (skel_a != model_skeleton_mapper->m_mapping.m_skeletonB.val())
        return false;

    hkaSkeleton* skel_b = skeleton_mapper->m_mapping.m_skeletonB.val();
    if (skel_b != model_skeleton_mapper->m_mapping.m_skeletonA.val())
        return false;

    const int num_bones_a = skel_a->m_bones.getSize();
    const int num_bones_b = skel_b->m_bones.getSize();
    if (num_bones_a <= 0 || num_bones_b <= 0)
        return false;

    const auto cleanup = [this] {
        mModelBoneAccessor.finalize();
        mBoneAccessor.finalize();
        return false;
    };

    if (num_bones_a <= num_bones_b) {
        mMapperA = model_skeleton_mapper;
        mMapperB = skeleton_mapper;

        if (!mModelBoneAccessor.init(skeleton_mapper->m_mapping.m_skeletonB.val(), model, heap) ||
            !mBoneAccessor.init(skeleton_mapper->m_mapping.m_skeletonA.val(), heap)) {
            return cleanup();
        }
    } else {
        mMapperA = skeleton_mapper;
        mMapperB = model_skeleton_mapper;

        if (!mModelBoneAccessor.init(skeleton_mapper->m_mapping.m_skeletonA.val(), model, heap) ||
            !mBoneAccessor.init(skeleton_mapper->m_mapping.m_skeletonB.val(), heap)) {
            return cleanup();
        }
    }

    return true;
}

void SkeletonMapper::mapPoseA() {
    mBoneAccessor.resetPoseData();
    mMapperA->mapPose(mModelBoneAccessor.getPose()->getSyncedPoseModelSpace().data(),
                      mBoneAccessor.getPose()->getSkeleton()->m_referencePose.data(),
                      mBoneAccessor.getPose()->accessUnsyncedPoseModelSpace().data(),
                      hkaSkeletonMapper::REFERENCE_POSE);
}

void SkeletonMapper::mapPoseB() {
    const auto* original = mModelBoneAccessor.getPose()->getSyncedPoseLocalSpace().data();
    auto* out = mModelBoneAccessor.getPose()->accessUnsyncedPoseModelSpace().data();
    mMapperB->mapPose(mBoneAccessor.getPose()->getSyncedPoseModelSpace().data(), original, out,
                      hkaSkeletonMapper::NO_CONSTRAINTS);
}

}  // namespace ksys::phys