forked from orangeduck/Motion-Matching
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspring.h
214 lines (178 loc) · 5.27 KB
/
spring.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#pragma once
#include "common.h"
#include "vec.h"
#include "quat.h"
//--------------------------------------
static inline float damper_implicit(float x, float g, float halflife, float dt, float eps=1e-5f)
{
return lerpf(x, g, 1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
static inline vec3 damper_implicit(vec3 x, vec3 g, float halflife, float dt, float eps=1e-5f)
{
return lerp(x, g, 1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
static inline quat damper_implicit(quat x, quat g, float halflife, float dt, float eps=1e-5f)
{
return quat_slerp_shortest_approx(x, g, 1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
static inline float damp_adjustment_implicit(float g, float halflife, float dt, float eps=1e-5f)
{
return g * (1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
static inline vec3 damp_adjustment_implicit(vec3 g, float halflife, float dt, float eps=1e-5f)
{
return g * (1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
static inline quat damp_adjustment_implicit(quat g, float halflife, float dt, float eps=1e-5f)
{
return quat_slerp_shortest_approx(quat(), g, 1.0f - fast_negexpf((LN2f * dt) / (halflife + eps)));
}
//--------------------------------------
static inline float halflife_to_damping(float halflife, float eps = 1e-5f)
{
return (4.0f * LN2f) / (halflife + eps);
}
static inline float damping_to_halflife(float damping, float eps = 1e-5f)
{
return (4.0f * LN2f) / (damping + eps);
}
static inline float frequency_to_stiffness(float frequency)
{
return squaref(2.0f * PIf * frequency);
}
static inline float stiffness_to_frequency(float stiffness)
{
return sqrtf(stiffness) / (2.0f * PIf);
}
//--------------------------------------
static inline void simple_spring_damper_implicit(
float& x,
float& v,
const float x_goal,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
float j0 = x - x_goal;
float j1 = v + j0*y;
float eydt = fast_negexpf(y*dt);
x = eydt*(j0 + j1*dt) + x_goal;
v = eydt*(v - j1*y*dt);
}
static inline void simple_spring_damper_implicit(
vec3& x,
vec3& v,
const vec3 x_goal,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
vec3 j0 = x - x_goal;
vec3 j1 = v + j0*y;
float eydt = fast_negexpf(y*dt);
x = eydt*(j0 + j1*dt) + x_goal;
v = eydt*(v - j1*y*dt);
}
static inline void simple_spring_damper_implicit(
quat& x,
vec3& v,
const quat x_goal,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
vec3 j0 = quat_to_scaled_angle_axis(quat_abs(quat_mul(x, quat_inv(x_goal))));
vec3 j1 = v + j0*y;
float eydt = fast_negexpf(y*dt);
x = quat_mul(quat_from_scaled_angle_axis(eydt*(j0 + j1*dt)), x_goal);
v = eydt*(v - j1*y*dt);
}
//--------------------------------------
static inline void decay_spring_damper_implicit(
float& x,
float& v,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
float j1 = v + x*y;
float eydt = fast_negexpf(y*dt);
x = eydt*(x + j1*dt);
v = eydt*(v - j1*y*dt);
}
static inline void decay_spring_damper_implicit(
vec3& x,
vec3& v,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
vec3 j1 = v + x*y;
float eydt = fast_negexpf(y*dt);
x = eydt*(x + j1*dt);
v = eydt*(v - j1*y*dt);
}
static inline void decay_spring_damper_implicit(
quat& x,
vec3& v,
const float halflife,
const float dt)
{
float y = halflife_to_damping(halflife) / 2.0f;
vec3 j0 = quat_to_scaled_angle_axis(x);
vec3 j1 = v + j0*y;
float eydt = fast_negexpf(y*dt);
x = quat_from_scaled_angle_axis(eydt*(j0 + j1*dt));
v = eydt*(v - j1*y*dt);
}
//--------------------------------------
static inline void inertialize_transition(
vec3& off_x,
vec3& off_v,
const vec3 src_x,
const vec3 src_v,
const vec3 dst_x,
const vec3 dst_v)
{
off_x = (src_x + off_x) - dst_x;
off_v = (src_v + off_v) - dst_v;
}
static inline void inertialize_update(
vec3& out_x,
vec3& out_v,
vec3& off_x,
vec3& off_v,
const vec3 in_x,
const vec3 in_v,
const float halflife,
const float dt)
{
decay_spring_damper_implicit(off_x, off_v, halflife, dt);
out_x = in_x + off_x;
out_v = in_v + off_v;
}
static inline void inertialize_transition(
quat& off_x,
vec3& off_v,
const quat src_x,
const vec3 src_v,
const quat dst_x,
const vec3 dst_v)
{
off_x = quat_abs(quat_mul(quat_mul(off_x, src_x), quat_inv(dst_x)));
off_v = (off_v + src_v) - dst_v;
}
static inline void inertialize_update(
quat& out_x,
vec3& out_v,
quat& off_x,
vec3& off_v,
const quat in_x,
const vec3 in_v,
const float halflife,
const float dt)
{
decay_spring_damper_implicit(off_x, off_v, halflife, dt);
out_x = quat_mul(off_x, in_x);
out_v = off_v + in_v;
}