@thi.ng/timestep 0.1.1 → 0.2.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 +8 -1
- package/api.d.ts +14 -0
- package/api.js +10 -1
- package/package.json +2 -2
- package/timestep.d.ts +26 -3
- package/timestep.js +46 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-04-
|
|
3
|
+
- **Last updated**: 2023-04-28T17:22:36Z
|
|
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,13 @@ 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.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.2.0) (2023-04-28)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add INotify support, add fixed time field ([b68c0c6](https://github.com/thi-ng/umbrella/commit/b68c0c6))
|
|
17
|
+
- add integrateAll/interpolateAll() helpers ([71087cf](https://github.com/thi-ng/umbrella/commit/71087cf))
|
|
18
|
+
|
|
12
19
|
### [0.1.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.1.1) (2023-04-25)
|
|
13
20
|
|
|
14
21
|
#### ♻️ Refactoring
|
package/api.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ export interface IUpdatable {
|
|
|
36
36
|
interpolate(alpha: number, ctx: ReadonlyTimeStep): void;
|
|
37
37
|
}
|
|
38
38
|
export interface ReadonlyTimeStep {
|
|
39
|
+
/**
|
|
40
|
+
* Simulation time since start (resolution {@link ReadonlyTimeStep.dt}).
|
|
41
|
+
*/
|
|
42
|
+
readonly t: number;
|
|
39
43
|
/**
|
|
40
44
|
* Configured timestep (in seconds)
|
|
41
45
|
*/
|
|
@@ -88,4 +92,14 @@ export interface TimeStepOpts {
|
|
|
88
92
|
}
|
|
89
93
|
export type StateUpdate<T> = (curr: T, dt: number, ctx: ReadonlyTimeStep) => T;
|
|
90
94
|
export type StateInterpolation<T> = (prev: T, curr: T, alpha: number, ctx: ReadonlyTimeStep) => T;
|
|
95
|
+
/**
|
|
96
|
+
* Event ID for {@link TimeStep.addListener} to be notified of individual
|
|
97
|
+
* {@link IUpdatable.integrate} iterations.
|
|
98
|
+
*/
|
|
99
|
+
export declare const EVENT_INTEGRATE = "integrate";
|
|
100
|
+
/**
|
|
101
|
+
* Event ID for {@link TimeStep.addListener} to be notified of calls to
|
|
102
|
+
* {@link TimeStep.update} (triggered at the very end of a frame update).
|
|
103
|
+
*/
|
|
104
|
+
export declare const EVENT_FRAME = "frame";
|
|
91
105
|
//# sourceMappingURL=api.d.ts.map
|
package/api.js
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Event ID for {@link TimeStep.addListener} to be notified of individual
|
|
3
|
+
* {@link IUpdatable.integrate} iterations.
|
|
4
|
+
*/
|
|
5
|
+
export const EVENT_INTEGRATE = "integrate";
|
|
6
|
+
/**
|
|
7
|
+
* Event ID for {@link TimeStep.addListener} to be notified of calls to
|
|
8
|
+
* {@link TimeStep.update} (triggered at the very end of a frame update).
|
|
9
|
+
*/
|
|
10
|
+
export const EVENT_FRAME = "frame";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/timestep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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": "e71e2d061ac0a754ce4899bb59208afb8b3d94b2\n"
|
|
92
92
|
}
|
package/timestep.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type Event, type INotify, type Listener } from "@thi.ng/api";
|
|
2
|
+
import { type IUpdatable, type ReadonlyTimeStep, type TimeStepOpts } from "./api.js";
|
|
3
|
+
export declare class TimeStep implements INotify {
|
|
4
4
|
start: number;
|
|
5
5
|
dt: number;
|
|
6
6
|
maxFrameTime: number;
|
|
7
7
|
scale: number;
|
|
8
|
+
t: number;
|
|
9
|
+
current: number;
|
|
8
10
|
accumulator: number;
|
|
9
11
|
frame: number;
|
|
10
12
|
updates: number;
|
|
13
|
+
protected __eventIntegrate: Event;
|
|
14
|
+
protected __eventFrame: Event;
|
|
11
15
|
constructor(opts?: Partial<TimeStepOpts>);
|
|
16
|
+
addListener(id: string, fn: Listener, scope?: any): boolean;
|
|
17
|
+
removeListener(id: string, fn: Listener, scope?: any): boolean;
|
|
18
|
+
notify(event: Event): boolean;
|
|
12
19
|
/**
|
|
13
20
|
* Updates internal time to given new time `now` (in seconds) and performs
|
|
14
21
|
* the required number of fixed timesteps to integrate and interpolate the
|
|
@@ -27,4 +34,20 @@ export declare class TimeStep {
|
|
|
27
34
|
update(now: number, items: IUpdatable[], interpolate?: boolean): void;
|
|
28
35
|
}
|
|
29
36
|
export declare const defTimeStep: (opts?: Partial<TimeStepOpts>) => TimeStep;
|
|
37
|
+
/**
|
|
38
|
+
* Calls {@link IUpdatable.integrate} for all given items (in given order).
|
|
39
|
+
*
|
|
40
|
+
* @param dt
|
|
41
|
+
* @param ctx
|
|
42
|
+
* @param items
|
|
43
|
+
*/
|
|
44
|
+
export declare const integrateAll: (dt: number, ctx: ReadonlyTimeStep, ...items: IUpdatable[]) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Calls {@link IUpdatable.interpolate} for all given items (in given order).
|
|
47
|
+
*
|
|
48
|
+
* @param dt
|
|
49
|
+
* @param ctx
|
|
50
|
+
* @param items
|
|
51
|
+
*/
|
|
52
|
+
export declare const interpolateAll: (alpha: number, ctx: ReadonlyTimeStep, ...items: IUpdatable[]) => void;
|
|
30
53
|
//# sourceMappingURL=timestep.d.ts.map
|
package/timestep.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { INotifyMixin, } from "@thi.ng/api";
|
|
3
|
+
import { EVENT_FRAME, EVENT_INTEGRATE, } from "./api.js";
|
|
4
|
+
let TimeStep = class TimeStep {
|
|
2
5
|
constructor(opts) {
|
|
6
|
+
this.t = 0;
|
|
3
7
|
this.current = 0;
|
|
4
8
|
this.accumulator = 0;
|
|
5
9
|
this.frame = 0;
|
|
@@ -15,7 +19,18 @@ export class TimeStep {
|
|
|
15
19
|
this.maxFrameTime = $opts.maxFrameTime;
|
|
16
20
|
this.scale = $opts.scale;
|
|
17
21
|
this.start = $opts.startTime * this.scale;
|
|
22
|
+
this.__eventIntegrate = Object.freeze({
|
|
23
|
+
id: EVENT_INTEGRATE,
|
|
24
|
+
target: this,
|
|
25
|
+
});
|
|
26
|
+
this.__eventFrame = Object.freeze({ id: EVENT_FRAME, target: this });
|
|
18
27
|
}
|
|
28
|
+
// @ts-ignore mixin
|
|
29
|
+
addListener(id, fn, scope) { }
|
|
30
|
+
// @ts-ignore mixin
|
|
31
|
+
removeListener(id, fn, scope) { }
|
|
32
|
+
// @ts-ignore mixin
|
|
33
|
+
notify(event) { }
|
|
19
34
|
/**
|
|
20
35
|
* Updates internal time to given new time `now` (in seconds) and performs
|
|
21
36
|
* the required number of fixed timesteps to integrate and interpolate the
|
|
@@ -33,8 +48,6 @@ export class TimeStep {
|
|
|
33
48
|
*/
|
|
34
49
|
update(now, items, interpolate = true) {
|
|
35
50
|
now = now * this.scale - this.start;
|
|
36
|
-
if (this.current < 0)
|
|
37
|
-
this.current = now;
|
|
38
51
|
this.accumulator += Math.min(now - this.current, this.maxFrameTime);
|
|
39
52
|
this.current = now;
|
|
40
53
|
const n = items.length;
|
|
@@ -42,8 +55,10 @@ export class TimeStep {
|
|
|
42
55
|
while (this.accumulator >= dt) {
|
|
43
56
|
for (let i = 0; i < n; i++)
|
|
44
57
|
items[i].integrate(dt, this);
|
|
58
|
+
this.t += dt;
|
|
45
59
|
this.accumulator -= dt;
|
|
46
60
|
this.updates++;
|
|
61
|
+
this.notify(this.__eventIntegrate);
|
|
47
62
|
}
|
|
48
63
|
if (interpolate) {
|
|
49
64
|
const alpha = this.accumulator / dt;
|
|
@@ -51,6 +66,33 @@ export class TimeStep {
|
|
|
51
66
|
items[i].interpolate(alpha, this);
|
|
52
67
|
}
|
|
53
68
|
this.frame++;
|
|
69
|
+
this.notify(this.__eventFrame);
|
|
54
70
|
}
|
|
55
|
-
}
|
|
71
|
+
};
|
|
72
|
+
TimeStep = __decorate([
|
|
73
|
+
INotifyMixin
|
|
74
|
+
], TimeStep);
|
|
75
|
+
export { TimeStep };
|
|
56
76
|
export const defTimeStep = (opts) => new TimeStep(opts);
|
|
77
|
+
/**
|
|
78
|
+
* Calls {@link IUpdatable.integrate} for all given items (in given order).
|
|
79
|
+
*
|
|
80
|
+
* @param dt
|
|
81
|
+
* @param ctx
|
|
82
|
+
* @param items
|
|
83
|
+
*/
|
|
84
|
+
export const integrateAll = (dt, ctx, ...items) => {
|
|
85
|
+
for (let i = 0, n = items.length; i < n; i++)
|
|
86
|
+
items[i].integrate(dt, ctx);
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Calls {@link IUpdatable.interpolate} for all given items (in given order).
|
|
90
|
+
*
|
|
91
|
+
* @param dt
|
|
92
|
+
* @param ctx
|
|
93
|
+
* @param items
|
|
94
|
+
*/
|
|
95
|
+
export const interpolateAll = (alpha, ctx, ...items) => {
|
|
96
|
+
for (let i = 0, n = items.length; i < n; i++)
|
|
97
|
+
items[i].interpolate(alpha, ctx);
|
|
98
|
+
};
|