UNPKG

@ar-js-org/ar.js-threejs

Version:

AR.js (THREEx, ARjs) modular package - Typescript version

146 lines (129 loc) 6.15 kB
import { ArBaseControls } from "./ArBaseControls"; import { ISmoothedControlsParameters, IArSmoothedControls } from "./CommonInterfaces/THREEx-interfaces"; import { setParameters } from './common-functions/utilityFunctions'; import { Object3D } from "three"; export class ArSmoothedControls extends ArBaseControls implements IArSmoothedControls { private _lastLerpStepAt: number | null; private _visibleStartedAt: number | null; private _unvisibleStartedAt: number | null; public parameters: ISmoothedControlsParameters; /** * - lerp position/quaternino/scale * - minDelayDetected * - minDelayUndetected * @constructor * @param {[type]} object3d [description] * @param {[type]} parameters [description] */ constructor(object3d: Object3D, parameters?: ISmoothedControlsParameters) { super(object3d); // copy parameters this.object3d.visible = false; this._lastLerpStepAt = null; this._visibleStartedAt = null; this._unvisibleStartedAt = null; // handle default parameters this.parameters = { // lerp coeficient for the position - between [0,1] - default to 1 lerpPosition: 0.8, // lerp coeficient for the quaternion - between [0,1] - default to 1 lerpQuaternion: 0.2, // lerp coeficient for the scale - between [0,1] - default to 1 lerpScale: 0.7, // delay for lerp fixed steps - in seconds - default to 1/120 lerpStepDelay: 1 / 60, // minimum delay the sub-control must be visible before this controls become visible - default to 0 seconds minVisibleDelay: 0.0, // minimum delay the sub-control must be unvisible before this controls become unvisible - default to 0 seconds minUnvisibleDelay: 0.2, }; ////////////////////////////////////////////////////////////////////////////// // setParameters ////////////////////////////////////////////////////////////////////////////// setParameters(parameters, this); } /** * update the object3d with the targetObject3d * @param {Object3D} targetObject3d * @returns {void} */ update(targetObject3d: Object3D): void { var object3d = this.object3d; var parameters = this.parameters; var wasVisible = object3d.visible; var present = performance.now() / 1000; ////////////////////////////////////////////////////////////////////////////// // handle object3d.visible with minVisibleDelay/minUnvisibleDelay ////////////////////////////////////////////////////////////////////////////// if (targetObject3d.visible === false) this._visibleStartedAt = null; if (targetObject3d.visible === true) this._unvisibleStartedAt = null; if (targetObject3d.visible === true && this._visibleStartedAt === null) this._visibleStartedAt = present; if (targetObject3d.visible === false && this._unvisibleStartedAt === null) this._unvisibleStartedAt = present; if (wasVisible === false && targetObject3d.visible === true) { var visibleFor = present - this._visibleStartedAt; if (visibleFor >= this.parameters.minVisibleDelay) { object3d.visible = true; snapDirectlyToTarget(); } // console.log('visibleFor', visibleFor) } if (wasVisible === true && targetObject3d.visible === false) { var unvisibleFor = present - this._unvisibleStartedAt; if (unvisibleFor >= this.parameters.minUnvisibleDelay) { object3d.visible = false; } } ////////////////////////////////////////////////////////////////////////////// // apply lerp on positon/quaternion/scale ////////////////////////////////////////////////////////////////////////////// // apply lerp steps - require fix time steps to behave the same no matter the fps if (this._lastLerpStepAt === null) { applyOneSlerpStep(); this._lastLerpStepAt = present; } else { var nStepsToDo = Math.floor( (present - this._lastLerpStepAt) / this.parameters.lerpStepDelay ); for (var i = 0; i < nStepsToDo; i++) { applyOneSlerpStep(); this._lastLerpStepAt += this.parameters.lerpStepDelay; } } // disable the lerp by directly copying targetObject3d position/quaternion/scale if (false) { snapDirectlyToTarget(); } // update the matrix this.object3d.updateMatrix(); ////////////////////////////////////////////////////////////////////////////// // honor becameVisible/becameUnVisible event ////////////////////////////////////////////////////////////////////////////// // honor becameVisible event if (wasVisible === false && object3d.visible === true) { this.dispatchEvent({ type: "becameVisible" }); } // honor becameUnVisible event if (wasVisible === true && object3d.visible === false) { this.dispatchEvent({ type: "becameUnVisible" }); } return; function snapDirectlyToTarget() { object3d.position.copy(targetObject3d.position); object3d.quaternion.copy(targetObject3d.quaternion); object3d.scale.copy(targetObject3d.scale); } function applyOneSlerpStep() { object3d.position.lerp(targetObject3d.position, parameters.lerpPosition); object3d.quaternion.slerp( targetObject3d.quaternion, parameters.lerpQuaternion ); object3d.scale.lerp(targetObject3d.scale, parameters.lerpScale); } } name(): string { return ""; } }