载入中...
搜索中...
未找到
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
43int Skeleton3D::createBone(int parentId, float length) {
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
int y
Definition Grass.cpp:135
int z
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
glm::vec3 n
Definition Grass.cpp:64
uint32_t b
int parent
Definition TreeMesh.cpp:175
Script-facing 3D skeleton + pose state (ik::skeleton3d + ik::ecs3d). Local angles are yaw/pitch in th...
Definition Skeleton3D.h:11
void setPosition(int boneId, float x, float y, float z)
void setConstraints(int boneId, float minYaw, float minPitch, float maxYaw, float maxPitch)
float getLength(int boneId) const
void setLength(int boneId, float length)
int getChildCount(int boneId) const
int createBone(int parentId, float length=1.f)
float getRotationPitch(int boneId) const
void setRotation(int boneId, float yaw, float pitch)
void setOrientation(int boneId, float x, float y, float z)
void initStraightPose(float rootX=0.f, float rootY=0.f, float rootZ=0.f)
float totalLengthTo(int boneId) const
float getOrientationZ(int boneId) const
void clearConstraints(int boneId)
float getZ(int boneId) const
float getY(int boneId) const
float getOrientationY(int boneId) const
bool hasConstraints(int boneId) const
float getX(int boneId) const
int getChild(int boneId, int childIndex) const
float getOrientationX(int boneId) const
float getRotationYaw(int boneId) const
int getParent(int boneId) const
int getBoneCount() const
std::string id
Definition Widget.h:15