载入中...
搜索中...
未找到
Skeleton3D.cpp
浏览该文件的文档.
1#include "ik/Skeleton3D.h"
2
3#include "common/Exception.h"
4
5namespace eve::ik {
6
8 ensureSorted();
9 ensureStateSize();
10}
11
12void Skeleton3D::ensureSorted() {
13 if (sk_.bones().empty()) {
14 sk_.topologicalSort();
15 }
16}
17
18void Skeleton3D::ensureStateSize() {
19 ensureSorted();
20 const unsigned n = static_cast<unsigned>(sk_.bones().size());
21 if (state_.size() < n) {
22 // Grow in place so existing joint poses survive createBone().
23 state_.position_.resize(n);
24 state_.orientation_.resize(n);
25 state_.scale_.resize(n);
26 state_.rotation_.resize(n);
27 }
28}
29
30::ik::bone3d *Skeleton3D::boneAt(int boneId) const {
31 if (boneId < 0) return nullptr;
32 const auto &bones = sk_.bones();
33 if (static_cast<size_t>(boneId) >= bones.size()) return nullptr;
34 return bones[static_cast<size_t>(boneId)];
35}
36
37void Skeleton3D::requireBone(int boneId) const {
38 if (!boneAt(boneId)) {
39 throw Exception("Skeleton3D: invalid bone id %d", boneId);
40 }
41}
42
44 ensureSorted();
45 requireBone(parentId);
46 if (length <= 0.f) {
47 throw Exception("Skeleton3D.createBone: length must be > 0");
48 }
49 ::ik::bone3d *parent = boneAt(parentId);
50 ::ik::bone3d *child = parent->createBone(length);
51 sk_.topologicalSort();
52 ensureStateSize();
53 return static_cast<int>(child->id);
54}
55
57 const_cast<Skeleton3D *>(this)->ensureSorted();
58 return static_cast<int>(sk_.bones().size());
59}
60
61int Skeleton3D::getParent(int boneId) const {
62 requireBone(boneId);
63 ::ik::bone3d *b = boneAt(boneId);
64 if (!b->parent) return -1;
65 return static_cast<int>(b->parent->id);
66}
67
68int Skeleton3D::getChildCount(int boneId) const {
69 requireBone(boneId);
70 return static_cast<int>(boneAt(boneId)->children.size());
71}
72
73int Skeleton3D::getChild(int boneId, int childIndex) const {
74 requireBone(boneId);
75 ::ik::bone3d *b = boneAt(boneId);
76 if (childIndex < 0 || static_cast<size_t>(childIndex) >= b->children.size()) {
77 throw Exception("Skeleton3D.getChild: childIndex out of range");
78 }
79 return static_cast<int>(b->children[static_cast<size_t>(childIndex)]->id);
80}
81
82float Skeleton3D::getLength(int boneId) const {
83 requireBone(boneId);
84 return boneAt(boneId)->length;
85}
86
87void Skeleton3D::setLength(int boneId, float length) {
88 requireBone(boneId);
89 if (boneId == 0) {
90 throw Exception("Skeleton3D.setLength: root length is always 0");
91 }
92 if (length <= 0.f) {
93 throw Exception("Skeleton3D.setLength: length must be > 0");
94 }
95 boneAt(boneId)->setLength(length);
96}
97
98void Skeleton3D::setPosition(int boneId, float x, float y, float z) {
99 requireBone(boneId);
100 ensureStateSize();
101 boneAt(boneId)->position(state_) = {x, y, z};
102}
103
104float Skeleton3D::getX(int boneId) const {
105 requireBone(boneId);
106 const_cast<Skeleton3D *>(this)->ensureStateSize();
107 return boneAt(boneId)->position(state_)[0];
108}
109
110float Skeleton3D::getY(int boneId) const {
111 requireBone(boneId);
112 const_cast<Skeleton3D *>(this)->ensureStateSize();
113 return boneAt(boneId)->position(state_)[1];
114}
115
116float Skeleton3D::getZ(int boneId) const {
117 requireBone(boneId);
118 const_cast<Skeleton3D *>(this)->ensureStateSize();
119 return boneAt(boneId)->position(state_)[2];
120}
121
122void Skeleton3D::setOrientation(int boneId, float x, float y, float z) {
123 requireBone(boneId);
124 ensureStateSize();
125 boneAt(boneId)->orientation(state_) = {x, y, z};
126}
127
128float Skeleton3D::getOrientationX(int boneId) const {
129 requireBone(boneId);
130 const_cast<Skeleton3D *>(this)->ensureStateSize();
131 return boneAt(boneId)->orientation(state_)[0];
132}
133
134float Skeleton3D::getOrientationY(int boneId) const {
135 requireBone(boneId);
136 const_cast<Skeleton3D *>(this)->ensureStateSize();
137 return boneAt(boneId)->orientation(state_)[1];
138}
139
140float Skeleton3D::getOrientationZ(int boneId) const {
141 requireBone(boneId);
142 const_cast<Skeleton3D *>(this)->ensureStateSize();
143 return boneAt(boneId)->orientation(state_)[2];
144}
145
146void Skeleton3D::setRotation(int boneId, float yaw, float pitch) {
147 requireBone(boneId);
148 ensureStateSize();
149 boneAt(boneId)->rotation(state_) = {yaw, pitch};
150}
151
152float Skeleton3D::getRotationYaw(int boneId) const {
153 requireBone(boneId);
154 const_cast<Skeleton3D *>(this)->ensureStateSize();
155 return boneAt(boneId)->rotation(state_)[0];
156}
157
158float Skeleton3D::getRotationPitch(int boneId) const {
159 requireBone(boneId);
160 const_cast<Skeleton3D *>(this)->ensureStateSize();
161 return boneAt(boneId)->rotation(state_)[1];
162}
163
164void Skeleton3D::setConstraints(int boneId, float minYaw, float minPitch, float maxYaw,
165 float maxPitch) {
166 requireBone(boneId);
167 if (minYaw > maxYaw || minPitch > maxPitch) {
168 throw Exception("Skeleton3D.setConstraints: min must be <= max per axis");
169 }
170 boneAt(boneId)->setConstraints(::ik::vec2{minYaw, minPitch},
171 ::ik::vec2{maxYaw, maxPitch});
172}
173
175 requireBone(boneId);
176 boneAt(boneId)->clearConstraints();
177}
178
179bool Skeleton3D::hasConstraints(int boneId) const {
180 requireBone(boneId);
181 return boneAt(boneId)->constrained;
182}
183
184void Skeleton3D::initStraightPose(float rootX, float rootY, float rootZ) {
185 ensureSorted();
186 ensureStateSize();
187 sk_.init_straight_pose(state_, ::ik::vec3{rootX, rootY, rootZ});
188}
189
191 ensureSorted();
192 ensureStateSize();
193 sk_.bind(state_);
194}
195
197 ensureSorted();
198 ensureStateSize();
199 sk_.forward_kinematics(state_);
200}
201
203 ensureSorted();
204 ensureStateSize();
205 sk_.update_rotations(state_);
206}
207
208float Skeleton3D::totalLengthTo(int boneId) const {
209 requireBone(boneId);
210 return sk_.total_length_to(boneAt(boneId));
211}
212
213} // namespace eve::ik
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
float length
Definition CaveMesh.cpp:94
std::uint64_t parentId
glm::vec3 n
Definition Grass.cpp:63
std::vector< Bone > bones
std::int32_t parent
MeleePoint3 b
Definition MeleeHit.cpp:41
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Script-facing 3D skeleton + pose state (ik::skeleton3d + ik::ecs3d). Local angles are yaw/pitch in th...
Definition Skeleton3D.h:13
void setPosition(int boneId, float x, float y, float z)
Sets the world-space bone position.
void setConstraints(int boneId, float minYaw, float minPitch, float maxYaw, float maxPitch)
Sets joint angle limits for the bone.
float getLength(int boneId) const
Rest length of the bone.
void setLength(int boneId, float length)
Sets the rest length of the bone.
void forwardKinematics()
Updates world positions from local rotations.
int getChildCount(int boneId) const
Number of direct children of boneId.
Skeleton3D()
Creates an empty 3D skeleton with a root bone.
Definition Skeleton3D.cpp:7
void bind()
Binds the current pose as the rest pose.
int createBone(int parentId, float length=1.f)
Create a child bone under parentId; returns new bone id.
float getRotationPitch(int boneId) const
Local pitch in radians.
void setRotation(int boneId, float yaw, float pitch)
Sets local hinge/yaw-pitch rotation (radians).
void setOrientation(int boneId, float x, float y, float z)
Sets the bone forward orientation vector.
void initStraightPose(float rootX=0.f, float rootY=0.f, float rootZ=0.f)
Initializes a straight chain pose from the root.
float totalLengthTo(int boneId) const
Sum of bone lengths from root to boneId inclusive.
float getOrientationZ(int boneId) const
Orientation vector Z.
void clearConstraints(int boneId)
Removes joint limits from the bone.
float getZ(int boneId) const
World-space Z of the bone (or component).
float getY(int boneId) const
World-space Y of the bone (or component).
float getOrientationY(int boneId) const
Orientation vector Y.
bool hasConstraints(int boneId) const
True if the bone has joint limits.
void updateRotations()
Derives local rotations from world positions.
float getX(int boneId) const
World-space X of the bone (or component).
int getChild(int boneId, int childIndex) const
Child bone id at childIndex under boneId.
float getOrientationX(int boneId) const
Orientation vector X.
float getRotationYaw(int boneId) const
Local yaw in radians.
int getParent(int boneId) const
Parent bone id, or -1 for the root.
int getBoneCount() const
Number of bones currently in the skeleton.
std::string id
Definition Widget.h:17