载入中...
搜索中...
未找到
PoseInertiaInternal.h
浏览该文件的文档.
1#pragma once
2
3#include <array>
4#include <cmath>
5#include <span>
6#include <vector>
8
10// Finite-duration offsets relative to a moving target. Inputs are copied;
11// simulation elapsed time is supplied by the owner, never wall-clock time.
14 using Channels = std::array<float, 9>;
15 std::vector<Channels> offsets, velocities;
17 float historyInterval = 0.f;
18 float duration = 0.f;
19
22 auto a = source, b = target;
23 a.normalizeRotation();
24 b.normalizeRotation();
25 // log(source * inverse(target)), with hemisphere-independent shortest arc.
26 float x = -a.qw * b.qx + a.qx * b.qw - a.qy * b.qz + a.qz * b.qy;
27 float y = -a.qw * b.qy + a.qx * b.qz + a.qy * b.qw - a.qz * b.qx;
28 float z = -a.qw * b.qz - a.qx * b.qy + a.qy * b.qx + a.qz * b.qw;
29 float w = a.qw * b.qw + a.qx * b.qx + a.qy * b.qy + a.qz * b.qz;
30 if (w < 0.f) {
31 x = -x;
32 y = -y;
33 z = -z;
34 w = -w;
35 }
36 float length = std::sqrt(x * x + y * y + z * z);
37 float factor = length > 1e-8f ? 2.f * std::atan2(length, w) / length : 2.f;
38 return {a.px - b.px, a.py - b.py, a.pz - b.pz, x * factor, y * factor,
39 z * factor, a.sx - b.sx, a.sy - b.sy, a.sz - b.sz};
40 }
41
43 void begin(const AnimPose& source, const AnimPose& target, const AnimPose& previousTarget, float seconds) {
44 duration = seconds;
45 offsets.resize(source.getBoneCount());
46 velocities.resize(source.getBoneCount());
47 bool history = historyInterval > 1e-6f && previousOutput.getBoneCount() == source.getBoneCount();
48 for (int bone = 0; bone < source.getBoneCount(); ++bone) {
49 offsets[bone] = difference(source.local(bone), target.local(bone));
50 velocities[bone].fill(0.f);
51 if (!history) continue;
52 auto previous = difference(previousOutput.local(bone), previousTarget.local(bone));
53 // At the pi branch cut, use the equivalent log closest to the current offset.
54 float dot = 0.f, length = 0.f;
55 for (int c = 3; c < 6; ++c) {
56 dot += previous[c] * offsets[bone][c];
57 length += previous[c] * previous[c];
58 }
59 length = std::sqrt(length);
60 if (dot < 0.f && length > 1.57079632679f) {
61 float factor = (length - 6.28318530718f) / length;
62 for (int c = 3; c < 6; ++c) previous[c] *= factor;
63 }
64 for (int c = 0; c < 9; ++c) velocities[bone][c] = (offsets[bone][c] - previous[c]) / historyInterval;
65 }
66 }
67
69 void remember(const AnimPose& output, float dt) {
70 if (dt <= 0.f) return;
72 historyInterval = dt;
73 }
74
76 void apply(const AnimPose& target, float elapsed, AnimPose& output, std::span<const float> factors = {}) const {
77 output.copyFrom(&target);
78 if (duration <= 0.f || elapsed >= duration) return;
79 for (int bone = 0; bone < target.getBoneCount(); ++bone) {
80 const float boneDuration = duration * (factors.empty() ? 1.f : factors[bone]);
81 if (boneDuration <= 0.f || elapsed >= boneDuration) continue;
82 float u = std::clamp(elapsed / boneDuration, 0.f, 1.f), u2 = u * u, u3 = u2 * u, u4 = u3 * u, u5 = u4 * u;
83 float position = 1.f - 10.f * u3 + 15.f * u4 - 6.f * u5;
84 float velocity = boneDuration * (u - 6.f * u3 + 8.f * u4 - 3.f * u5);
86 for (int c = 0; c < 9; ++c) value[c] = offsets[bone][c] * position + velocities[bone][c] * velocity;
87 auto& result = output.local(bone);
88 result.px += value[0];
89 result.py += value[1];
90 result.pz += value[2];
91 result.sx += value[6];
92 result.sy += value[7];
93 result.sz += value[8];
94 float angle = std::sqrt(value[3] * value[3] + value[4] * value[4] + value[5] * value[5]);
95 float factor = angle > 1e-8f ? std::sin(angle * .5f) / angle : .5f;
96 float x = value[3] * factor, y = value[4] * factor, z = value[5] * factor, w = std::cos(angle * .5f);
97 auto q = result;
98 result.qx = w * q.qx + x * q.qw + y * q.qz - z * q.qy;
99 result.qy = w * q.qy - x * q.qz + y * q.qw + z * q.qx;
100 result.qz = w * q.qz + x * q.qy - y * q.qx + z * q.qw;
101 result.qw = w * q.qw - x * q.qx - y * q.qy - z * q.qz;
102 result.normalizeRotation();
103 }
104 }
105};
106} // namespace eve::animation::detail
LogicalId target
double value
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string output
float length
Definition CaveMesh.cpp:94
float u
Definition Grass.cpp:233
std::array< double, 10 > q
std::int32_t c
std::array< float, 3 > position
std::uint32_t bone
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
const UnitySourceAsset & source
float angle
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:17
int getBoneCount() const
Returns the bone count.
Definition AnimPose.h:36
TransformTRS & local(int boneIndex)
Local.
Definition AnimPose.cpp:126
void copyFrom(const AnimPose *other)
Copies from.
Definition AnimPose.cpp:91
Local TRS used by skeletal animation (quaternion xyzw).
Definition AnimMath.h:9
void remember(const AnimPose &output, float dt)
Remember.
static Channels difference(const TransformTRS &source, const TransformTRS &target)
Difference.
void begin(const AnimPose &source, const AnimPose &target, const AnimPose &previousTarget, float seconds)
Begins .
void apply(const AnimPose &target, float elapsed, AnimPose &output, std::span< const float > factors={}) const
Applies .