@thi.ng/timestep 0.3.3 → 0.4.0
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/CHANGELOG.md +11 -1
- package/README.md +10 -7
- package/package.json +2 -2
- package/state.d.ts +61 -28
- package/state.js +68 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-06-
|
|
3
|
+
- **Last updated**: 2023-06-19T09:41:50Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,16 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [0.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.4.0) (2023-06-19)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- update Numeric/VectorState, add 2/3/4d versions ([65ace1e](https://github.com/thi-ng/umbrella/commit/65ace1e))
|
|
17
|
+
- remove abstract AState class
|
|
18
|
+
- update NumericState
|
|
19
|
+
- add new VectorState impl
|
|
20
|
+
- add defVector2/3/4()
|
|
21
|
+
|
|
12
22
|
## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.3.0) (2023-05-05)
|
|
13
23
|
|
|
14
24
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -50,14 +50,16 @@ the two main phases of the frame update:
|
|
|
50
50
|
|
|
51
51
|
In other words, this means any updatable state value will require 3 versions:
|
|
52
52
|
previous, current (next), interpolated. **Only the interpolated version is to be
|
|
53
|
-
used for rendering (or other
|
|
53
|
+
used for rendering (or other userland purposes).** For that reason, the package
|
|
54
54
|
also provides wrappers for
|
|
55
55
|
[numeric](https://docs.thi.ng/umbrella/timestep/functions/defNumeric.html) and
|
|
56
56
|
[vector-based](https://docs.thi.ng/umbrella/timestep/functions/defVector.html)
|
|
57
|
-
|
|
57
|
+
(arbitrary length and optimized 2D/3D/4D versions) state variables, illustrated
|
|
58
|
+
in the following short example:
|
|
58
59
|
|
|
59
60
|
```ts tangle:export/readme.ts
|
|
60
|
-
import { defTimeStep, defNumeric,
|
|
61
|
+
import { defTimeStep, defNumeric, defVector2 } from "@thi.ng/timestep";
|
|
62
|
+
import { maddN2 } from "@thi.ng/vectors";
|
|
61
63
|
|
|
62
64
|
// initialize with default options (i.e. dt = 1/60 = 60 fps)
|
|
63
65
|
// start time is given in milliseconds but will be converted to seconds
|
|
@@ -67,9 +69,10 @@ const sim = defTimeStep({ dt: 1 / 60, startTime: Date.now() });
|
|
|
67
69
|
// define numeric state variable, increase using @ 10 units per second
|
|
68
70
|
const a = defNumeric(0, (x, dt) => x + dt * 10);
|
|
69
71
|
|
|
70
|
-
// define vector state variable, update
|
|
71
|
-
// also see thi.ng/vectors for hundreds of useful vector operations
|
|
72
|
-
|
|
72
|
+
// define vector state variable, update by applying velocity of [-10, 20] (per second)
|
|
73
|
+
// also see thi.ng/vectors for hundreds of other useful vector operations...
|
|
74
|
+
// the update function MUST write its result in given vector (1st arg)
|
|
75
|
+
const b = defVector2([0, 0], (v, dt) => maddN2(v, [-10, 20], dt, v));
|
|
73
76
|
|
|
74
77
|
// even though the sim will update at a fixed (theoretical) 60 fps,
|
|
75
78
|
// the simulated render frame rate here is only 25 fps...
|
|
@@ -148,7 +151,7 @@ For Node.js REPL:
|
|
|
148
151
|
const timestep = await import("@thi.ng/timestep");
|
|
149
152
|
```
|
|
150
153
|
|
|
151
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
154
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 817 bytes
|
|
152
155
|
|
|
153
156
|
## Dependencies
|
|
154
157
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/timestep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Deterministic fixed timestep simulation updates with state interpolation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"status": "alpha",
|
|
89
89
|
"year": 2023
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "db8b3ed2ab79e513d378a465a6d8cacf3243b052\n"
|
|
92
92
|
}
|
package/state.d.ts
CHANGED
|
@@ -1,31 +1,41 @@
|
|
|
1
1
|
import type { IDeref } from "@thi.ng/api";
|
|
2
|
-
import type { ReadonlyVec } from "@thi.ng/vectors";
|
|
3
|
-
import type { ITimeStep, ReadonlyTimeStep,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
deref(): T;
|
|
18
|
-
integrate(dt: number, ctx: ReadonlyTimeStep): void;
|
|
19
|
-
interpolate(alpha: number, ctx: ReadonlyTimeStep): void;
|
|
20
|
-
abstract reset(value: T): void;
|
|
21
|
-
}
|
|
22
|
-
export declare class NumericState extends AState<number> {
|
|
23
|
-
constructor(x: number, update: StateUpdate<number>);
|
|
2
|
+
import type { ReadonlyVec, Vec, VecOpV, VecOpVVN } from "@thi.ng/vectors";
|
|
3
|
+
import type { ITimeStep, ReadonlyTimeStep, StateUpdate } from "./api.js";
|
|
4
|
+
export declare class NumericState implements IDeref<number>, ITimeStep {
|
|
5
|
+
value: number;
|
|
6
|
+
update: StateUpdate<number>;
|
|
7
|
+
curr: number;
|
|
8
|
+
prev: number;
|
|
9
|
+
constructor(value: number, update: StateUpdate<number>);
|
|
10
|
+
deref(): number;
|
|
11
|
+
/**
|
|
12
|
+
* Sets {@link NumericState.prev}, {@link NumericState.curr} and
|
|
13
|
+
* {@link NumericState.value} to given new value.
|
|
14
|
+
*
|
|
15
|
+
* @param value
|
|
16
|
+
*/
|
|
24
17
|
reset(value: number): void;
|
|
18
|
+
integrate(dt: number, ctx: ReadonlyTimeStep): void;
|
|
19
|
+
interpolate(alpha: number): void;
|
|
25
20
|
}
|
|
26
|
-
export declare class VectorState
|
|
27
|
-
|
|
21
|
+
export declare class VectorState implements IDeref<ReadonlyVec>, ITimeStep {
|
|
22
|
+
value: Vec;
|
|
23
|
+
setFn: VecOpV;
|
|
24
|
+
mixFn: VecOpVVN;
|
|
25
|
+
update: StateUpdate<ReadonlyVec>;
|
|
26
|
+
prev: Vec;
|
|
27
|
+
curr: Vec;
|
|
28
|
+
constructor(value: Vec, setFn: VecOpV, mixFn: VecOpVVN, update: StateUpdate<ReadonlyVec>);
|
|
29
|
+
deref(): ReadonlyVec;
|
|
30
|
+
/**
|
|
31
|
+
* Copies given vector to {@link VectorState.prev}, {@link VectorState.curr}
|
|
32
|
+
* and {@link VectorState.value}.
|
|
33
|
+
*
|
|
34
|
+
* @param value
|
|
35
|
+
*/
|
|
28
36
|
reset(value: ReadonlyVec): void;
|
|
37
|
+
integrate(dt: number, ctx: ReadonlyTimeStep): void;
|
|
38
|
+
interpolate(alpha: number): void;
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
41
|
* Returns a new {@link NumericState} wrapper for given value `x` and its update
|
|
@@ -36,15 +46,38 @@ export declare class VectorState extends AState<ReadonlyVec> {
|
|
|
36
46
|
*/
|
|
37
47
|
export declare const defNumeric: (x: number, update: StateUpdate<number>) => NumericState;
|
|
38
48
|
/**
|
|
39
|
-
* Returns a new {@link VectorState} wrapper for given vector `v`
|
|
40
|
-
* function for use with {@link TimeStep.update}.
|
|
49
|
+
* Returns a new {@link VectorState} wrapper for given vector `v` (arbitrary
|
|
50
|
+
* length) and its update function for use with {@link TimeStep.update}.
|
|
41
51
|
*
|
|
42
52
|
* @remarks
|
|
43
|
-
* **IMPORTANT:** The `update` function MUST
|
|
44
|
-
*
|
|
53
|
+
* **IMPORTANT:** The `update` function MUST manipulate the vector received as
|
|
54
|
+
* 1st arg (which is {@link VectorState.curr}).
|
|
55
|
+
*
|
|
56
|
+
* Also see {@link defVector2}, {@link defVector3}, {@link defVector4}.
|
|
45
57
|
*
|
|
46
58
|
* @param x
|
|
47
59
|
* @param update
|
|
48
60
|
*/
|
|
49
61
|
export declare const defVector: (v: ReadonlyVec, update: StateUpdate<ReadonlyVec>) => VectorState;
|
|
62
|
+
/**
|
|
63
|
+
* 2D optimized version of {@link defVector}.
|
|
64
|
+
*
|
|
65
|
+
* @param v
|
|
66
|
+
* @param update
|
|
67
|
+
*/
|
|
68
|
+
export declare const defVector2: (v: ReadonlyVec, update: StateUpdate<ReadonlyVec>) => VectorState;
|
|
69
|
+
/**
|
|
70
|
+
* 3D optimized version of {@link defVector}.
|
|
71
|
+
*
|
|
72
|
+
* @param v
|
|
73
|
+
* @param update
|
|
74
|
+
*/
|
|
75
|
+
export declare const defVector3: (v: ReadonlyVec, update: StateUpdate<ReadonlyVec>) => VectorState;
|
|
76
|
+
/**
|
|
77
|
+
* 4D optimized version of {@link defVector}.
|
|
78
|
+
*
|
|
79
|
+
* @param v
|
|
80
|
+
* @param update
|
|
81
|
+
*/
|
|
82
|
+
export declare const defVector4: (v: ReadonlyVec, update: StateUpdate<ReadonlyVec>) => VectorState;
|
|
50
83
|
//# sourceMappingURL=state.d.ts.map
|
package/state.js
CHANGED
|
@@ -1,47 +1,63 @@
|
|
|
1
1
|
import { mix } from "@thi.ng/math/mix";
|
|
2
|
-
import { mixN } from "@thi.ng/vectors/mixn";
|
|
3
|
-
import { set } from "@thi.ng/vectors/set";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* See {@link defNumeric} and {@link defVector}.
|
|
9
|
-
*/
|
|
10
|
-
export class AState {
|
|
11
|
-
constructor(value, update, mix) {
|
|
2
|
+
import { mixN, mixN2, mixN3, mixN4 } from "@thi.ng/vectors/mixn";
|
|
3
|
+
import { set, set2, set3, set4 } from "@thi.ng/vectors/set";
|
|
4
|
+
export class NumericState {
|
|
5
|
+
constructor(value, update) {
|
|
12
6
|
this.value = value;
|
|
13
7
|
this.update = update;
|
|
14
|
-
this.
|
|
15
|
-
this.prev = this.curr = value;
|
|
8
|
+
this.reset(value);
|
|
16
9
|
}
|
|
17
10
|
deref() {
|
|
18
11
|
return this.value;
|
|
19
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Sets {@link NumericState.prev}, {@link NumericState.curr} and
|
|
15
|
+
* {@link NumericState.value} to given new value.
|
|
16
|
+
*
|
|
17
|
+
* @param value
|
|
18
|
+
*/
|
|
19
|
+
reset(value) {
|
|
20
|
+
this.prev = this.curr = this.value = value;
|
|
21
|
+
}
|
|
20
22
|
integrate(dt, ctx) {
|
|
21
23
|
this.prev = this.curr;
|
|
22
24
|
this.curr = this.update(this.curr, dt, ctx);
|
|
23
25
|
}
|
|
24
|
-
interpolate(alpha
|
|
25
|
-
this.value =
|
|
26
|
+
interpolate(alpha) {
|
|
27
|
+
this.value = mix(this.prev, this.curr, alpha);
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
|
-
export class
|
|
29
|
-
constructor(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.
|
|
30
|
+
export class VectorState {
|
|
31
|
+
constructor(value, setFn, mixFn, update) {
|
|
32
|
+
this.value = value;
|
|
33
|
+
this.setFn = setFn;
|
|
34
|
+
this.mixFn = mixFn;
|
|
35
|
+
this.update = update;
|
|
36
|
+
this.prev = [...value];
|
|
37
|
+
this.curr = [...value];
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
constructor(x, update) {
|
|
38
|
-
super(x, update, (a, b, t) => mixN([], a, b, t));
|
|
39
|
+
deref() {
|
|
40
|
+
return this.value;
|
|
39
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Copies given vector to {@link VectorState.prev}, {@link VectorState.curr}
|
|
44
|
+
* and {@link VectorState.value}.
|
|
45
|
+
*
|
|
46
|
+
* @param value
|
|
47
|
+
*/
|
|
40
48
|
reset(value) {
|
|
49
|
+
const set = this.setFn;
|
|
41
50
|
set(this.prev, value);
|
|
42
51
|
set(this.curr, value);
|
|
43
52
|
set(this.value, value);
|
|
44
53
|
}
|
|
54
|
+
integrate(dt, ctx) {
|
|
55
|
+
this.setFn(this.prev, this.curr);
|
|
56
|
+
this.update(this.curr, dt, ctx);
|
|
57
|
+
}
|
|
58
|
+
interpolate(alpha) {
|
|
59
|
+
this.mixFn(this.value, this.prev, this.curr, alpha);
|
|
60
|
+
}
|
|
45
61
|
}
|
|
46
62
|
/**
|
|
47
63
|
* Returns a new {@link NumericState} wrapper for given value `x` and its update
|
|
@@ -52,14 +68,37 @@ export class VectorState extends AState {
|
|
|
52
68
|
*/
|
|
53
69
|
export const defNumeric = (x, update) => new NumericState(x, update);
|
|
54
70
|
/**
|
|
55
|
-
* Returns a new {@link VectorState} wrapper for given vector `v`
|
|
56
|
-
* function for use with {@link TimeStep.update}.
|
|
71
|
+
* Returns a new {@link VectorState} wrapper for given vector `v` (arbitrary
|
|
72
|
+
* length) and its update function for use with {@link TimeStep.update}.
|
|
57
73
|
*
|
|
58
74
|
* @remarks
|
|
59
|
-
* **IMPORTANT:** The `update` function MUST
|
|
60
|
-
*
|
|
75
|
+
* **IMPORTANT:** The `update` function MUST manipulate the vector received as
|
|
76
|
+
* 1st arg (which is {@link VectorState.curr}).
|
|
77
|
+
*
|
|
78
|
+
* Also see {@link defVector2}, {@link defVector3}, {@link defVector4}.
|
|
61
79
|
*
|
|
62
80
|
* @param x
|
|
63
81
|
* @param update
|
|
64
82
|
*/
|
|
65
|
-
export const defVector = (v, update) => new VectorState(v, update);
|
|
83
|
+
export const defVector = (v, update) => new VectorState(v, set, mixN, update);
|
|
84
|
+
/**
|
|
85
|
+
* 2D optimized version of {@link defVector}.
|
|
86
|
+
*
|
|
87
|
+
* @param v
|
|
88
|
+
* @param update
|
|
89
|
+
*/
|
|
90
|
+
export const defVector2 = (v, update) => new VectorState(v, set2, mixN2, update);
|
|
91
|
+
/**
|
|
92
|
+
* 3D optimized version of {@link defVector}.
|
|
93
|
+
*
|
|
94
|
+
* @param v
|
|
95
|
+
* @param update
|
|
96
|
+
*/
|
|
97
|
+
export const defVector3 = (v, update) => new VectorState(v, set3, mixN3, update);
|
|
98
|
+
/**
|
|
99
|
+
* 4D optimized version of {@link defVector}.
|
|
100
|
+
*
|
|
101
|
+
* @param v
|
|
102
|
+
* @param update
|
|
103
|
+
*/
|
|
104
|
+
export const defVector4 = (v, update) => new VectorState(v, set4, mixN4, update);
|