@thi.ng/timestep 0.2.0 → 0.3.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 +4 -4
- package/api.d.ts +2 -2
- package/api.js +1 -1
- package/package.json +2 -2
- package/state.d.ts +9 -2
- package/state.js +13 -0
- package/timestep.d.ts +16 -13
- package/timestep.js +12 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-
|
|
3
|
+
- **Last updated**: 2023-05-05T21:29:28Z
|
|
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.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.3.0) (2023-05-05)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add AState.reset() & impls ([a2c4946](https://github.com/thi-ng/umbrella/commit/a2c4946))
|
|
17
|
+
|
|
18
|
+
#### ♻️ Refactoring
|
|
19
|
+
|
|
20
|
+
- rename IUpdatable => ITimeStep ([2cc3951](https://github.com/thi-ng/umbrella/commit/2cc3951))
|
|
21
|
+
|
|
12
22
|
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.2.0) (2023-04-28)
|
|
13
23
|
|
|
14
24
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ upon which this implementation is principally based on.
|
|
|
31
31
|
The package provides a configurable [`TimeStep`
|
|
32
32
|
class](https://docs.thi.ng/umbrella/timestep/classes/TimeStep.html) to manage
|
|
33
33
|
the update logic. To participate in these managed updates, the user must provide
|
|
34
|
-
state values/wrappers implementing the [`
|
|
35
|
-
interface](https://docs.thi.ng/umbrella/timestep/interfaces/
|
|
34
|
+
state values/wrappers implementing the [`ITimeStep`
|
|
35
|
+
interface](https://docs.thi.ng/umbrella/timestep/interfaces/ITimeStep.html) for
|
|
36
36
|
the two main phases of the frame update:
|
|
37
37
|
|
|
38
38
|
- `integrate(dt: number, ctx: ReadonlyTimeStep): void`: Depending on actual
|
|
@@ -75,7 +75,7 @@ const b = defVector([0, 0], (x, dt) => [x[0] - 10 * dt, x[1] + 20 * dt]);
|
|
|
75
75
|
// the simulated render frame rate here is only 25 fps...
|
|
76
76
|
setInterval(() => {
|
|
77
77
|
// provide current time and an array of state values to update
|
|
78
|
-
// (any
|
|
78
|
+
// (any ITimeStep impl can be given here, incl. custom types)
|
|
79
79
|
sim.update(Date.now(), [a, b]);
|
|
80
80
|
// show current frame, num updates, time (relative to start) and interpolated state values
|
|
81
81
|
console.log(sim.frame, sim.updates, sim.current, a.value, b.value);
|
|
@@ -148,7 +148,7 @@ For Node.js REPL:
|
|
|
148
148
|
const timestep = await import("@thi.ng/timestep");
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
151
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 758 bytes
|
|
152
152
|
|
|
153
153
|
## Dependencies
|
|
154
154
|
|
package/api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Interface for participating in the {@link TimeStep.update} logic.
|
|
3
3
|
*/
|
|
4
|
-
export interface
|
|
4
|
+
export interface ITimeStep {
|
|
5
5
|
/**
|
|
6
6
|
* 1st phase of the update cycle and main update function for this
|
|
7
7
|
* simulation state. Receives timestep (in seconds) and a `ctx` object.
|
|
@@ -94,7 +94,7 @@ export type StateUpdate<T> = (curr: T, dt: number, ctx: ReadonlyTimeStep) => T;
|
|
|
94
94
|
export type StateInterpolation<T> = (prev: T, curr: T, alpha: number, ctx: ReadonlyTimeStep) => T;
|
|
95
95
|
/**
|
|
96
96
|
* Event ID for {@link TimeStep.addListener} to be notified of individual
|
|
97
|
-
* {@link
|
|
97
|
+
* {@link ITimeStep.integrate} iterations.
|
|
98
98
|
*/
|
|
99
99
|
export declare const EVENT_INTEGRATE = "integrate";
|
|
100
100
|
/**
|
package/api.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/timestep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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": "81dcbba93e7230c2f400bee87878145d902e975b\n"
|
|
92
92
|
}
|
package/state.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { IDeref } from "@thi.ng/api";
|
|
2
2
|
import type { ReadonlyVec } from "@thi.ng/vectors";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ITimeStep, ReadonlyTimeStep, StateInterpolation, StateUpdate } from "./api.js";
|
|
4
4
|
/**
|
|
5
5
|
* Abstract base class for simulation state wrappers.
|
|
6
6
|
*
|
|
7
7
|
* @remarks
|
|
8
8
|
* See {@link defNumeric} and {@link defVector}.
|
|
9
9
|
*/
|
|
10
|
-
export declare abstract class AState<T> implements IDeref<T>,
|
|
10
|
+
export declare abstract class AState<T> implements IDeref<T>, ITimeStep {
|
|
11
11
|
value: T;
|
|
12
12
|
update: StateUpdate<T>;
|
|
13
13
|
mix: StateInterpolation<T>;
|
|
@@ -17,12 +17,15 @@ export declare abstract class AState<T> implements IDeref<T>, IUpdatable {
|
|
|
17
17
|
deref(): T;
|
|
18
18
|
integrate(dt: number, ctx: ReadonlyTimeStep): void;
|
|
19
19
|
interpolate(alpha: number, ctx: ReadonlyTimeStep): void;
|
|
20
|
+
abstract reset(value: T): void;
|
|
20
21
|
}
|
|
21
22
|
export declare class NumericState extends AState<number> {
|
|
22
23
|
constructor(x: number, update: StateUpdate<number>);
|
|
24
|
+
reset(value: number): void;
|
|
23
25
|
}
|
|
24
26
|
export declare class VectorState extends AState<ReadonlyVec> {
|
|
25
27
|
constructor(x: ReadonlyVec, update: StateUpdate<ReadonlyVec>);
|
|
28
|
+
reset(value: ReadonlyVec): void;
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
28
31
|
* Returns a new {@link NumericState} wrapper for given value `x` and its update
|
|
@@ -36,6 +39,10 @@ export declare const defNumeric: (x: number, update: StateUpdate<number>) => Num
|
|
|
36
39
|
* Returns a new {@link VectorState} wrapper for given vector `v` and its update
|
|
37
40
|
* function for use with {@link TimeStep.update}.
|
|
38
41
|
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* **IMPORTANT:** The `update` function MUST return a new vector and not mutate
|
|
44
|
+
* the existing one!
|
|
45
|
+
*
|
|
39
46
|
* @param x
|
|
40
47
|
* @param update
|
|
41
48
|
*/
|
package/state.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mix } from "@thi.ng/math/mix";
|
|
2
2
|
import { mixN } from "@thi.ng/vectors/mixn";
|
|
3
|
+
import { set } from "@thi.ng/vectors/set";
|
|
3
4
|
/**
|
|
4
5
|
* Abstract base class for simulation state wrappers.
|
|
5
6
|
*
|
|
@@ -28,11 +29,19 @@ export class NumericState extends AState {
|
|
|
28
29
|
constructor(x, update) {
|
|
29
30
|
super(x, update, mix);
|
|
30
31
|
}
|
|
32
|
+
reset(value) {
|
|
33
|
+
this.prev = this.curr = this.value = value;
|
|
34
|
+
}
|
|
31
35
|
}
|
|
32
36
|
export class VectorState extends AState {
|
|
33
37
|
constructor(x, update) {
|
|
34
38
|
super(x, update, (a, b, t) => mixN([], a, b, t));
|
|
35
39
|
}
|
|
40
|
+
reset(value) {
|
|
41
|
+
set(this.prev, value);
|
|
42
|
+
set(this.curr, value);
|
|
43
|
+
set(this.value, value);
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
/**
|
|
38
47
|
* Returns a new {@link NumericState} wrapper for given value `x` and its update
|
|
@@ -46,6 +55,10 @@ export const defNumeric = (x, update) => new NumericState(x, update);
|
|
|
46
55
|
* Returns a new {@link VectorState} wrapper for given vector `v` and its update
|
|
47
56
|
* function for use with {@link TimeStep.update}.
|
|
48
57
|
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* **IMPORTANT:** The `update` function MUST return a new vector and not mutate
|
|
60
|
+
* the existing one!
|
|
61
|
+
*
|
|
49
62
|
* @param x
|
|
50
63
|
* @param update
|
|
51
64
|
*/
|
package/timestep.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Event, type INotify, type Listener } from "@thi.ng/api";
|
|
2
|
-
import { type
|
|
2
|
+
import { type ITimeStep, type ReadonlyTimeStep, type TimeStepOpts } from "./api.js";
|
|
3
3
|
export declare class TimeStep implements INotify {
|
|
4
4
|
start: number;
|
|
5
5
|
dt: number;
|
|
@@ -17,37 +17,40 @@ export declare class TimeStep implements INotify {
|
|
|
17
17
|
removeListener(id: string, fn: Listener, scope?: any): boolean;
|
|
18
18
|
notify(event: Event): boolean;
|
|
19
19
|
/**
|
|
20
|
-
* Updates internal time to given new time `now` (
|
|
21
|
-
* the required number of fixed
|
|
22
|
-
* given `state` values.
|
|
20
|
+
* Updates internal time to given new time `now` (given value will be scaled
|
|
21
|
+
* via {@link TimeStepOpts.scale}) and performs the required number of fixed
|
|
22
|
+
* timesteps to integrate and interpolate the given `state` values.
|
|
23
23
|
*
|
|
24
24
|
* @remarks
|
|
25
|
-
* If
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* If the scaled time difference since the last step is greater than
|
|
26
|
+
* {@link TimeStepOpts.maxFrameTime}, it will be limited to the latter.
|
|
27
|
+
*
|
|
28
|
+
* If `interpolate` is false, the {@link ITimeStep.interpolate} phase of the
|
|
29
|
+
* update cycle is skipped. This is useful when using this setup to simulate
|
|
30
|
+
* sub-steps (e.g. in XPBD) and only requiring the interpolation stage for
|
|
31
|
+
* the last step.
|
|
29
32
|
*
|
|
30
33
|
* @param now
|
|
31
34
|
* @param items
|
|
32
35
|
* @param interpolate
|
|
33
36
|
*/
|
|
34
|
-
update(now: number, items:
|
|
37
|
+
update(now: number, items: ITimeStep[], interpolate?: boolean): void;
|
|
35
38
|
}
|
|
36
39
|
export declare const defTimeStep: (opts?: Partial<TimeStepOpts>) => TimeStep;
|
|
37
40
|
/**
|
|
38
|
-
* Calls {@link
|
|
41
|
+
* Calls {@link ITimeStep.integrate} for all given items (in given order).
|
|
39
42
|
*
|
|
40
43
|
* @param dt
|
|
41
44
|
* @param ctx
|
|
42
45
|
* @param items
|
|
43
46
|
*/
|
|
44
|
-
export declare const integrateAll: (dt: number, ctx: ReadonlyTimeStep, ...items:
|
|
47
|
+
export declare const integrateAll: (dt: number, ctx: ReadonlyTimeStep, ...items: ITimeStep[]) => void;
|
|
45
48
|
/**
|
|
46
|
-
* Calls {@link
|
|
49
|
+
* Calls {@link ITimeStep.interpolate} for all given items (in given order).
|
|
47
50
|
*
|
|
48
51
|
* @param dt
|
|
49
52
|
* @param ctx
|
|
50
53
|
* @param items
|
|
51
54
|
*/
|
|
52
|
-
export declare const interpolateAll: (alpha: number, ctx: ReadonlyTimeStep, ...items:
|
|
55
|
+
export declare const interpolateAll: (alpha: number, ctx: ReadonlyTimeStep, ...items: ITimeStep[]) => void;
|
|
53
56
|
//# sourceMappingURL=timestep.d.ts.map
|
package/timestep.js
CHANGED
|
@@ -32,15 +32,18 @@ let TimeStep = class TimeStep {
|
|
|
32
32
|
// @ts-ignore mixin
|
|
33
33
|
notify(event) { }
|
|
34
34
|
/**
|
|
35
|
-
* Updates internal time to given new time `now` (
|
|
36
|
-
* the required number of fixed
|
|
37
|
-
* given `state` values.
|
|
35
|
+
* Updates internal time to given new time `now` (given value will be scaled
|
|
36
|
+
* via {@link TimeStepOpts.scale}) and performs the required number of fixed
|
|
37
|
+
* timesteps to integrate and interpolate the given `state` values.
|
|
38
38
|
*
|
|
39
39
|
* @remarks
|
|
40
|
-
* If
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* If the scaled time difference since the last step is greater than
|
|
41
|
+
* {@link TimeStepOpts.maxFrameTime}, it will be limited to the latter.
|
|
42
|
+
*
|
|
43
|
+
* If `interpolate` is false, the {@link ITimeStep.interpolate} phase of the
|
|
44
|
+
* update cycle is skipped. This is useful when using this setup to simulate
|
|
45
|
+
* sub-steps (e.g. in XPBD) and only requiring the interpolation stage for
|
|
46
|
+
* the last step.
|
|
44
47
|
*
|
|
45
48
|
* @param now
|
|
46
49
|
* @param items
|
|
@@ -75,7 +78,7 @@ TimeStep = __decorate([
|
|
|
75
78
|
export { TimeStep };
|
|
76
79
|
export const defTimeStep = (opts) => new TimeStep(opts);
|
|
77
80
|
/**
|
|
78
|
-
* Calls {@link
|
|
81
|
+
* Calls {@link ITimeStep.integrate} for all given items (in given order).
|
|
79
82
|
*
|
|
80
83
|
* @param dt
|
|
81
84
|
* @param ctx
|
|
@@ -86,7 +89,7 @@ export const integrateAll = (dt, ctx, ...items) => {
|
|
|
86
89
|
items[i].integrate(dt, ctx);
|
|
87
90
|
};
|
|
88
91
|
/**
|
|
89
|
-
* Calls {@link
|
|
92
|
+
* Calls {@link ITimeStep.interpolate} for all given items (in given order).
|
|
90
93
|
*
|
|
91
94
|
* @param dt
|
|
92
95
|
* @param ctx
|