Loading...
Searching...
No Matches
HumanoidSourceMaps.hpp
1#pragma once
2
3// Source-side tables for HumanoidRetarget's conversion step: per-workflow
4// keypoint->bone mapping (BlazePose 33, COCO-17, RTMPose Whole 133), the
5// canonical T-pose bone axes used as the rest direction in the shortest-arc
6// computation, and the bone hierarchy needed to turn world rotations into
7// parent-relative quaternions.
8
9#include <Threedim/HumanoidPose.hpp>
10
11#include <array>
12#include <cstdint>
13
14namespace Threedim
15{
16
17// ---------------------------------------------------------------------------
18// Bone tree: for each canonical bone, its parent bone (or Count if root).
19// Matches the humanoid_bone_index enum order.
20// ---------------------------------------------------------------------------
21inline constexpr std::array<
22 humanoid_bone_index,
23 std::size_t(humanoid_bone_index::Count)>
24 kHumanoidParent = {{
25 humanoid_bone_index::Count, // Hips (root)
26 humanoid_bone_index::Hips, // Spine
27 humanoid_bone_index::Spine, // Chest
28 humanoid_bone_index::Chest, // Neck
29 humanoid_bone_index::Neck, // Head
30
31 humanoid_bone_index::Chest, // LeftShoulder
32 humanoid_bone_index::LeftShoulder, // LeftUpperArm
33 humanoid_bone_index::LeftUpperArm, // LeftLowerArm
34 humanoid_bone_index::LeftLowerArm, // LeftHand
35
36 humanoid_bone_index::Chest, // RightShoulder
37 humanoid_bone_index::RightShoulder, // RightUpperArm
38 humanoid_bone_index::RightUpperArm, // RightLowerArm
39 humanoid_bone_index::RightLowerArm, // RightHand
40
41 humanoid_bone_index::Hips, // LeftUpperLeg
42 humanoid_bone_index::LeftUpperLeg, // LeftLowerLeg
43 humanoid_bone_index::LeftLowerLeg, // LeftFoot
44 humanoid_bone_index::LeftFoot, // LeftToes
45
46 humanoid_bone_index::Hips, // RightUpperLeg
47 humanoid_bone_index::RightUpperLeg, // RightLowerLeg
48 humanoid_bone_index::RightLowerLeg, // RightFoot
49 humanoid_bone_index::RightFoot, // RightToes
50 }};
51
52// ---------------------------------------------------------------------------
53// Canonical T-pose bone axes. Y-up, right-handed, model facing +Z. Each entry
54// is the world-space unit direction the bone's parent->child segment points in
55// the canonical T-pose, used as the "from" vector of the shortest-arc rotation
56// onto the landmark-derived direction.
57//
58// spine / neck / head +Y arms -X left, +X right
59// legs -Y toes +Z
60// shoulders toward the upper-arm, horizontal
61// hips the root, identity
62// ---------------------------------------------------------------------------
63inline constexpr std::array<
64 std::array<float, 3>,
65 std::size_t(humanoid_bone_index::Count)>
66 kHumanoidRestAxis = {{
67 {0.f, 0.f, 0.f}, // Hips — root, no direction
68 {0.f, 1.f, 0.f}, // Spine +Y
69 {0.f, 1.f, 0.f}, // Chest +Y
70 {0.f, 1.f, 0.f}, // Neck +Y
71 {0.f, 1.f, 0.f}, // Head +Y
72
73 {-1.f, 0.f, 0.f}, // LeftShoulder -X
74 {-1.f, 0.f, 0.f}, // LeftUpperArm -X
75 {-1.f, 0.f, 0.f}, // LeftLowerArm -X
76 {-1.f, 0.f, 0.f}, // LeftHand -X
77
78 {1.f, 0.f, 0.f}, // RightShoulder +X
79 {1.f, 0.f, 0.f}, // RightUpperArm +X
80 {1.f, 0.f, 0.f}, // RightLowerArm +X
81 {1.f, 0.f, 0.f}, // RightHand +X
82
83 {0.f, -1.f, 0.f}, // LeftUpperLeg -Y
84 {0.f, -1.f, 0.f}, // LeftLowerLeg -Y
85 {0.f, -1.f, 0.f}, // LeftFoot -Y
86 {0.f, 0.f, 1.f}, // LeftToes +Z
87
88 {0.f, -1.f, 0.f}, // RightUpperLeg -Y
89 {0.f, -1.f, 0.f}, // RightLowerLeg -Y
90 {0.f, -1.f, 0.f}, // RightFoot -Y
91 {0.f, 0.f, 1.f}, // RightToes +Z
92 }};
93
94// ---------------------------------------------------------------------------
95// Keypoint mapping: for each canonical bone, (parent_keypoint_idx,
96// child_keypoint_idx) into the workflow's keypoint array. -1 means this
97// bone isn't derivable from this workflow (the adapter will skip it,
98// keeping the target bone at its rest rotation).
99// ---------------------------------------------------------------------------
101{
102 int16_t parent_idx{-1};
103 int16_t child_idx{-1};
104 bool valid() const noexcept { return parent_idx >= 0 && child_idx >= 0; }
105};
106
107using HumanoidKeypointMap = std::array<
109 std::size_t(humanoid_bone_index::Count)>;
110
111// ---------------------------------------------------------------------------
112// BlazePose (33 landmarks).
113// 0: nose, 1: left_eye_inner, 2: left_eye, 3: left_eye_outer,
114// 4: right_eye_inner, 5: right_eye, 6: right_eye_outer,
115// 7: left_ear, 8: right_ear, 9: mouth_left, 10: mouth_right,
116// 11: left_shoulder, 12: right_shoulder, 13: left_elbow, 14: right_elbow,
117// 15: left_wrist, 16: right_wrist,
118// 17..22: left/right pinky/index/thumb,
119// 23: left_hip, 24: right_hip, 25: left_knee, 26: right_knee,
120// 27: left_ankle, 28: right_ankle, 29: left_heel, 30: right_heel,
121// 31: left_foot_index, 32: right_foot_index
122//
123// Bone directions are parent_kp -> child_kp. Spine, chest, neck and the
124// shoulder bones want a hips/shoulders midpoint; they are approximated with a
125// single side (left_hip -> left_shoulder and so on), which a precise version
126// would replace with synthesized virtual landmarks. Toes are ankle ->
127// foot_index.
128// ---------------------------------------------------------------------------
129inline constexpr HumanoidKeypointMap kBlazePoseMap = {{
130 {-1, -1}, // Hips (root)
131 {23, 11}, // Spine: left_hip → left_shoulder
132 {11, 12}, // Chest: shoulders pair (approximation)
133 {11, 0}, // Neck: left_shoulder → nose (approx)
134 {0, 2}, // Head: nose → left_eye (approx)
135
136 {11, 11}, // LeftShoulder (collar): degenerate — map skipped by validity
137 {11, 13}, // LeftUpperArm: left_shoulder → left_elbow
138 {13, 15}, // LeftLowerArm: left_elbow → left_wrist
139 {15, 19}, // LeftHand: left_wrist → left_index
140
141 {12, 12}, // RightShoulder (collar): skipped
142 {12, 14}, // RightUpperArm
143 {14, 16}, // RightLowerArm
144 {16, 20}, // RightHand
145
146 {23, 25}, // LeftUpperLeg
147 {25, 27}, // LeftLowerLeg
148 {27, 29}, // LeftFoot
149 {27, 31}, // LeftToes: ankle → foot_index
150
151 {24, 26}, // RightUpperLeg
152 {26, 28}, // RightLowerLeg
153 {28, 30}, // RightFoot
154 {28, 32}, // RightToes
155}};
156
157// ---------------------------------------------------------------------------
158// COCO-17 layout (YOLO-pose, ViTPose, RTMPose_COCO).
159// 0: nose, 1: left_eye, 2: right_eye, 3: left_ear, 4: right_ear,
160// 5: left_shoulder, 6: right_shoulder, 7: left_elbow, 8: right_elbow,
161// 9: left_wrist, 10: right_wrist, 11: left_hip, 12: right_hip,
162// 13: left_knee, 14: right_knee, 15: left_ankle, 16: right_ankle
163//
164// No toes, feet or fingers: those bones are flagged unmappable and keep their
165// target rest rotation.
166// ---------------------------------------------------------------------------
167inline constexpr HumanoidKeypointMap kCoco17Map = {{
168 {-1, -1}, // Hips
169 {11, 5}, // Spine: left_hip → left_shoulder (approx)
170 {5, 6}, // Chest: shoulders (approx)
171 {5, 0}, // Neck: shoulder → nose (approx)
172 {0, 1}, // Head: nose → left_eye
173
174 {-1, -1}, // LeftShoulder — no dedicated landmark
175 {5, 7}, // LeftUpperArm
176 {7, 9}, // LeftLowerArm
177 {-1, -1}, // LeftHand — no wrist-to-hand direction in COCO
178
179 {-1, -1}, // RightShoulder
180 {6, 8}, // RightUpperArm
181 {8, 10}, // RightLowerArm
182 {-1, -1}, // RightHand
183
184 {11, 13}, // LeftUpperLeg
185 {13, 15}, // LeftLowerLeg
186 {-1, -1}, // LeftFoot — ankle only
187 {-1, -1}, // LeftToes
188
189 {12, 14}, // RightUpperLeg
190 {14, 16}, // RightLowerLeg
191 {-1, -1}, // RightFoot
192 {-1, -1}, // RightToes
193}};
194
195// ---------------------------------------------------------------------------
196// RTMPose Whole-body 133 keypoints — first 17 match COCO, 17..22 face,
197// 23..90 face mesh, 91..132 hands. For body retargeting we reuse the
198// first 17 (same as COCO), and optionally pull finger landmarks for a
199// richer hand (Hand bone direction = wrist → middle_finger_mcp).
200// ---------------------------------------------------------------------------
201inline constexpr HumanoidKeypointMap kRTMPoseWholeMap = kCoco17Map;
202
203} // namespace Threedim
Definition HumanoidSourceMaps.hpp:101