Skip to content

Commit

Permalink
Improve timestep
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandernanberg committed May 5, 2023
1 parent d2d30b2 commit e982ce5
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 60 deletions.
16 changes: 10 additions & 6 deletions testbed2d/src/Graphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const BALL_INSTANCE_INDEX = 1;

var kk = 0;

function lerp(a: number, b: number, t: number) {
return a + (b - a) * t;
}

export class Graphics {
coll2gfx: Map<number, PIXI.Graphics>;
colorIndex: number;
Expand Down Expand Up @@ -89,7 +93,7 @@ export class Graphics {
);
}

render(world: RAPIER.World, debugRender: Boolean) {
render(world: RAPIER.World, debugRender: Boolean, alpha: number) {
kk += 1;

if (!this.lines) {
Expand Down Expand Up @@ -118,7 +122,7 @@ export class Graphics {
this.lines.clear();
}

this.updatePositions(world);
this.updatePositions(world, alpha);
this.renderer.render(this.scene);
}

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

updatePositions(world: RAPIER.World) {
updatePositions(world: RAPIER.World, alpha: number) {
world.forEachCollider((elt) => {
let gfx = this.coll2gfx.get(elt.handle);
let translation = elt.translation();
let rotation = elt.rotation();

if (!!gfx) {
gfx.position.x = translation.x;
gfx.position.y = -translation.y;
gfx.rotation = -rotation;
gfx.position.x = lerp(gfx.position.x, translation.x, alpha);
gfx.position.y = lerp(gfx.position.y, -translation.y, alpha);
gfx.rotation = lerp(gfx.rotation, -rotation, alpha);
}
});
}
Expand Down
103 changes: 66 additions & 37 deletions testbed2d/src/Testbed.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Graphics} from "./Graphics";
import {Gui} from "./Gui";
import type {DebugInfos} from "./Gui";
import * as md5 from "md5";
import md5 from "md5";
import type * as RAPIER from "@dimforge/rapier2d";

type RAPIER_API = typeof import("@dimforge/rapier2d");
Expand Down Expand Up @@ -60,6 +60,10 @@ export class Testbed {
lastMessageTime: number;
snap: Uint8Array;
snapStepId: number;
frameTime: number;
accumulator: number;
alpha: number;
maxSubsteps: number;

constructor(RAPIER: RAPIER_API, builders: Builders) {
let backends = ["rapier"];
Expand All @@ -73,6 +77,10 @@ export class Testbed {
this.mouse = {x: 0, y: 0};
this.events = new RAPIER.EventQueue(true);
this.switchToDemo(builders.keys().next().value);
this.frameTime = 0;
this.accumulator = 0;
this.alpha = 0;
this.maxSubsteps = 6;

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

run() {
if (this.parameters.running || this.parameters.stepping) {
this.world.maxVelocityIterations = this.parameters.numVelocityIter;
this.world.maxVelocityFrictionIterations =
this.parameters.numVelocityIter * 2;

if (!!this.preTimestepAction) {
this.preTimestepAction(this.graphics);
let time = performance.now();
let fixedStep = this.world.timestep;
let deltaTime = (time - this.frameTime) / 1000;
let substeps = 0;

this.frameTime = time;
this.accumulator += deltaTime;

if (this.accumulator >= fixedStep && substeps < this.maxSubsteps) {
this.accumulator -= fixedStep;
substeps++;

if (this.parameters.running || this.parameters.stepping) {
this.world.maxVelocityIterations =
this.parameters.numVelocityIter;
this.world.maxVelocityFrictionIterations =
this.parameters.numVelocityIter * 2;

if (!!this.preTimestepAction) {
this.preTimestepAction(this.graphics);
}

let t0 = new Date().getTime();
this.world.step(this.events);
this.gui.setTiming(new Date().getTime() - t0);
this.stepId += 1;

if (!!this.parameters.debugInfos) {
let t0 = performance.now();
let snapshot = this.world.takeSnapshot();
let t1 = performance.now();
let snapshotTime = t1 - t0;

let debugInfos: DebugInfos = {
token: this.demoToken,
stepId: this.stepId,
worldHash: "",
worldHashTime: 0,
snapshotTime: 0,
};
t0 = performance.now();
debugInfos.worldHash = md5(snapshot);
t1 = performance.now();
let worldHashTime = t1 - t0;

debugInfos.worldHashTime = worldHashTime;
debugInfos.snapshotTime = snapshotTime;

this.gui.setDebugInfos(debugInfos);
}
}

let t0 = new Date().getTime();
this.world.step(this.events);
this.gui.setTiming(new Date().getTime() - t0);
this.stepId += 1;

if (!!this.parameters.debugInfos) {
let t0 = performance.now();
let snapshot = this.world.takeSnapshot();
let t1 = performance.now();
let snapshotTime = t1 - t0;

let debugInfos: DebugInfos = {
token: this.demoToken,
stepId: this.stepId,
worldHash: "",
worldHashTime: 0,
snapshotTime: 0,
};
t0 = performance.now();
debugInfos.worldHash = md5(snapshot);
t1 = performance.now();
let worldHashTime = t1 - t0;

debugInfos.worldHashTime = worldHashTime;
debugInfos.snapshotTime = snapshotTime;

this.gui.setDebugInfos(debugInfos);
}
this.accumulator = this.accumulator % fixedStep;
this.alpha = this.accumulator / fixedStep;
}

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

this.gui.stats.begin();
this.graphics.render(this.world, this.parameters.debugRender);
this.graphics.render(
this.world,
this.parameters.debugRender,
this.alpha,
);
this.gui.stats.end();

requestAnimationFrame(() => this.run());
Expand Down
1 change: 0 additions & 1 deletion testbed2d/src/demos/characterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
newPos.x += movement.x;
newPos.y += movement.y;
character.setNextKinematicTranslation(newPos);
console.log("here");
};

testbed.setWorld(world);
Expand Down
36 changes: 20 additions & 16 deletions testbed3d/src/Testbed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ export class Testbed {
prevDemo: string;
snap: Uint8Array;
snapStepId: number;
time: number;
physicsTime: number;
frameTime: number;
accumulator: number;
alpha: number;
maxSubsteps: number;

constructor(RAPIER: RAPIER_API, builders: Builders) {
let backends = ["rapier"];
Expand All @@ -72,9 +73,10 @@ export class Testbed {
this.demoToken = 0;
this.mouse = {x: 0, y: 0};
this.events = new RAPIER.EventQueue(true);
this.time = 0;
this.physicsTime = 0;
this.frameTime = 0;
this.accumulator = 0;
this.alpha = 0;
this.maxSubsteps = 6;

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

Expand Down Expand Up @@ -144,13 +146,16 @@ export class Testbed {
run() {
let time = performance.now();
let fixedStep = this.world.timestep;
let deltaTime = (time - this.time) / 1000;
let physicsDeltaTime = (time - this.physicsTime) / 1000;
let deltaTime = (time - this.frameTime) / 1000;
let substeps = 0;

this.time = time;
this.frameTime = time;
this.accumulator += deltaTime;

if (physicsDeltaTime >= fixedStep) {
if (this.accumulator >= fixedStep && substeps < this.maxSubsteps) {
this.accumulator -= fixedStep;
substeps++;

if (this.parameters.running || this.parameters.stepping) {
this.world.maxVelocityIterations =
this.parameters.numVelocityIter;
Expand Down Expand Up @@ -189,22 +194,21 @@ export class Testbed {
}
}

this.physicsTime = time;
this.accumulator -= fixedStep;
this.accumulator = this.accumulator % fixedStep;
this.alpha = this.accumulator / fixedStep;
}

// let alpha = this.accumulator / fixedStep;
let alpha = 1;

console.log(alpha);

if (this.parameters.stepping) {
this.parameters.running = false;
this.parameters.stepping = false;
}

this.gui.stats.begin();
this.graphics.render(this.world, this.parameters.debugRender, alpha);
this.graphics.render(
this.world,
this.parameters.debugRender,
this.alpha,
);
this.gui.stats.end();

requestAnimationFrame(() => this.run());
Expand Down

0 comments on commit e982ce5

Please sign in to comment.