UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

95 lines (79 loc) 3.61 kB
import { Clock } from 'three' import { type ITime } from './engine_types.js'; import { getParam } from './engine_utils.js'; const timescaleUrl = getParam("timescale"); let timeScale = 1; if (typeof timescaleUrl === "number") timeScale = timescaleUrl; /** * Time is a class that provides time-related information. * It is created and used within the Needle Engine Context. */ export class Time implements ITime { /** The time in seconds since the start of Needle Engine. */ get time() { return this._time; } private set time(value: number) { this._time = value; } private _time = 0; /** The time in seconds it took to complete the last frame (Read Only). */ get deltaTime() { return this._deltaTime; } private set deltaTime(value: number) { this._deltaTime = value; } private _deltaTime = 0; /** The time in seconds it took to complete the last frame (Read Only). Timescale is not applied. */ get deltaTimeUnscaled() { return this._deltaTimeUnscaled; } private _deltaTimeUnscaled = 0; /** The scale at which time passes. This can be used for slow motion effects or to speed up time. */ timeScale = 1; /** same as frameCount */ get frame() { return this._frame; } private set frame(value: number) { this._frame = value; } private _frame = 0; /** The total number of frames that have passed (Read Only). Same as frame */ get frameCount() { return this.frame; } /** The time in seconds it took to complete the last frame (Read Only). */ get realtimeSinceStartup(): number { return this.clock.elapsedTime; } /** * @returns {Number} FPS for this frame. * Note that this returns the raw value (e.g. 59.88023952362959) and will fluctuate a lot between frames. * If you want a more stable FPS, use `smoothedFps` instead. */ get fps() { return 1 / this.deltaTime; } /** * Approximated frames per second * @returns the smoothed FPS value over the last 60 frames with decimals. */ get smoothedFps() { return this._smoothedFps; } /** The smoothed time in seconds it took to complete the last frame (Read Only). */ get smoothedDeltaTime() { return 1 / this._smoothedFps; } private clock = new Clock(); private _smoothedFps: number = 0; private _smoothedDeltaTime: number = 0; private readonly _fpsSamples: number[] = []; private _fpsSampleIndex: number = 0; constructor() { if (typeof timeScale === "number") this.timeScale = timeScale; } /** Step the time. This is called automatically by the Needle Engine Context. * @internal */ update() { this.deltaTime = this.clock.getDelta(); // clamp delta time because if tab is not active clock.getDelta can get pretty big this.deltaTime = Math.min(.1, this.deltaTime); this._deltaTimeUnscaled = this.deltaTime; if (this.deltaTime <= 0) this.deltaTime = 0.000000000001; this.deltaTime *= this.timeScale; this.frame += 1; this.time += this.deltaTime; if (this._fpsSamples.length < 60) this._fpsSamples.push(this.deltaTime); else this._fpsSamples[(this._fpsSampleIndex++) % 60] = this.deltaTime; let sum = 0; for (let i = 0; i < this._fpsSamples.length; i++) sum += this._fpsSamples[i]; this._smoothedDeltaTime = sum / this._fpsSamples.length; this._smoothedFps = 1 / this._smoothedDeltaTime; } }