Loading...
Searching...
No Matches
HumanoidPresets.hpp
1#pragma once
2
3// Target rig presets for HumanoidRetarget: compile-time tables mapping
4// canonical humanoid_bone_index → the target skeleton's joint name for
5// three common conventions:
6//
7// - Mixamo (mixamorig:*) — ubiquitous for indie / live / education
8// - VRM — VTubing standard; Ready Player Me derivatives all use this
9// spec's bone names (the VRM humanoid bone list)
10// - Unreal Mannequin — game-dev convention; also matches the
11// output of many BVH-to-FBX converters and most "clean" glTF rigs
12//
13// The tables are compile-time std::array<std::string_view>.
14// If an entry is empty the target rig doesn't have a corresponding bone
15// and HumanoidRetarget will silently skip it (e.g. Mixamo has no explicit
16// Toes bone so LeftToes / RightToes are empty).
17
18#include <Threedim/HumanoidPose.hpp>
19
20#include <array>
21#include <string_view>
22
23namespace Threedim
24{
25
26using HumanoidBoneMap = std::array<
27 std::string_view,
28 std::size_t(humanoid_bone_index::Count)>;
29
30enum class HumanoidRigPreset : uint8_t
31{
32 Mixamo = 0,
33 VRM,
34 UnrealMannequin,
35 Count
36};
37
38// Mixamo — "mixamorig:" prefix, title-cased component names.
39// Spine / Spine1 / Spine2 are three bones; we map the canonical
40// Spine→Spine, Chest→Spine1, (no UpperChest) and Neck/Head directly.
41// Mixamo has no explicit Toes bones; we map to *ToeBase which is the
42// closest equivalent (foot → toe-base is enough for live retargeting).
43inline constexpr HumanoidBoneMap kMixamoBoneMap = {
44 "mixamorig:Hips", // Hips
45 "mixamorig:Spine", // Spine
46 "mixamorig:Spine1", // Chest
47 "mixamorig:Neck", // Neck
48 "mixamorig:Head", // Head
49
50 "mixamorig:LeftShoulder", // LeftShoulder
51 "mixamorig:LeftArm", // LeftUpperArm
52 "mixamorig:LeftForeArm", // LeftLowerArm
53 "mixamorig:LeftHand", // LeftHand
54
55 "mixamorig:RightShoulder", // RightShoulder
56 "mixamorig:RightArm", // RightUpperArm
57 "mixamorig:RightForeArm", // RightLowerArm
58 "mixamorig:RightHand", // RightHand
59
60 "mixamorig:LeftUpLeg", // LeftUpperLeg
61 "mixamorig:LeftLeg", // LeftLowerLeg
62 "mixamorig:LeftFoot", // LeftFoot
63 "mixamorig:LeftToeBase", // LeftToes
64
65 "mixamorig:RightUpLeg", // RightUpperLeg
66 "mixamorig:RightLeg", // RightLowerLeg
67 "mixamorig:RightFoot", // RightFoot
68 "mixamorig:RightToeBase", // RightToes
69};
70
71// VRM — per the VRM humanoid spec bone names. Ready Player Me avatars
72// also use this naming. Toes are not part of the mandatory VRM bone
73// list but commonly present; we map to the optional "LeftToes"/"RightToes"
74// which RPM and most VRM exports populate.
75inline constexpr HumanoidBoneMap kVRMBoneMap = {
76 "Hips", // Hips
77 "Spine", // Spine
78 "Chest", // Chest
79 "Neck", // Neck
80 "Head", // Head
81
82 "LeftShoulder", // LeftShoulder
83 "LeftUpperArm", // LeftUpperArm
84 "LeftLowerArm", // LeftLowerArm
85 "LeftHand", // LeftHand
86
87 "RightShoulder", // RightShoulder
88 "RightUpperArm", // RightUpperArm
89 "RightLowerArm", // RightLowerArm
90 "RightHand", // RightHand
91
92 "LeftUpperLeg", // LeftUpperLeg
93 "LeftLowerLeg", // LeftLowerLeg
94 "LeftFoot", // LeftFoot
95 "LeftToes", // LeftToes
96
97 "RightUpperLeg", // RightUpperLeg
98 "RightLowerLeg", // RightLowerLeg
99 "RightFoot", // RightFoot
100 "RightToes", // RightToes
101};
102
103// Unreal Mannequin — snake_case with "_l"/"_r" suffix. Spine is
104// spine_01/02/03; we map Spine→spine_01, Chest→spine_02 (the visible
105// chest bone). UE mannequin has no UpperChest; Spine→spine_03 would
106// be closer if the rig has one authored. ball_l/r is the UE name for
107// toes-equivalent.
108inline constexpr HumanoidBoneMap kUnrealMannequinBoneMap = {
109 "pelvis", // Hips
110 "spine_01", // Spine
111 "spine_02", // Chest
112 "neck_01", // Neck
113 "head", // Head
114
115 "clavicle_l", // LeftShoulder
116 "upperarm_l", // LeftUpperArm
117 "lowerarm_l", // LeftLowerArm
118 "hand_l", // LeftHand
119
120 "clavicle_r", // RightShoulder
121 "upperarm_r", // RightUpperArm
122 "lowerarm_r", // RightLowerArm
123 "hand_r", // RightHand
124
125 "thigh_l", // LeftUpperLeg
126 "calf_l", // LeftLowerLeg
127 "foot_l", // LeftFoot
128 "ball_l", // LeftToes
129
130 "thigh_r", // RightUpperLeg
131 "calf_r", // RightLowerLeg
132 "foot_r", // RightFoot
133 "ball_r", // RightToes
134};
135
136inline constexpr const HumanoidBoneMap&
137humanoidBoneMap(HumanoidRigPreset preset) noexcept
138{
139 switch(preset)
140 {
141 case HumanoidRigPreset::Mixamo:
142 return kMixamoBoneMap;
143 case HumanoidRigPreset::VRM:
144 return kVRMBoneMap;
145 case HumanoidRigPreset::UnrealMannequin:
146 return kUnrealMannequinBoneMap;
147 case HumanoidRigPreset::Count:
148 break;
149 }
150 return kMixamoBoneMap;
151}
152
153} // namespace Threedim