载入中...
搜索中...
未找到
AnimControlMath.h
浏览该文件的文档.
1#pragma once
2
3#include <cmath>
4#include <algorithm>
5
6namespace eve::animation {
7
21 float k1 = 0.f;
22 float k2 = 1.f;
23 float k3 = 0.f;
24};
25
27inline SecondOrderCoeffs makeSecondOrderCoeffs(float frequencyHz, float dampingZeta,
28 float response) {
29 const float f = std::max(frequencyHz, 1e-4f);
30 const float z = std::max(dampingZeta, 0.f);
31 const float twoPiF = 6.283185307179586f * f;
33 c.k1 = z / (3.141592653589793f * f);
34 c.k2 = 1.f / (twoPiF * twoPiF);
35 c.k3 = response * z / twoPiF;
36 return c;
37}
38
44inline void stepSecondOrder(float dt, float x, float xd, const SecondOrderCoeffs &c, float &y,
45 float &yd) {
46 if (dt <= 0.f) return;
47 const float k2Stable = std::max(c.k2, std::max(dt * dt * 0.5f + dt * c.k1 * 0.5f, dt * c.k1));
48 y += dt * yd;
49 yd += dt * (x + c.k3 * xd - y - c.k1 * yd) / k2Stable;
50}
51
54 float posPos = 1.f;
55 float posVel = 0.f;
56 float velPos = 0.f;
57 float velVel = 1.f;
58};
59
61inline DampedSpringStep makeDampedSpringStep(float dt, float angularFrequency, float dampingRatio) {
63 if (dt <= 0.f || angularFrequency <= 0.f) return s;
64
65 const float eps = 1e-4f;
66 const float omega = angularFrequency;
67 const float zeta = std::max(dampingRatio, 0.f);
68
69 if (zeta > 1.f + eps) {
70 // Over-damped
71 const float za = -omega * zeta;
72 const float zb = omega * std::sqrt(zeta * zeta - 1.f);
73 const float z1 = za - zb;
74 const float z2 = za + zb;
75 const float e1 = std::exp(z1 * dt);
76 const float e2 = std::exp(z2 * dt);
77 const float invTwoZb = 1.f / (2.f * zb);
78 const float e1Over = e1 * invTwoZb;
79 const float e2Over = e2 * invTwoZb;
80 const float z1e1 = z1 * e1Over;
81 const float z2e2 = z2 * e2Over;
82 s.posPos = e1Over * z2 - z2e2 + e2;
83 s.posVel = -e1Over + e2Over;
84 s.velPos = (z1e1 - z2e2 + e2) * z2;
85 s.velVel = -z1e1 + z2e2;
86 } else if (zeta < 1.f - eps) {
87 // Under-damped
88 const float omegaZeta = omega * zeta;
89 const float alpha = omega * std::sqrt(1.f - zeta * zeta);
90 const float expTerm = std::exp(-omegaZeta * dt);
91 const float cosTerm = std::cos(alpha * dt);
92 const float sinTerm = std::sin(alpha * dt);
93 const float invAlpha = 1.f / alpha;
94 const float expSin = expTerm * sinTerm;
95 const float expCos = expTerm * cosTerm;
96 const float expOzSin = expTerm * omegaZeta * sinTerm * invAlpha;
97 s.posPos = expCos + expOzSin;
98 s.posVel = expSin * invAlpha;
99 s.velPos = -expSin * alpha - omegaZeta * expOzSin;
100 s.velVel = expCos - expOzSin;
101 } else {
102 // Critically damped
103 const float expTerm = std::exp(-omega * dt);
104 const float timeExp = dt * expTerm;
105 const float timeExpFreq = timeExp * omega;
106 s.posPos = timeExpFreq + expTerm;
107 s.posVel = timeExp;
108 s.velPos = -omega * timeExpFreq;
109 s.velVel = -timeExpFreq + expTerm;
110 }
111 return s;
112}
113
115inline void stepDampedSpring(float dt, float target, float angularFrequency, float dampingRatio,
116 float &pos, float &vel) {
117 const DampedSpringStep s = makeDampedSpringStep(dt, angularFrequency, dampingRatio);
118 const float oldPos = pos - target;
119 const float oldVel = vel;
120 const float newPos = oldPos * s.posPos + oldVel * s.posVel;
121 const float newVel = oldPos * s.velPos + oldVel * s.velVel;
122 pos = newPos + target;
123 vel = newVel;
124}
125
127inline void pdGainsFromOmegaZeta(float omega, float zeta, float &kp, float &kd) {
128 const float w = std::max(omega, 0.f);
129 const float z = std::max(zeta, 0.f);
130 kp = w * w;
131 kd = 2.f * z * w;
132}
133
138inline void stepPd(float dt, float target, float targetVel, float kp, float kd, float &y,
139 float &yd) {
140 if (dt <= 0.f) return;
141 const float a = kp * (target - y) + kd * (targetVel - yd);
142 yd += a * dt;
143 y += yd * dt;
144}
145
147inline float hzToOmega(float frequencyHz) {
148 return 6.283185307179586f * std::max(frequencyHz, 0.f);
149}
150
151} // namespace eve::animation
LogicalId target
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
const std::string & s
std::int32_t c
MeleePoint3 a
Definition MeleeHit.cpp:40
float f
void stepPd(float dt, float target, float targetVel, float kp, float kd, float &y, float &yd)
Semi-implicit Euler PD step (unit mass): a = Kp (target − y) + Kd (targetVel − yd),...
void stepSecondOrder(float dt, float x, float xd, const SecondOrderCoeffs &c, float &y, float &yd)
Stable semi-implicit Euler step for a second-order tracker. Estimates input velocity from consecutive...
DampedSpringStep makeDampedSpringStep(float dt, float angularFrequency, float dampingRatio)
Make damped spring step.
void pdGainsFromOmegaZeta(float omega, float zeta, float &kp, float &kd)
Unit-mass PD gains from natural frequency ω (rad/s) and damping ratio ζ.
SecondOrderCoeffs makeSecondOrderCoeffs(float frequencyHz, float dampingZeta, float response)
Build second-order coefficients from frequency (Hz), damping ζ, response r.
float hzToOmega(float frequencyHz)
ω (rad/s) from frequency in Hz.
void stepDampedSpring(float dt, float target, float angularFrequency, float dampingRatio, float &pos, float &vel)
Advance position/velocity relative to a set-point using closed-form spring step.
Closed-form coefficients for one damped-spring time step (Juckett).
Control-theory helpers for procedural animation.