playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
125 lines (124 loc) • 4.08 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { Quat } from "../../../core/math/quat.js";
import { Vec3 } from "../../../core/math/vec3.js";
import { InputController } from "../input.js";
import { damp } from "../math.js";
import { Pose } from "../pose.js";
const dir = new Vec3();
const offset = new Vec3();
const angles = new Vec3();
const rotation = new Quat();
class OrbitController extends InputController {
constructor() {
super(...arguments);
/**
* @type {Pose}
* @private
*/
__publicField(this, "_targetRootPose", new Pose());
/**
* @type {Pose}
* @private
*/
__publicField(this, "_rootPose", new Pose());
/**
* @type {Pose}
* @private
*/
__publicField(this, "_targetChildPose", new Pose());
/**
* @type {Pose}
* @private
*/
__publicField(this, "_childPose", new Pose());
/**
* The rotation damping. In the range 0 to 1, where a value of 0 means no damping and 1 means
* full damping. Default is 0.98.
*/
__publicField(this, "rotateDamping", 0.98);
/**
* The movement damping. In the range 0 to 1, where a value of 0 means no damping and 1 means
* full damping. Default is 0.98.
*/
__publicField(this, "moveDamping", 0.98);
/**
* The zoom damping. A higher value means more damping. A value of 0 means no damping.
*/
__publicField(this, "zoomDamping", 0.98);
}
set pitchRange(range) {
this._targetRootPose.pitchRange.copy(range);
this._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));
}
get pitchRange() {
return this._targetRootPose.pitchRange;
}
set yawRange(range) {
this._targetRootPose.yawRange.copy(range);
this._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));
}
get yawRange() {
return this._targetRootPose.yawRange;
}
set zoomRange(range) {
this._targetChildPose.zRange.copy(range);
this._childPose.copy(this._targetChildPose.move(Vec3.ZERO));
}
get zoomRange() {
return this._targetRootPose.zRange;
}
/**
* @param {Pose} pose - The initial pose of the controller.
* @param {boolean} [smooth] - Whether to smooth the transition.
*/
attach(pose, smooth = true) {
this._targetRootPose.set(pose.getFocus(dir), pose.angles, 0);
this._targetChildPose.position.set(0, 0, pose.distance);
if (!smooth) {
this._rootPose.copy(this._targetRootPose);
this._childPose.copy(this._targetChildPose);
}
}
detach() {
this._targetRootPose.copy(this._rootPose);
this._targetChildPose.copy(this._childPose);
}
/**
* @param {InputFrame<{ move: number[], rotate: number[] }>} frame - The input frame.
* @param {number} dt - The delta time.
* @returns {Pose} - The controller pose.
*/
update(frame, dt) {
const { move, rotate } = frame.read();
offset.set(move[0], move[1], 0);
rotation.setFromEulerAngles(this._rootPose.angles).transformVector(offset, offset);
this._targetRootPose.move(offset);
const { z: dist } = this._targetChildPose.position;
this._targetChildPose.move(offset.set(0, 0, dist * (1 + move[2]) - dist));
this._targetRootPose.rotate(angles.set(-rotate[1], -rotate[0], 0));
this._rootPose.lerp(
this._rootPose,
this._targetRootPose,
damp(this.moveDamping, dt),
damp(this.rotateDamping, dt),
1
);
this._childPose.lerp(
this._childPose,
this._targetChildPose,
damp(this.zoomDamping, dt),
1,
1
);
rotation.setFromEulerAngles(this._rootPose.angles).transformVector(this._childPose.position, offset).add(this._rootPose.position);
return this._pose.set(offset, this._rootPose.angles, this._childPose.position.z);
}
destroy() {
this.detach();
}
}
export {
OrbitController
};