ogl
Version:
WebGL Library
82 lines (68 loc) • 2.84 kB
JavaScript
import { Vec3 } from '../math/Vec3.js';
import { Quat } from '../math/Quat.js';
import { Mat4 } from '../math/Mat4.js';
import { Euler } from '../math/Euler.js';
export class Transform {
constructor() {
this.parent = null;
this.children = [];
this.visible = true;
this.matrix = new Mat4();
this.worldMatrix = new Mat4();
this.matrixAutoUpdate = true;
this.worldMatrixNeedsUpdate = false;
this.position = new Vec3();
this.quaternion = new Quat();
this.scale = new Vec3(1);
this.rotation = new Euler();
this.up = new Vec3(0, 1, 0);
this.rotation._target.onChange = () => this.quaternion.fromEuler(this.rotation, true);
this.quaternion._target.onChange = () => this.rotation.fromQuaternion(this.quaternion, undefined, true);
}
setParent(parent, notifyParent = true) {
if (this.parent && parent !== this.parent) this.parent.removeChild(this, false);
this.parent = parent;
if (notifyParent && parent) parent.addChild(this, false);
}
addChild(child, notifyChild = true) {
if (!~this.children.indexOf(child)) this.children.push(child);
if (notifyChild) child.setParent(this, false);
}
removeChild(child, notifyChild = true) {
if (!!~this.children.indexOf(child)) this.children.splice(this.children.indexOf(child), 1);
if (notifyChild) child.setParent(null, false);
}
updateMatrixWorld(force) {
if (this.matrixAutoUpdate) this.updateMatrix();
if (this.worldMatrixNeedsUpdate || force) {
if (this.parent === null) this.worldMatrix.copy(this.matrix);
else this.worldMatrix.multiply(this.parent.worldMatrix, this.matrix);
this.worldMatrixNeedsUpdate = false;
force = true;
}
for (let i = 0, l = this.children.length; i < l; i++) {
this.children[i].updateMatrixWorld(force);
}
}
updateMatrix() {
this.matrix.compose(this.quaternion, this.position, this.scale);
this.worldMatrixNeedsUpdate = true;
}
traverse(callback) {
// Return true in callback to stop traversing children
if (callback(this)) return;
for (let i = 0, l = this.children.length; i < l; i++) {
this.children[i].traverse(callback);
}
}
decompose() {
this.matrix.decompose(this.quaternion._target, this.position, this.scale);
this.rotation.fromQuaternion(this.quaternion);
}
lookAt(target, invert = false) {
if (invert) this.matrix.lookAt(this.position, target, this.up);
else this.matrix.lookAt(target, this.position, this.up);
this.matrix.getRotation(this.quaternion._target);
this.rotation.fromQuaternion(this.quaternion);
}
}