Skip to content

Commit e982ce5

Browse files
Improve timestep
1 parent d2d30b2 commit e982ce5

File tree

4 files changed

+96
-60
lines changed

4 files changed

+96
-60
lines changed

testbed2d/src/Graphics.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ const BALL_INSTANCE_INDEX = 1;
99

1010
var kk = 0;
1111

12+
function lerp(a: number, b: number, t: number) {
13+
return a + (b - a) * t;
14+
}
15+
1216
export class Graphics {
1317
coll2gfx: Map<number, PIXI.Graphics>;
1418
colorIndex: number;
@@ -89,7 +93,7 @@ export class Graphics {
8993
);
9094
}
9195

92-
render(world: RAPIER.World, debugRender: Boolean) {
96+
render(world: RAPIER.World, debugRender: Boolean, alpha: number) {
9397
kk += 1;
9498

9599
if (!this.lines) {
@@ -118,7 +122,7 @@ export class Graphics {
118122
this.lines.clear();
119123
}
120124

121-
this.updatePositions(world);
125+
this.updatePositions(world, alpha);
122126
this.renderer.render(this.scene);
123127
}
124128

@@ -127,16 +131,16 @@ export class Graphics {
127131
this.viewport.moveCenter(pos.target.x, pos.target.y);
128132
}
129133

130-
updatePositions(world: RAPIER.World) {
134+
updatePositions(world: RAPIER.World, alpha: number) {
131135
world.forEachCollider((elt) => {
132136
let gfx = this.coll2gfx.get(elt.handle);
133137
let translation = elt.translation();
134138
let rotation = elt.rotation();
135139

136140
if (!!gfx) {
137-
gfx.position.x = translation.x;
138-
gfx.position.y = -translation.y;
139-
gfx.rotation = -rotation;
141+
gfx.position.x = lerp(gfx.position.x, translation.x, alpha);
142+
gfx.position.y = lerp(gfx.position.y, -translation.y, alpha);
143+
gfx.rotation = lerp(gfx.rotation, -rotation, alpha);
140144
}
141145
});
142146
}

testbed2d/src/Testbed.ts

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Graphics} from "./Graphics";
22
import {Gui} from "./Gui";
33
import type {DebugInfos} from "./Gui";
4-
import * as md5 from "md5";
4+
import md5 from "md5";
55
import type * as RAPIER from "@dimforge/rapier2d";
66

77
type RAPIER_API = typeof import("@dimforge/rapier2d");
@@ -60,6 +60,10 @@ export class Testbed {
6060
lastMessageTime: number;
6161
snap: Uint8Array;
6262
snapStepId: number;
63+
frameTime: number;
64+
accumulator: number;
65+
alpha: number;
66+
maxSubsteps: number;
6367

6468
constructor(RAPIER: RAPIER_API, builders: Builders) {
6569
let backends = ["rapier"];
@@ -73,6 +77,10 @@ export class Testbed {
7377
this.mouse = {x: 0, y: 0};
7478
this.events = new RAPIER.EventQueue(true);
7579
this.switchToDemo(builders.keys().next().value);
80+
this.frameTime = 0;
81+
this.accumulator = 0;
82+
this.alpha = 0;
83+
this.maxSubsteps = 6;
7684

7785
window.addEventListener("mousemove", (event) => {
7886
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
@@ -141,43 +149,60 @@ export class Testbed {
141149
}
142150

143151
run() {
144-
if (this.parameters.running || this.parameters.stepping) {
145-
this.world.maxVelocityIterations = this.parameters.numVelocityIter;
146-
this.world.maxVelocityFrictionIterations =
147-
this.parameters.numVelocityIter * 2;
148-
149-
if (!!this.preTimestepAction) {
150-
this.preTimestepAction(this.graphics);
152+
let time = performance.now();
153+
let fixedStep = this.world.timestep;
154+
let deltaTime = (time - this.frameTime) / 1000;
155+
let substeps = 0;
156+
157+
this.frameTime = time;
158+
this.accumulator += deltaTime;
159+
160+
if (this.accumulator >= fixedStep && substeps < this.maxSubsteps) {
161+
this.accumulator -= fixedStep;
162+
substeps++;
163+
164+
if (this.parameters.running || this.parameters.stepping) {
165+
this.world.maxVelocityIterations =
166+
this.parameters.numVelocityIter;
167+
this.world.maxVelocityFrictionIterations =
168+
this.parameters.numVelocityIter * 2;
169+
170+
if (!!this.preTimestepAction) {
171+
this.preTimestepAction(this.graphics);
172+
}
173+
174+
let t0 = new Date().getTime();
175+
this.world.step(this.events);
176+
this.gui.setTiming(new Date().getTime() - t0);
177+
this.stepId += 1;
178+
179+
if (!!this.parameters.debugInfos) {
180+
let t0 = performance.now();
181+
let snapshot = this.world.takeSnapshot();
182+
let t1 = performance.now();
183+
let snapshotTime = t1 - t0;
184+
185+
let debugInfos: DebugInfos = {
186+
token: this.demoToken,
187+
stepId: this.stepId,
188+
worldHash: "",
189+
worldHashTime: 0,
190+
snapshotTime: 0,
191+
};
192+
t0 = performance.now();
193+
debugInfos.worldHash = md5(snapshot);
194+
t1 = performance.now();
195+
let worldHashTime = t1 - t0;
196+
197+
debugInfos.worldHashTime = worldHashTime;
198+
debugInfos.snapshotTime = snapshotTime;
199+
200+
this.gui.setDebugInfos(debugInfos);
201+
}
151202
}
152203

153-
let t0 = new Date().getTime();
154-
this.world.step(this.events);
155-
this.gui.setTiming(new Date().getTime() - t0);
156-
this.stepId += 1;
157-
158-
if (!!this.parameters.debugInfos) {
159-
let t0 = performance.now();
160-
let snapshot = this.world.takeSnapshot();
161-
let t1 = performance.now();
162-
let snapshotTime = t1 - t0;
163-
164-
let debugInfos: DebugInfos = {
165-
token: this.demoToken,
166-
stepId: this.stepId,
167-
worldHash: "",
168-
worldHashTime: 0,
169-
snapshotTime: 0,
170-
};
171-
t0 = performance.now();
172-
debugInfos.worldHash = md5(snapshot);
173-
t1 = performance.now();
174-
let worldHashTime = t1 - t0;
175-
176-
debugInfos.worldHashTime = worldHashTime;
177-
debugInfos.snapshotTime = snapshotTime;
178-
179-
this.gui.setDebugInfos(debugInfos);
180-
}
204+
this.accumulator = this.accumulator % fixedStep;
205+
this.alpha = this.accumulator / fixedStep;
181206
}
182207

183208
if (this.parameters.stepping) {
@@ -186,7 +211,11 @@ export class Testbed {
186211
}
187212

188213
this.gui.stats.begin();
189-
this.graphics.render(this.world, this.parameters.debugRender);
214+
this.graphics.render(
215+
this.world,
216+
this.parameters.debugRender,
217+
this.alpha,
218+
);
190219
this.gui.stats.end();
191220

192221
requestAnimationFrame(() => this.run());

testbed2d/src/demos/characterController.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
6464
newPos.x += movement.x;
6565
newPos.y += movement.y;
6666
character.setNextKinematicTranslation(newPos);
67-
console.log("here");
6867
};
6968

7069
testbed.setWorld(world);

testbed3d/src/Testbed.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ export class Testbed {
5757
prevDemo: string;
5858
snap: Uint8Array;
5959
snapStepId: number;
60-
time: number;
61-
physicsTime: number;
60+
frameTime: number;
6261
accumulator: number;
62+
alpha: number;
63+
maxSubsteps: number;
6364

6465
constructor(RAPIER: RAPIER_API, builders: Builders) {
6566
let backends = ["rapier"];
@@ -72,9 +73,10 @@ export class Testbed {
7273
this.demoToken = 0;
7374
this.mouse = {x: 0, y: 0};
7475
this.events = new RAPIER.EventQueue(true);
75-
this.time = 0;
76-
this.physicsTime = 0;
76+
this.frameTime = 0;
7777
this.accumulator = 0;
78+
this.alpha = 0;
79+
this.maxSubsteps = 6;
7880

7981
this.switchToDemo(builders.keys().next().value);
8082

@@ -144,13 +146,16 @@ export class Testbed {
144146
run() {
145147
let time = performance.now();
146148
let fixedStep = this.world.timestep;
147-
let deltaTime = (time - this.time) / 1000;
148-
let physicsDeltaTime = (time - this.physicsTime) / 1000;
149+
let deltaTime = (time - this.frameTime) / 1000;
150+
let substeps = 0;
149151

150-
this.time = time;
152+
this.frameTime = time;
151153
this.accumulator += deltaTime;
152154

153-
if (physicsDeltaTime >= fixedStep) {
155+
if (this.accumulator >= fixedStep && substeps < this.maxSubsteps) {
156+
this.accumulator -= fixedStep;
157+
substeps++;
158+
154159
if (this.parameters.running || this.parameters.stepping) {
155160
this.world.maxVelocityIterations =
156161
this.parameters.numVelocityIter;
@@ -189,22 +194,21 @@ export class Testbed {
189194
}
190195
}
191196

192-
this.physicsTime = time;
193-
this.accumulator -= fixedStep;
197+
this.accumulator = this.accumulator % fixedStep;
198+
this.alpha = this.accumulator / fixedStep;
194199
}
195200

196-
// let alpha = this.accumulator / fixedStep;
197-
let alpha = 1;
198-
199-
console.log(alpha);
200-
201201
if (this.parameters.stepping) {
202202
this.parameters.running = false;
203203
this.parameters.stepping = false;
204204
}
205205

206206
this.gui.stats.begin();
207-
this.graphics.render(this.world, this.parameters.debugRender, alpha);
207+
this.graphics.render(
208+
this.world,
209+
this.parameters.debugRender,
210+
this.alpha,
211+
);
208212
this.gui.stats.end();
209213

210214
requestAnimationFrame(() => this.run());

0 commit comments

Comments
 (0)