physics-animator 0.2.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/cjs/Animator.js +255 -157
- package/dist/cjs/IFieldAnimator.js +8 -0
- package/dist/cjs/{Spring.js → animators/SpringAnimator.js} +57 -12
- package/dist/cjs/animators/TweenAnimator.js +75 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/react/useSpringValue.js +12 -42
- package/dist/esm/Animator.js +254 -156
- package/dist/esm/IFieldAnimator.js +5 -0
- package/dist/esm/{Spring.js → animators/SpringAnimator.js} +56 -11
- package/dist/esm/animators/TweenAnimator.js +68 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/react/useSpringValue.js +12 -42
- package/dist/types/Animator.d.ts +88 -63
- package/dist/types/IFieldAnimator.d.ts +9 -0
- package/dist/types/{Spring.d.ts → animators/SpringAnimator.d.ts} +11 -1
- package/dist/types/animators/TweenAnimator.d.ts +21 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/react/useSpringState.d.ts +1 -1
- package/dist/types/react/useSpringValue.d.ts +1 -1
- package/package.json +2 -10
- package/dist/cjs/three/ThreeAnimator.js +0 -453
- package/dist/cjs/three/index.js +0 -17
- package/dist/esm/three/ThreeAnimator.js +0 -450
- package/dist/esm/three/index.js +0 -1
- package/dist/types/three/ThreeAnimator.d.ts +0 -56
- package/dist/types/three/index.d.ts +0 -1
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
import { Euler, Matrix4, Quaternion, Vector2, Vector3, Vector4 } from "three";
|
|
2
|
-
import { Animator, Tween } from "../Animator.js";
|
|
3
|
-
import { Spring } from "../Spring.js";
|
|
4
|
-
export var QuaternionSpringMode;
|
|
5
|
-
(function (QuaternionSpringMode) {
|
|
6
|
-
QuaternionSpringMode[QuaternionSpringMode["DirectionRollCartesian"] = 0] = "DirectionRollCartesian";
|
|
7
|
-
QuaternionSpringMode[QuaternionSpringMode["YawPitchRoll"] = 1] = "YawPitchRoll";
|
|
8
|
-
})(QuaternionSpringMode || (QuaternionSpringMode = {}));
|
|
9
|
-
/**
|
|
10
|
-
* Extends Animator to add support for animating vectors and quaternions
|
|
11
|
-
*/
|
|
12
|
-
export class ThreeAnimator {
|
|
13
|
-
animator;
|
|
14
|
-
get onAfterStep() {
|
|
15
|
-
return this.animator.onAfterStep;
|
|
16
|
-
}
|
|
17
|
-
get onBeforeStep() {
|
|
18
|
-
return this.animator.onBeforeStep;
|
|
19
|
-
}
|
|
20
|
-
quaternionSprings = new Map();
|
|
21
|
-
constructor(animator = new Animator()) {
|
|
22
|
-
this.animator = animator;
|
|
23
|
-
this.animator.onBeforeStep.on(e => this.stepQuaternionSprings(e.dt_s));
|
|
24
|
-
}
|
|
25
|
-
setTo(object, field, target) {
|
|
26
|
-
if (target instanceof Vector4) {
|
|
27
|
-
let v = object[field];
|
|
28
|
-
this.animator.setTo(v, 'x', target.x);
|
|
29
|
-
this.animator.setTo(v, 'y', target.y);
|
|
30
|
-
this.animator.setTo(v, 'z', target.z);
|
|
31
|
-
this.animator.setTo(v, 'w', target.w);
|
|
32
|
-
}
|
|
33
|
-
else if (target instanceof Vector3) {
|
|
34
|
-
let v = object[field];
|
|
35
|
-
this.animator.setTo(v, 'x', target.x);
|
|
36
|
-
this.animator.setTo(v, 'y', target.y);
|
|
37
|
-
this.animator.setTo(v, 'z', target.z);
|
|
38
|
-
}
|
|
39
|
-
else if (target instanceof Vector2) {
|
|
40
|
-
let v = object[field];
|
|
41
|
-
this.animator.setTo(v, 'x', target.x);
|
|
42
|
-
this.animator.setTo(v, 'y', target.y);
|
|
43
|
-
}
|
|
44
|
-
else if (target instanceof Quaternion) {
|
|
45
|
-
let q = object[field];
|
|
46
|
-
this.animator.setTo(q, 'x', target.x);
|
|
47
|
-
this.animator.setTo(q, 'y', target.y);
|
|
48
|
-
this.animator.setTo(q, 'z', target.z);
|
|
49
|
-
this.animator.setTo(q, 'w', target.w);
|
|
50
|
-
}
|
|
51
|
-
else if (target instanceof Euler) {
|
|
52
|
-
let e = object[field];
|
|
53
|
-
this.animator.setTo(e, 'x', target.x);
|
|
54
|
-
this.animator.setTo(e, 'y', target.y);
|
|
55
|
-
this.animator.setTo(e, 'z', target.z);
|
|
56
|
-
e.order = target.order;
|
|
57
|
-
}
|
|
58
|
-
else { // number
|
|
59
|
-
this.animator.setTo(object, field, target);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
springTo(object, field, target, params = { duration_s: 0.5 }, mode) {
|
|
63
|
-
if (target instanceof Vector4) {
|
|
64
|
-
let v = object[field];
|
|
65
|
-
this.animator.springTo(v, 'x', target.x, params);
|
|
66
|
-
this.animator.springTo(v, 'y', target.y, params);
|
|
67
|
-
this.animator.springTo(v, 'z', target.z, params);
|
|
68
|
-
this.animator.springTo(v, 'w', target.w, params);
|
|
69
|
-
}
|
|
70
|
-
else if (target instanceof Vector3) {
|
|
71
|
-
let v = object[field];
|
|
72
|
-
this.animator.springTo(v, 'x', target.x, params);
|
|
73
|
-
this.animator.springTo(v, 'y', target.y, params);
|
|
74
|
-
this.animator.springTo(v, 'z', target.z, params);
|
|
75
|
-
}
|
|
76
|
-
else if (target instanceof Vector2) {
|
|
77
|
-
let v = object[field];
|
|
78
|
-
this.animator.springTo(v, 'x', target.x, params);
|
|
79
|
-
this.animator.springTo(v, 'y', target.y, params);
|
|
80
|
-
}
|
|
81
|
-
else if (target instanceof Quaternion) {
|
|
82
|
-
let q = object[field];
|
|
83
|
-
let spring = this.getQuaternionSpring(q);
|
|
84
|
-
// update
|
|
85
|
-
spring.target.copy(target).normalize();
|
|
86
|
-
spring.params = Spring.getPhysicsParameters(params);
|
|
87
|
-
spring.mode = mode ?? QuaternionSpringMode.DirectionRollCartesian;
|
|
88
|
-
}
|
|
89
|
-
else if (target instanceof Euler) {
|
|
90
|
-
let e = object[field];
|
|
91
|
-
this.animator.springTo(e, 'x', target.x, params);
|
|
92
|
-
this.animator.springTo(e, 'y', target.y, params);
|
|
93
|
-
this.animator.springTo(e, 'z', target.z, params);
|
|
94
|
-
e.order = target.order;
|
|
95
|
-
}
|
|
96
|
-
else { // number
|
|
97
|
-
this.animator.springTo(object, field, target, params);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
customTweenTo(object, field, target, duration_s, step) {
|
|
101
|
-
if (target instanceof Vector4) {
|
|
102
|
-
let v = object[field];
|
|
103
|
-
this.animator.customTweenTo(v, 'x', target.x, duration_s, step);
|
|
104
|
-
this.animator.customTweenTo(v, 'y', target.y, duration_s, step);
|
|
105
|
-
this.animator.customTweenTo(v, 'z', target.z, duration_s, step);
|
|
106
|
-
this.animator.customTweenTo(v, 'w', target.w, duration_s, step);
|
|
107
|
-
}
|
|
108
|
-
else if (target instanceof Vector3) {
|
|
109
|
-
let v = object[field];
|
|
110
|
-
this.animator.customTweenTo(v, 'x', target.x, duration_s, step);
|
|
111
|
-
this.animator.customTweenTo(v, 'y', target.y, duration_s, step);
|
|
112
|
-
this.animator.customTweenTo(v, 'z', target.z, duration_s, step);
|
|
113
|
-
}
|
|
114
|
-
else if (target instanceof Vector2) {
|
|
115
|
-
let v = object[field];
|
|
116
|
-
this.animator.customTweenTo(v, 'x', target.x, duration_s, step);
|
|
117
|
-
this.animator.customTweenTo(v, 'y', target.y, duration_s, step);
|
|
118
|
-
}
|
|
119
|
-
else if (target instanceof Quaternion) {
|
|
120
|
-
throw new Error('Quaternion customTweenTo not yet supported, try springTo or use Euler');
|
|
121
|
-
}
|
|
122
|
-
else if (target instanceof Euler) {
|
|
123
|
-
let e = object[field];
|
|
124
|
-
this.animator.customTweenTo(e, 'x', target.x, duration_s, step);
|
|
125
|
-
this.animator.customTweenTo(e, 'y', target.y, duration_s, step);
|
|
126
|
-
this.animator.customTweenTo(e, 'z', target.z, duration_s, step);
|
|
127
|
-
e.order = target.order;
|
|
128
|
-
}
|
|
129
|
-
else { // number
|
|
130
|
-
this.animator.customTweenTo(object, field, target, duration_s, step);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
linearTo(object, field, target, duration_s) {
|
|
134
|
-
this.customTweenTo(object, field, target, duration_s, Tween.linearStep);
|
|
135
|
-
}
|
|
136
|
-
easeInOutTo(object, field, target, duration_s) {
|
|
137
|
-
this.customTweenTo(object, field, target, duration_s, Tween.easeInOutStep);
|
|
138
|
-
}
|
|
139
|
-
easeInTo(object, field, target, duration_s) {
|
|
140
|
-
this.customTweenTo(object, field, target, duration_s, Tween.easeInStep);
|
|
141
|
-
}
|
|
142
|
-
easeOutTo(object, field, target, duration_s) {
|
|
143
|
-
this.customTweenTo(object, field, target, duration_s, Tween.easeOutStep);
|
|
144
|
-
}
|
|
145
|
-
step(dt_s) {
|
|
146
|
-
this.animator.step(dt_s);
|
|
147
|
-
}
|
|
148
|
-
tick() {
|
|
149
|
-
this.animator.tick();
|
|
150
|
-
}
|
|
151
|
-
remove(object, field) {
|
|
152
|
-
let v = object[field];
|
|
153
|
-
if (v instanceof Vector4) {
|
|
154
|
-
this.animator.remove(v, 'x');
|
|
155
|
-
this.animator.remove(v, 'y');
|
|
156
|
-
this.animator.remove(v, 'z');
|
|
157
|
-
this.animator.remove(v, 'w');
|
|
158
|
-
}
|
|
159
|
-
else if (v instanceof Vector3) {
|
|
160
|
-
this.animator.remove(v, 'x');
|
|
161
|
-
this.animator.remove(v, 'y');
|
|
162
|
-
this.animator.remove(v, 'z');
|
|
163
|
-
}
|
|
164
|
-
else if (v instanceof Vector2) {
|
|
165
|
-
this.animator.remove(v, 'x');
|
|
166
|
-
this.animator.remove(v, 'y');
|
|
167
|
-
}
|
|
168
|
-
else if (v instanceof Quaternion) {
|
|
169
|
-
this.quaternionSprings.delete(v);
|
|
170
|
-
}
|
|
171
|
-
else if (v instanceof Euler) {
|
|
172
|
-
this.animator.remove(v, 'x');
|
|
173
|
-
this.animator.remove(v, 'y');
|
|
174
|
-
this.animator.remove(v, 'z');
|
|
175
|
-
}
|
|
176
|
-
else { // number
|
|
177
|
-
this.animator.remove(object, field);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
removeAll() {
|
|
181
|
-
this.animator.removeAll();
|
|
182
|
-
this.quaternionSprings.clear();
|
|
183
|
-
}
|
|
184
|
-
getVelocity(object, field, into) {
|
|
185
|
-
let target = object[field];
|
|
186
|
-
if (target instanceof Vector4) {
|
|
187
|
-
let i = into ?? new Vector4();
|
|
188
|
-
i.x = this.animator.getVelocity(target, 'x');
|
|
189
|
-
i.y = this.animator.getVelocity(target, 'y');
|
|
190
|
-
i.z = this.animator.getVelocity(target, 'z');
|
|
191
|
-
i.w = this.animator.getVelocity(target, 'w');
|
|
192
|
-
return i;
|
|
193
|
-
}
|
|
194
|
-
else if (target instanceof Vector3) {
|
|
195
|
-
let i = into ?? new Vector3();
|
|
196
|
-
i.x = this.animator.getVelocity(target, 'x');
|
|
197
|
-
i.y = this.animator.getVelocity(target, 'y');
|
|
198
|
-
i.z = this.animator.getVelocity(target, 'z');
|
|
199
|
-
return i;
|
|
200
|
-
}
|
|
201
|
-
else if (target instanceof Vector2) {
|
|
202
|
-
let i = into ?? new Vector2();
|
|
203
|
-
i.x = this.animator.getVelocity(target, 'x');
|
|
204
|
-
i.y = this.animator.getVelocity(target, 'y');
|
|
205
|
-
return i;
|
|
206
|
-
}
|
|
207
|
-
else if (target instanceof Quaternion) {
|
|
208
|
-
let spring = this.quaternionSprings.get(target);
|
|
209
|
-
return {
|
|
210
|
-
directionVelocity: spring?.directionVelocity ?? new Vector3(),
|
|
211
|
-
rollVelocity: spring?.rollVelocity ?? 0
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
else if (target instanceof Euler) {
|
|
215
|
-
let i = into ?? new Euler();
|
|
216
|
-
i.x = this.animator.getVelocity(target, 'x');
|
|
217
|
-
i.y = this.animator.getVelocity(target, 'y');
|
|
218
|
-
i.z = this.animator.getVelocity(target, 'z');
|
|
219
|
-
i.order = target.order;
|
|
220
|
-
return i;
|
|
221
|
-
}
|
|
222
|
-
else { // number
|
|
223
|
-
return this.animator.getVelocity(object, field);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
startAnimationFrameLoop() {
|
|
227
|
-
return this.animator.startAnimationFrameLoop();
|
|
228
|
-
}
|
|
229
|
-
startIntervalLoop(interval_ms) {
|
|
230
|
-
return this.animator.startIntervalLoop(interval_ms);
|
|
231
|
-
}
|
|
232
|
-
stop() {
|
|
233
|
-
this.animator.stop();
|
|
234
|
-
}
|
|
235
|
-
stepQuaternionSprings(dt_s) {
|
|
236
|
-
// step quaternion springs
|
|
237
|
-
this.quaternionSprings.forEach((spring, q) => {
|
|
238
|
-
if (spring.params) {
|
|
239
|
-
if (spring.mode === QuaternionSpringMode.DirectionRollCartesian) {
|
|
240
|
-
stepSpringQuaternion(dt_s, spring, spring.params);
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
stepSpringQuaternionSpherical(dt_s, spring, spring.params);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
// copy target
|
|
248
|
-
q.copy(spring.target);
|
|
249
|
-
// zero velocity
|
|
250
|
-
spring.directionVelocity.set(0, 0, 0);
|
|
251
|
-
spring.rollVelocity = 0;
|
|
252
|
-
}
|
|
253
|
-
// if quaternions match and velocity close to zero, remove spring
|
|
254
|
-
if (Math.abs(q.dot(spring.target)) > 0.999 && spring.directionVelocity.lengthSq() < 0.0001 && Math.abs(spring.rollVelocity) < 0.0001) {
|
|
255
|
-
this.quaternionSprings.delete(q);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
getQuaternionSpring(q) {
|
|
260
|
-
let spring = this.quaternionSprings.get(q);
|
|
261
|
-
if (!spring) {
|
|
262
|
-
_m.makeRotationFromQuaternion(q);
|
|
263
|
-
let direction = new Vector3();
|
|
264
|
-
_m.extractBasis(new Vector3(), new Vector3(), direction);
|
|
265
|
-
spring = {
|
|
266
|
-
q: q,
|
|
267
|
-
target: new Quaternion(),
|
|
268
|
-
direction: direction,
|
|
269
|
-
directionVelocity: new Vector3(),
|
|
270
|
-
rollVelocity: 0,
|
|
271
|
-
params: null,
|
|
272
|
-
mode: QuaternionSpringMode.DirectionRollCartesian,
|
|
273
|
-
};
|
|
274
|
-
this.quaternionSprings.set(q, spring);
|
|
275
|
-
}
|
|
276
|
-
return spring;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Analytic quaternion spring
|
|
281
|
-
*
|
|
282
|
-
* Todo:
|
|
283
|
-
* - for cameras we want to prefer rotations in xz plane rather than z
|
|
284
|
-
* - animate direction in spherical space rather than cartesian
|
|
285
|
-
*/
|
|
286
|
-
// working variables to avoid allocations
|
|
287
|
-
const _m = new Matrix4();
|
|
288
|
-
const _x = new Vector3();
|
|
289
|
-
const _y = new Vector3();
|
|
290
|
-
const _z = new Vector3();
|
|
291
|
-
const _qMatrix = new Matrix4();
|
|
292
|
-
const _springState = { x: 0, v: 0, targetX: 0 };
|
|
293
|
-
function stepSpringQuaternion(dt_s, state, parameters) {
|
|
294
|
-
// step direction spring in cartesian space
|
|
295
|
-
// we should do this in spherical in the future
|
|
296
|
-
let targetDirection = new Vector3();
|
|
297
|
-
let targetYBasis = new Vector3();
|
|
298
|
-
_m.makeRotationFromQuaternion(state.target);
|
|
299
|
-
_m.extractBasis(_x, targetYBasis, targetDirection);
|
|
300
|
-
let directionBefore = state.direction.clone();
|
|
301
|
-
// step spring direction
|
|
302
|
-
_springState.x = state.direction.x;
|
|
303
|
-
_springState.v = state.directionVelocity.x;
|
|
304
|
-
_springState.targetX = targetDirection.x;
|
|
305
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
306
|
-
state.direction.x = _springState.x;
|
|
307
|
-
state.directionVelocity.x = _springState.v;
|
|
308
|
-
_springState.x = state.direction.y;
|
|
309
|
-
_springState.v = state.directionVelocity.y;
|
|
310
|
-
_springState.targetX = targetDirection.y;
|
|
311
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
312
|
-
state.direction.y = _springState.x;
|
|
313
|
-
state.directionVelocity.y = _springState.v;
|
|
314
|
-
_springState.x = state.direction.z;
|
|
315
|
-
_springState.v = state.directionVelocity.z;
|
|
316
|
-
_springState.targetX = targetDirection.z;
|
|
317
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
318
|
-
state.direction.z = _springState.x;
|
|
319
|
-
state.directionVelocity.z = _springState.v;
|
|
320
|
-
// update quaternion
|
|
321
|
-
let directionDeltaQuaternion = new Quaternion().setFromUnitVectors(_x.copy(directionBefore).normalize(), _y.copy(state.direction).normalize());
|
|
322
|
-
state.q.premultiply(directionDeltaQuaternion);
|
|
323
|
-
// this forces synchronization of direction and quaternion
|
|
324
|
-
alignQuaternion(state.q, state.direction, _qMatrix);
|
|
325
|
-
// determine roll required to align yBasis with targetYBasis
|
|
326
|
-
let directionToTargetQuaternion = new Quaternion().setFromUnitVectors(state.direction.clone().normalize(), targetDirection);
|
|
327
|
-
_m.makeRotationFromQuaternion(state.q);
|
|
328
|
-
_m.extractBasis(_x, _y, _z);
|
|
329
|
-
let newYBasis = _y.applyQuaternion(directionToTargetQuaternion).clone();
|
|
330
|
-
let rollQuaternion = new Quaternion().setFromUnitVectors(newYBasis, targetYBasis);
|
|
331
|
-
// to axis angle (clamp w)
|
|
332
|
-
let rollAngle = Math.acos(Math.min(1, Math.max(-1, rollQuaternion.w))) * 2;
|
|
333
|
-
let rollSign = _x.crossVectors(newYBasis, targetYBasis).dot(targetDirection) < 0 ? -1 : 1;
|
|
334
|
-
rollAngle = -rollSign * rollAngle;
|
|
335
|
-
// step roll spring
|
|
336
|
-
_springState.x = rollAngle;
|
|
337
|
-
_springState.v = state.rollVelocity;
|
|
338
|
-
_springState.targetX = 0;
|
|
339
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
340
|
-
state.rollVelocity = _springState.v;
|
|
341
|
-
let rollAfter = _springState.x;
|
|
342
|
-
let rollDelta = rollAfter - rollAngle;
|
|
343
|
-
// apply roll correction
|
|
344
|
-
let rollDeltaQuaternion = new Quaternion().setFromAxisAngle(state.direction.clone().normalize(), rollDelta /*-rollAngle * 0.1*/);
|
|
345
|
-
state.q.premultiply(rollDeltaQuaternion);
|
|
346
|
-
state.q.normalize();
|
|
347
|
-
}
|
|
348
|
-
function stepSpringQuaternionSpherical(dt_s, state, parameters) {
|
|
349
|
-
let azimuthVelocity = state.directionVelocity.x;
|
|
350
|
-
let elevationVelocity = state.directionVelocity.y;
|
|
351
|
-
// get quaternion in spherical coordinates
|
|
352
|
-
let elAzRoll = quaternionToPitchYawRoll(state.q);
|
|
353
|
-
// get target quaternion in spherical coordinates
|
|
354
|
-
let targetElAzRoll = quaternionToPitchYawRoll(state.target);
|
|
355
|
-
// step springs
|
|
356
|
-
_springState.x = elAzRoll.x;
|
|
357
|
-
_springState.v = elevationVelocity;
|
|
358
|
-
_springState.targetX = getAngleContinuous(targetElAzRoll.x, elAzRoll.x);
|
|
359
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
360
|
-
elevationVelocity = _springState.v;
|
|
361
|
-
let elevationAfter = _springState.x;
|
|
362
|
-
_springState.x = elAzRoll.y;
|
|
363
|
-
_springState.v = azimuthVelocity;
|
|
364
|
-
_springState.targetX = getAngleContinuous(targetElAzRoll.y, elAzRoll.y);
|
|
365
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
366
|
-
azimuthVelocity = _springState.v;
|
|
367
|
-
let azimuthAfter = _springState.x;
|
|
368
|
-
// update directionVelocity
|
|
369
|
-
state.directionVelocity.x = azimuthVelocity;
|
|
370
|
-
state.directionVelocity.y = elevationVelocity;
|
|
371
|
-
// compose quaternion from spherical coordinates
|
|
372
|
-
// direction from azimuth and elevation
|
|
373
|
-
let direction = new Vector3(Math.cos(azimuthAfter) * Math.cos(elevationAfter), Math.sin(elevationAfter), Math.sin(azimuthAfter) * Math.cos(elevationAfter)).normalize();
|
|
374
|
-
// roll alignment spring
|
|
375
|
-
_springState.x = elAzRoll.z;
|
|
376
|
-
_springState.v = state.rollVelocity;
|
|
377
|
-
_springState.targetX = getAngleContinuous(targetElAzRoll.z, elAzRoll.z);
|
|
378
|
-
Spring.stepSpring(dt_s, _springState, parameters);
|
|
379
|
-
state.rollVelocity = _springState.v;
|
|
380
|
-
let rollAfter = _springState.x;
|
|
381
|
-
// compose quaternion from direction and roll
|
|
382
|
-
alignQuaternion(state.q, direction, _qMatrix);
|
|
383
|
-
setRoll(state.q, rollAfter);
|
|
384
|
-
}
|
|
385
|
-
function quaternionToPitchYawRoll(q, out = new Vector3()) {
|
|
386
|
-
// // get quaternion in spherical coordinates
|
|
387
|
-
_m.makeRotationFromQuaternion(q);
|
|
388
|
-
_m.extractBasis(_x, _y, _z);
|
|
389
|
-
// // azimuth and elevation are found from z direction
|
|
390
|
-
let azimuth = Math.atan2(_z.z, _z.x);
|
|
391
|
-
let elevation = Math.atan2(_z.y, Math.sqrt(_z.x * _z.x + _z.z * _z.z));
|
|
392
|
-
let roll = getRoll(q);
|
|
393
|
-
out.set(elevation, azimuth, roll);
|
|
394
|
-
return out;
|
|
395
|
-
}
|
|
396
|
-
function setRoll(q, roll) {
|
|
397
|
-
let currentRoll_rad = getRoll(q);
|
|
398
|
-
let deltaRoll = roll - currentRoll_rad;
|
|
399
|
-
let objectForward = new Vector3(0, 0, -1).applyQuaternion(q);
|
|
400
|
-
let rotation = new Quaternion().setFromAxisAngle(objectForward, deltaRoll);
|
|
401
|
-
q.premultiply(rotation);
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Aligns quaternion
|
|
405
|
-
*/
|
|
406
|
-
const _zBasis = new Vector3();
|
|
407
|
-
function alignQuaternion(q, direction, outMatrix = new Matrix4()) {
|
|
408
|
-
outMatrix.makeRotationFromQuaternion(q);
|
|
409
|
-
outMatrix.extractBasis(_x, _y, _z);
|
|
410
|
-
// must ensure _x and _y are orthogonal to zBasis
|
|
411
|
-
_zBasis.copy(direction).normalize();
|
|
412
|
-
_x.crossVectors(_y, _zBasis).normalize();
|
|
413
|
-
_y.crossVectors(_zBasis, _x).normalize();
|
|
414
|
-
outMatrix.makeBasis(_x, _y, _zBasis);
|
|
415
|
-
q.setFromRotationMatrix(outMatrix);
|
|
416
|
-
return outMatrix;
|
|
417
|
-
}
|
|
418
|
-
function getAngleContinuous(a, lastAngle) {
|
|
419
|
-
const tau = 2 * Math.PI;
|
|
420
|
-
let u = a / tau + 0.5;
|
|
421
|
-
let uLast = fract(lastAngle / tau + 0.5);
|
|
422
|
-
let du = u - uLast;
|
|
423
|
-
let angle;
|
|
424
|
-
if (Math.abs(du) < 0.5) {
|
|
425
|
-
angle = lastAngle + du * tau;
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
// passed through 0
|
|
429
|
-
let duSmall = 1 - Math.abs(du);
|
|
430
|
-
angle = lastAngle + -Math.sign(du) * duSmall * tau;
|
|
431
|
-
}
|
|
432
|
-
return angle;
|
|
433
|
-
}
|
|
434
|
-
function fract(x) {
|
|
435
|
-
return x - Math.floor(x);
|
|
436
|
-
}
|
|
437
|
-
function getRoll(quaternion) {
|
|
438
|
-
return getQuaternionPlaneAngle(quaternion, new Vector3(0, 1, 0), new Vector3(0, 0, -1));
|
|
439
|
-
}
|
|
440
|
-
function getQuaternionPlaneAngle(quaternion, basisDirection, basisPlane) {
|
|
441
|
-
let objectDirection = basisDirection.clone().applyQuaternion(quaternion);
|
|
442
|
-
let objectPlane = basisPlane.clone().applyQuaternion(quaternion);
|
|
443
|
-
let objectDirectionProjected = objectDirection.projectOnPlane(objectPlane);
|
|
444
|
-
let worldZeroProjected = basisDirection.clone().projectOnPlane(objectPlane);
|
|
445
|
-
let angle = worldZeroProjected.angleTo(objectDirectionProjected);
|
|
446
|
-
// sign of angle
|
|
447
|
-
let sign = Math.sign(worldZeroProjected.cross(objectDirectionProjected).dot(objectPlane));
|
|
448
|
-
angle *= sign;
|
|
449
|
-
return angle;
|
|
450
|
-
}
|
package/dist/esm/three/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ThreeAnimator.js';
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Euler, Quaternion, Vector2, Vector3, Vector4 } from "three";
|
|
2
|
-
import { Animator, TweenStepFn } from "../Animator.js";
|
|
3
|
-
import { Spring, SpringParameters } from "../Spring.js";
|
|
4
|
-
export declare enum QuaternionSpringMode {
|
|
5
|
-
DirectionRollCartesian = 0,
|
|
6
|
-
YawPitchRoll = 1
|
|
7
|
-
}
|
|
8
|
-
type SupportedTypes = Vector4 | Vector3 | Vector2 | Quaternion | Euler | number;
|
|
9
|
-
type KeysOfType<T, U> = keyof T;
|
|
10
|
-
/**
|
|
11
|
-
* Extends Animator to add support for animating vectors and quaternions
|
|
12
|
-
*/
|
|
13
|
-
export declare class ThreeAnimator {
|
|
14
|
-
animator: Animator;
|
|
15
|
-
get onAfterStep(): import("@haxiomic/event-signal").EventSignal<{
|
|
16
|
-
dt_s: number;
|
|
17
|
-
}, {
|
|
18
|
-
dt_s: number;
|
|
19
|
-
}>;
|
|
20
|
-
get onBeforeStep(): import("@haxiomic/event-signal").EventSignal<{
|
|
21
|
-
dt_s: number;
|
|
22
|
-
}, {
|
|
23
|
-
dt_s: number;
|
|
24
|
-
}>;
|
|
25
|
-
quaternionSprings: Map<Quaternion, {
|
|
26
|
-
q: Quaternion;
|
|
27
|
-
target: Quaternion;
|
|
28
|
-
direction: Vector3;
|
|
29
|
-
directionVelocity: Vector3;
|
|
30
|
-
rollVelocity: number;
|
|
31
|
-
params: Spring.PhysicsParameters | null;
|
|
32
|
-
mode: QuaternionSpringMode;
|
|
33
|
-
}>;
|
|
34
|
-
constructor(animator?: Animator);
|
|
35
|
-
setTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T): void;
|
|
36
|
-
springTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, params?: SpringParameters, mode?: QuaternionSpringMode): void;
|
|
37
|
-
customTweenTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, duration_s: number, step: TweenStepFn): void;
|
|
38
|
-
linearTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, duration_s: number): void;
|
|
39
|
-
easeInOutTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, duration_s: number): void;
|
|
40
|
-
easeInTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, duration_s: number): void;
|
|
41
|
-
easeOutTo<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & SupportedTypes>(object: Obj, field: Name, target: T, duration_s: number): void;
|
|
42
|
-
step(dt_s: number): void;
|
|
43
|
-
tick(): void;
|
|
44
|
-
remove<Obj, Name extends KeysOfType<Obj, SupportedTypes>>(object: Obj, field: Name): void;
|
|
45
|
-
removeAll(): void;
|
|
46
|
-
getVelocity<Obj, Name extends KeysOfType<Obj, SupportedTypes>, T extends Obj[Name] & (Vector4 | Vector3 | Vector2 | {
|
|
47
|
-
directionVelocity: Vector3;
|
|
48
|
-
rollVelocity: number;
|
|
49
|
-
} | Euler | number)>(object: Obj, field: Name, into?: T): T;
|
|
50
|
-
startAnimationFrameLoop(): void;
|
|
51
|
-
startIntervalLoop(interval_ms?: number): void;
|
|
52
|
-
stop(): void;
|
|
53
|
-
private stepQuaternionSprings;
|
|
54
|
-
private getQuaternionSpring;
|
|
55
|
-
}
|
|
56
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ThreeAnimator.js';
|