载入中...
搜索中...
未找到
AnimPose.cpp
浏览该文件的文档.
3
4#include "common/Exception.h"
5
6namespace eve::animation {
7
8namespace {
9
10TransformTRS mulTRS(const TransformTRS &parent, const TransformTRS &local) {
11 // world = parent * local (TRS, scale ignored in rotation path for FK positions)
12 TransformTRS out;
13 // Rotate local translation by parent rotation, then add parent translation * scales.
14 const float qx = parent.qx, qy = parent.qy, qz = parent.qz, qw = parent.qw;
15 const float lx = local.px * parent.sx;
16 const float ly = local.py * parent.sy;
17 const float lz = local.pz * parent.sz;
18 // q * v
19 const float ix = qw * lx + qy * lz - qz * ly;
20 const float iy = qw * ly + qz * lx - qx * lz;
21 const float iz = qw * lz + qx * ly - qy * lx;
22 const float iw = -qx * lx - qy * ly - qz * lz;
23 out.px = parent.px + (ix * qw + iw * -qx + iy * -qz - iz * -qy);
24 out.py = parent.py + (iy * qw + iw * -qy + iz * -qx - ix * -qz);
25 out.pz = parent.pz + (iz * qw + iw * -qz + ix * -qy - iy * -qx);
26
27 // Quaternion multiply parent * local
28 out.qw = parent.qw * local.qw - parent.qx * local.qx - parent.qy * local.qy - parent.qz * local.qz;
29 out.qx = parent.qw * local.qx + parent.qx * local.qw + parent.qy * local.qz - parent.qz * local.qy;
30 out.qy = parent.qw * local.qy - parent.qx * local.qz + parent.qy * local.qw + parent.qz * local.qx;
31 out.qz = parent.qw * local.qz + parent.qx * local.qy - parent.qy * local.qx + parent.qz * local.qw;
32 out.normalizeRotation();
33
34 out.sx = parent.sx * local.sx;
35 out.sy = parent.sy * local.sy;
36 out.sz = parent.sz * local.sz;
37 return out;
38}
39
40} // namespace
41
42AnimPose::AnimPose(int boneCount) { resize(boneCount); }
43
44void AnimPose::resize(int boneCount) {
45 if (boneCount < 0) throw Exception("AnimPose.resize: boneCount must be >= 0");
46 locals_.assign(static_cast<size_t>(boneCount), TransformTRS::identity());
47 worlds_.assign(static_cast<size_t>(boneCount), TransformTRS::identity());
48}
49
50void AnimPose::requireBone(int boneIndex) const {
51 if (boneIndex < 0 || boneIndex >= getBoneCount()) {
52 throw Exception("AnimPose: invalid bone index %d", boneIndex);
53 }
54}
55
56void AnimPose::copyFrom(const AnimPose *other) {
57 if (!other) throw Exception("AnimPose.copyFrom: other is null");
58 locals_ = other->locals_;
59 worlds_ = other->worlds_;
60}
61
62void AnimPose::blendFrom(const AnimPose *a, const AnimPose *b, float t) {
63 if (!a || !b) throw Exception("AnimPose.blendFrom: pose is null");
64 if (a->getBoneCount() != b->getBoneCount()) {
65 throw Exception("AnimPose.blendFrom: bone count mismatch");
66 }
67 resize(a->getBoneCount());
68 for (int i = 0; i < getBoneCount(); ++i) {
69 locals_[static_cast<size_t>(i)] =
70 blendTRS(a->locals_[static_cast<size_t>(i)], b->locals_[static_cast<size_t>(i)], t);
71 }
72}
73
75 requireBone(boneIndex);
76 return locals_[static_cast<size_t>(boneIndex)];
77}
78
79const TransformTRS &AnimPose::local(int boneIndex) const {
80 requireBone(boneIndex);
81 return locals_[static_cast<size_t>(boneIndex)];
82}
83
84void AnimPose::setLocalPosition(int boneIndex, float x, float y, float z) {
85 requireBone(boneIndex);
86 auto &t = locals_[static_cast<size_t>(boneIndex)];
87 t.px = x;
88 t.py = y;
89 t.pz = z;
90}
91
92void AnimPose::setLocalRotation(int boneIndex, float x, float y, float z, float w) {
93 requireBone(boneIndex);
94 auto &t = locals_[static_cast<size_t>(boneIndex)];
95 t.qx = x;
96 t.qy = y;
97 t.qz = z;
98 t.qw = w;
99 t.normalizeRotation();
100}
101
102void AnimPose::setLocalScale(int boneIndex, float x, float y, float z) {
103 requireBone(boneIndex);
104 auto &t = locals_[static_cast<size_t>(boneIndex)];
105 t.sx = x;
106 t.sy = y;
107 t.sz = z;
108}
109
110float AnimPose::getLocalPositionX(int boneIndex) const {
111 requireBone(boneIndex);
112 return locals_[static_cast<size_t>(boneIndex)].px;
113}
114float AnimPose::getLocalPositionY(int boneIndex) const {
115 requireBone(boneIndex);
116 return locals_[static_cast<size_t>(boneIndex)].py;
117}
118float AnimPose::getLocalPositionZ(int boneIndex) const {
119 requireBone(boneIndex);
120 return locals_[static_cast<size_t>(boneIndex)].pz;
121}
122float AnimPose::getLocalRotationX(int boneIndex) const {
123 requireBone(boneIndex);
124 return locals_[static_cast<size_t>(boneIndex)].qx;
125}
126float AnimPose::getLocalRotationY(int boneIndex) const {
127 requireBone(boneIndex);
128 return locals_[static_cast<size_t>(boneIndex)].qy;
129}
130float AnimPose::getLocalRotationZ(int boneIndex) const {
131 requireBone(boneIndex);
132 return locals_[static_cast<size_t>(boneIndex)].qz;
133}
134float AnimPose::getLocalRotationW(int boneIndex) const {
135 requireBone(boneIndex);
136 return locals_[static_cast<size_t>(boneIndex)].qw;
137}
138float AnimPose::getLocalScaleX(int boneIndex) const {
139 requireBone(boneIndex);
140 return locals_[static_cast<size_t>(boneIndex)].sx;
141}
142float AnimPose::getLocalScaleY(int boneIndex) const {
143 requireBone(boneIndex);
144 return locals_[static_cast<size_t>(boneIndex)].sy;
145}
146float AnimPose::getLocalScaleZ(int boneIndex) const {
147 requireBone(boneIndex);
148 return locals_[static_cast<size_t>(boneIndex)].sz;
149}
150
152 if (!skeleton) throw Exception("AnimPose.computeWorld: skeleton is null");
153 if (skeleton->getBoneCount() != getBoneCount()) {
154 throw Exception("AnimPose.computeWorld: bone count mismatch");
155 }
156 worlds_.resize(locals_.size());
157 for (int i = 0; i < getBoneCount(); ++i) {
158 const int parent = skeleton->getParent(i);
159 if (parent < 0) {
160 worlds_[static_cast<size_t>(i)] = locals_[static_cast<size_t>(i)];
161 } else {
162 worlds_[static_cast<size_t>(i)] =
163 mulTRS(worlds_[static_cast<size_t>(parent)], locals_[static_cast<size_t>(i)]);
164 }
165 }
166}
167
168float AnimPose::getWorldPositionX(int boneIndex) const {
169 requireBone(boneIndex);
170 return worlds_[static_cast<size_t>(boneIndex)].px;
171}
172float AnimPose::getWorldPositionY(int boneIndex) const {
173 requireBone(boneIndex);
174 return worlds_[static_cast<size_t>(boneIndex)].py;
175}
176float AnimPose::getWorldPositionZ(int boneIndex) const {
177 requireBone(boneIndex);
178 return worlds_[static_cast<size_t>(boneIndex)].pz;
179}
180float AnimPose::getWorldRotationX(int boneIndex) const {
181 requireBone(boneIndex);
182 return worlds_[static_cast<size_t>(boneIndex)].qx;
183}
184float AnimPose::getWorldRotationY(int boneIndex) const {
185 requireBone(boneIndex);
186 return worlds_[static_cast<size_t>(boneIndex)].qy;
187}
188float AnimPose::getWorldRotationZ(int boneIndex) const {
189 requireBone(boneIndex);
190 return worlds_[static_cast<size_t>(boneIndex)].qz;
191}
192float AnimPose::getWorldRotationW(int boneIndex) const {
193 requireBone(boneIndex);
194 return worlds_[static_cast<size_t>(boneIndex)].qw;
195}
196
197const TransformTRS &AnimPose::world(int boneIndex) const {
198 requireBone(boneIndex);
199 return worlds_[static_cast<size_t>(boneIndex)];
200}
201
202float AnimPose::getWorldMatrixElement(int boneIndex, int elementIndex) const {
203 requireBone(boneIndex);
204 if (elementIndex < 0 || elementIndex > 15) {
205 throw Exception("AnimPose.getWorldMatrixElement: elementIndex must be 0..15");
206 }
207 const Mat4 mat = Mat4::fromTRS(worlds_[static_cast<size_t>(boneIndex)]);
208 return mat.m[elementIndex];
209}
210
211void AnimPose::getWorldMatrix(int boneIndex, float *out16) const {
212 requireBone(boneIndex);
213 if (!out16) throw Exception("AnimPose.getWorldMatrix: out16 is null");
214 const Mat4 mat = Mat4::fromTRS(worlds_[static_cast<size_t>(boneIndex)]);
215 for (int i = 0; i < 16; ++i) out16[i] = mat.m[i];
216}
217
218} // namespace eve::animation
int y
Definition Grass.cpp:135
int z
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
int w
std::vector< Colorf > px
uint32_t a
uint32_t b
int parent
Definition TreeMesh.cpp:175
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:15
float getLocalRotationX(int boneIndex) const
Definition AnimPose.cpp:122
float getWorldRotationX(int boneIndex) const
Definition AnimPose.cpp:180
float getWorldPositionZ(int boneIndex) const
Definition AnimPose.cpp:176
float getLocalScaleZ(int boneIndex) const
Definition AnimPose.cpp:146
float getLocalPositionZ(int boneIndex) const
Definition AnimPose.cpp:118
void blendFrom(const AnimPose *a, const AnimPose *b, float t)
Definition AnimPose.cpp:62
int getBoneCount() const
Definition AnimPose.h:25
float getWorldMatrixElement(int boneIndex, int elementIndex) const
Column-major 4x4 world matrix for boneIndex after computeWorld(). elementIndex in [0,...
Definition AnimPose.cpp:202
float getLocalPositionX(int boneIndex) const
Definition AnimPose.cpp:110
float getLocalRotationW(int boneIndex) const
Definition AnimPose.cpp:134
float getWorldPositionX(int boneIndex) const
Definition AnimPose.cpp:168
void setLocalScale(int boneIndex, float x, float y, float z)
Definition AnimPose.cpp:102
const TransformTRS & world(int boneIndex) const
Definition AnimPose.cpp:197
float getLocalScaleX(int boneIndex) const
Definition AnimPose.cpp:138
float getWorldPositionY(int boneIndex) const
Definition AnimPose.cpp:172
void getWorldMatrix(int boneIndex, float *out16) const
Write 16 floats (column-major) into out16 (must not be null).
Definition AnimPose.cpp:211
void setLocalRotation(int boneIndex, float x, float y, float z, float w)
Definition AnimPose.cpp:92
float getWorldRotationW(int boneIndex) const
Definition AnimPose.cpp:192
float getWorldRotationZ(int boneIndex) const
Definition AnimPose.cpp:188
float getWorldRotationY(int boneIndex) const
Definition AnimPose.cpp:184
float getLocalScaleY(int boneIndex) const
Definition AnimPose.cpp:142
TransformTRS & local(int boneIndex)
Definition AnimPose.cpp:74
float getLocalRotationZ(int boneIndex) const
Definition AnimPose.cpp:130
void setLocalPosition(int boneIndex, float x, float y, float z)
Definition AnimPose.cpp:84
float getLocalPositionY(int boneIndex) const
Definition AnimPose.cpp:114
void copyFrom(const AnimPose *other)
Definition AnimPose.cpp:56
float getLocalRotationY(int boneIndex) const
Definition AnimPose.cpp:126
void computeWorld(const AnimSkeleton *skeleton)
Compute world transforms from local pose + skeleton hierarchy. World values readable via getWorld* af...
Definition AnimPose.cpp:151
void resize(int boneCount)
Definition AnimPose.cpp:44
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
int getParent(int boneIndex) const
TransformTRS blendTRS(const TransformTRS &a, const TransformTRS &b, float t)
Definition AnimMath.h:72
Column-major 4x4 matrix (OpenGL / glTF / Assimp-compatible layout). Elements: m[col * 4 + row].
Definition AnimMath.h:97
static Mat4 fromTRS(const TransformTRS &t)
Definition AnimMath.h:102
Local TRS used by skeletal animation (quaternion xyzw).
Definition AnimMath.h:9
static TransformTRS identity()
Definition AnimMath.h:14