Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign Time #1339

Merged
merged 25 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/core/src/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class Engine extends EventDispatcher {

/* @internal */
_renderElementPool: ClassPool<RenderElement> = new ClassPool(RenderElement);
/* @internal */
/* @internal */
_meshRenderDataPool: ClassPool<MeshRenderData> = new ClassPool(MeshRenderData);
/* @internal */
_spriteRenderDataPool: ClassPool<SpriteRenderData> = new ClassPool(SpriteRenderData);
Expand Down Expand Up @@ -158,21 +158,21 @@ export class Engine extends EventDispatcher {
}

/**
* Get the resource manager.
* The resource manager.
*/
get resourceManager(): ResourceManager {
return this._resourceManager;
}

/**
* Get the scene manager.
* The scene manager.
*/
get sceneManager(): SceneManager {
return this._sceneManager;
}

/**
* Get the Time class.
* The time information of the engine.
*/
get time(): Time {
return this._time;
Expand Down Expand Up @@ -293,7 +293,7 @@ export class Engine extends EventDispatcher {
resume(): void {
if (!this._isPaused) return;
this._isPaused = false;
this.time.reset();
this.time._reset();
this._requestId = requestAnimationFrame(this._animate);
}

Expand All @@ -306,7 +306,7 @@ export class Engine extends EventDispatcher {
}

const time = this._time;
time.tick();
time._update();

const deltaTime = time.deltaTime;
this._frameInProcess = true;
Expand All @@ -323,7 +323,7 @@ export class Engine extends EventDispatcher {
scene._activeCameras.sort((camera1, camera2) => camera1.priority - camera2.priority);

componentsManager.callScriptOnStart();
this.physicsManager._initialized && this.physicsManager._update(deltaTime / 1000.0);
this.physicsManager._initialized && this.physicsManager._update(deltaTime);
this.inputManager._update();
componentsManager.callScriptOnUpdate(deltaTime);
componentsManager.callAnimationUpdate(deltaTime);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/RenderPipeline/BasicRenderPipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export class BasicRenderPipeline {
continue;
}
}
renderer._renderFrameCount = engine.time._frameCount;
renderer._renderFrameCount = engine.time.frameCount;
renderer._prepareRender(context);
}
}
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/Scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,11 @@ export class Scene extends EngineObject {
*/
_updateShaderData(): void {
const shaderData = this.shaderData;
const time = this._engine.time;
const lightManager = this._engine._lightManager;

time._updateSceneShaderData(shaderData);

lightManager._updateShaderData(this.shaderData);
cptbtptpbcptdtptp marked this conversation as resolved.
Show resolved Hide resolved
const sunLightIndex = lightManager._getSunLightIndex();
if (sunLightIndex !== -1) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ export class Script extends Component {

/**
* The main loop, called frame by frame.
* @param deltaTime - The deltaTime when the script update.
* @param deltaTime - The delta time since last frame in seconds
*/
onUpdate(deltaTime: number): void {}

/**
* Called after the onUpdate finished, called frame by frame.
* @param deltaTime - The deltaTime when the script update.
* @param deltaTime - The delta time since last frame in seconds
*/
onLateUpdate(deltaTime: number): void {}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/animation/Animator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class Animator extends Component {
continue;
}

this._updateLayer(i, i === 0, deltaTime / 1000, animationUpdate);
this._updateLayer(i, i === 0, deltaTime, animationUpdate);
}
}

Expand Down
117 changes: 73 additions & 44 deletions packages/core/src/base/Time.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import { Vector4 } from "@oasis-engine/math";
import { ShaderData } from "../shader/ShaderData";
import { ShaderProperty } from "../shader/ShaderProperty";

/**
* Tools for calculating the time per frame.
* Provide time related information.
*/
export class Time {
/** @internal */
_frameCount: number = 0;
private static _elapsedTimeProperty = ShaderProperty.getByName("oasis_ElapsedTime");
private static _deltaTimeProperty = ShaderProperty.getByName("oasis_DeltaTime");
cptbtptpbcptdtptp marked this conversation as resolved.
Show resolved Hide resolved

private _frameCount: number = 0;
private _deltaTime: number = 0;
private _unscaledDeltaTime: number = 0;
private _elapsedTime: number = 0;
private _unscaledElapsedTime: number = 0;
private _lastSystemTime: number;

private _clock: { now: () => number };
private _timeScale: number;
private _deltaTime: number;
private _startTime: number;
private _lastTickTime: number;
private _elapsedTimeValue: Vector4 = new Vector4();
private _deltaTimeValue: Vector4 = new Vector4();

/**
* Maximum delta time allowed per frame in seconds.
*
* @remarks
* When the frame rate is low or stutter occurs, `deltaTime` will not exceed the value of `maximumDeltaTime` * `timeScale`.
*/
maximumDeltaTime: number = 0.333333;

/** The scale of time. */
timeScale: number = 1.0;

/*
* The total number of frames since the start of the engine.
Expand All @@ -19,68 +38,78 @@ export class Time {
}

/**
* Constructor of the Time.
* The delta time in seconds from the last frame to the current frame.
*/
constructor() {
this._clock = performance ? performance : Date;

this._timeScale = 1.0;
this._deltaTime = 0.0001;

const now = this._clock.now();
this._startTime = now;
this._lastTickTime = now;
get deltaTime(): number {
return this._deltaTime;
}

reset() {
this._lastTickTime = this._clock.now();
/**
* The unscaled delta time in seconds from the last frame to the current frame.
*/
get unscaledDeltaTime(): number {
return this._unscaledDeltaTime;
}

/**
* Current Time
* The amount of elapsed time in seconds since the start of the engine.
*/
get nowTime(): number {
return this._clock.now();
get elapsedTime(): number {
return this._elapsedTime;
}

/**
* Time between two ticks
* The amount of unscaled elapsed time in seconds since the start of the engine.
*/
get deltaTime(): number {
return this._deltaTime;
get unscaledElapsedTime(): number {
return this._unscaledElapsedTime;
}

/**
* Scaled delta time.
* Constructor of the Time.
*/
get timeScale(): number {
return this._timeScale;
}
set timeScale(s) {
this._timeScale = s;
constructor() {
this._lastSystemTime = performance.now() / 1000;
}

/**
* Unscaled delta time.
* @internal
*/
get unscaledDeltaTime(): number {
return this._deltaTime / this._timeScale;
_reset() {
this._lastSystemTime = performance.now() / 1000;
}

/**
* The elapsed time, after the clock is initialized.
* @internal
*/
get timeSinceStartup(): number {
return this.nowTime - this._startTime;
_update(): void {
const currentSystemTime = performance.now() / 1000;

const unscaledDeltaTime = currentSystemTime - this._lastSystemTime;
this._unscaledDeltaTime = unscaledDeltaTime;
cptbtptpbcptdtptp marked this conversation as resolved.
Show resolved Hide resolved
this._unscaledElapsedTime += unscaledDeltaTime;

const deltaTime = Math.min(unscaledDeltaTime, this.maximumDeltaTime) * this.timeScale;
this._deltaTime = deltaTime;
this._elapsedTime += deltaTime;
this._frameCount++;

this._lastSystemTime = currentSystemTime;
}

/**
* Call every frame, update delta time and other data.
* @internal
*/
public tick(): void {
const now = this.nowTime;
this._deltaTime = (now - this._lastTickTime) * this._timeScale;
this._lastTickTime = now;
this._frameCount++;
_updateSceneShaderData(shaderData: ShaderData): void {
const elapsedTimeValue = this._elapsedTimeValue;
const deltaTimeValue = this._deltaTimeValue;
cptbtptpbcptdtptp marked this conversation as resolved.
Show resolved Hide resolved

const time = this._elapsedTime;
elapsedTimeValue.set(time, Math.sin(time), Math.cos(time), 0);
shaderData.setVector4(Time._elapsedTimeProperty, elapsedTimeValue);

const deltaTime = this._deltaTime;
deltaTimeValue.set(deltaTime, 0, 0, 0);
cptbtptpbcptdtptp marked this conversation as resolved.
Show resolved Hide resolved
shaderData.setVector4(Time._deltaTimeProperty, deltaTimeValue);
}
}
14 changes: 7 additions & 7 deletions packages/core/src/particle/ParticleRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { MathUtil, Vector3, Color } from "@oasis-engine/math";
import { Color, MathUtil, Vector3 } from "@oasis-engine/math";
import { GLCapabilityType } from "../base/Constant";
import { ignoreClone } from "../clone/CloneManager";
import { Buffer } from "../graphic/Buffer";
import { BufferBindFlag } from "../graphic/enums/BufferBindFlag";
import { BufferUsage } from "../graphic/enums/BufferUsage";
import { IndexFormat } from "../graphic/enums/IndexFormat";
import { VertexElementFormat } from "../graphic/enums/VertexElementFormat";
import { VertexElement } from "../graphic/VertexElement";
import { Material } from "../material/Material";
import { BufferMesh } from "../mesh/BufferMesh";
import { MeshRenderer } from "../mesh/MeshRenderer";
import { CullMode, Shader } from "../shader";
import { BlendFactor } from "../shader/enums/BlendFactor";
import { RenderQueueType } from "../shader/enums/RenderQueueType";
import { Shader, CullMode } from "../shader";
import { Texture } from "../texture";
import { MeshRenderer } from "../mesh/MeshRenderer";
import { GLCapabilityType } from "../base/Constant";
import { BufferMesh } from "../mesh/BufferMesh";
import { ignoreClone } from "../clone/CloneManager";

enum DirtyFlagType {
Position = 0x1,
Expand Down Expand Up @@ -560,7 +560,7 @@ export class ParticleRenderer extends MeshRenderer {
this._updateDirtyFlag = 0;
}

this._time += deltaTime / 1000;
this._time += deltaTime;
this.shaderData.setFloat("u_time", this._time);
}

Expand Down
25 changes: 2 additions & 23 deletions packages/core/src/physics/PhysicsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,6 @@ export class PhysicsManager {
/** The fixed time step in seconds at which physics are performed. */
fixedTimeStep: number = 1 / 60;

/**
* The max allowed time step in seconds one frame.
*
* @remarks
* When the frame rate is low or stutter occurs, the maximum execution time of physics will not exceed this value.
* So physics will slow down a bit when performance hitch occurs.
*/
maxAllowedTimeStep: number = 1 / 3;

/**
* The gravity of physics scene.
*/
Expand All @@ -150,18 +141,6 @@ export class PhysicsManager {
}
}

/**
* @deprecated
* Please use `maxAllowedTimeStep` instead.
*/
get maxSumTimeStep(): number {
return this.maxAllowedTimeStep;
}

set maxSumTimeStep(value: number) {
this.maxAllowedTimeStep = value;
}

constructor(engine: Engine) {
this._engine = engine;

Expand Down Expand Up @@ -299,10 +278,10 @@ export class PhysicsManager {
* @internal
*/
_update(deltaTime: number): void {
const { fixedTimeStep: fixedTimeStep, _nativePhysicsManager: nativePhysicsManager } = this;
const { fixedTimeStep, _nativePhysicsManager: nativePhysicsManager } = this;
const componentsManager = this._engine._componentsManager;

const simulateTime = Math.min(this.maxAllowedTimeStep, this._restTime + deltaTime);
const simulateTime = this._restTime + deltaTime;
const step = Math.floor(simulateTime / fixedTimeStep);
this._restTime = simulateTime - step * fixedTimeStep;
for (let i = 0; i < step; i++) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/shadow/ShadowUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class ShadowUtils {
renderer.castShadows &&
ShadowUtils.cullingRenderBounds(renderer.bounds, shadowSliceData.cullPlaneCount, shadowSliceData.cullPlanes)
) {
renderer._renderFrameCount = renderer.engine.time._frameCount;
renderer._renderFrameCount = renderer.engine.time.frameCount;
renderer._prepareRender(context);
}
}
Expand Down
25 changes: 25 additions & 0 deletions tests/src/core/base/Time.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { WebGLEngine } from "@oasis-engine/rhi-webgl";
import { expect } from "chai";

describe("Time", () => {
it("Time basic", () => {
const engine = new WebGLEngine(document.createElement("canvas"));

expect(engine.time.frameCount).to.be.equal(0);
expect(engine.time.elapsedTime).to.be.equal(0);
expect(engine.time.deltaTime).to.be.equal(0);
expect(engine.time.unscaledElapsedTime).to.be.equal(0);
expect(engine.time.unscaledDeltaTime).to.be.equal(0);

expect(engine.time.timeScale).to.be.equal(1);
engine.time.timeScale = 2;
expect(engine.time.timeScale).to.be.equal(2);

expect(engine.time.maximumDeltaTime).to.be.equal(0.333333);
engine.time.maximumDeltaTime = 0.5;
expect(engine.time.maximumDeltaTime).to.be.equal(0.5);

engine.update();
expect(engine.time.frameCount).to.be.equal(1);
});
});
1 change: 0 additions & 1 deletion tests/src/core/physics/PhysicsManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ describe("physics manager test", () => {
engine.physicsManager.initialize(LitePhysics);

expect(engine.physicsManager.gravity.y).to.eq(-9.81);
expect(engine.physicsManager.maxSumTimeStep).to.eq(1 / 3);
expect(engine.physicsManager.fixedTimeStep).to.eq(1 / 60);
});

Expand Down