@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
122 lines (92 loc) • 3.93 kB
JavaScript
import { DoubleSide, Matrix4, MeshBasicMaterial, PlaneGeometry, Quaternion, Vector3 } from "three";
import { ShadedGeometry } from "../../../src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
import { GizmoNode } from "./GizmoNode.js";
import { TransformMode } from "./TransformMode.js";
// Reusable utility variables
const _alignVector = new Vector3(0, 1, 0);
const _identityQuaternion = new Quaternion();
const _dirVector = new Vector3();
const _tempMatrix = new Matrix4();
const _unitX = new Vector3(1, 0, 0);
const _unitY = new Vector3(0, 1, 0);
const _unitZ = new Vector3(0, 0, 1);
const _v1 = new Vector3();
const _v2 = new Vector3();
const _v3 = new Vector3();
const _tempVector = new Vector3();
export class TransformControlsPlane extends GizmoNode {
constructor() {
super();
this.entity.add(ShadedGeometry.from(new PlaneGeometry(100000, 100000, 2, 2),
new MeshBasicMaterial({
visible: false,
wireframe: true,
side: DoubleSide,
transparent: true,
opacity: 0.1,
toneMapped: false
})));
this.isTransformControlsPlane = true;
this.type = 'TransformControlsPlane';
}
update() {
let space = this.space;
/**
*
* @type {Transform}
*/
const transform = this.transform;
transform.position.copy(this.worldPosition);
if (this.mode === TransformMode.Scale) space = 'local'; // scale always oriented to local rotation
_v1.copy(_unitX).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
_v2.copy(_unitY).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
_v3.copy(_unitZ).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
// Align the plane for current transform mode, axis and space.
_alignVector.copy(_v2);
switch (this.mode) {
case TransformMode.Translate:
case TransformMode.Scale:
switch (this.axis) {
case 'X':
_alignVector.copy(this.eye).cross(_v1);
_dirVector.copy(_v1).cross(_alignVector);
break;
case 'Y':
_alignVector.copy(this.eye).cross(_v2);
_dirVector.copy(_v2).cross(_alignVector);
break;
case 'Z':
_alignVector.copy(this.eye).cross(_v3);
_dirVector.copy(_v3).cross(_alignVector);
break;
case 'XY':
_dirVector.copy(_v3);
break;
case 'YZ':
_dirVector.copy(_v1);
break;
case 'XZ':
_alignVector.copy(_v3);
_dirVector.copy(_v2);
break;
case 'XYZ':
case 'E':
_dirVector.set(0, 0, 0);
break;
}
break;
case TransformMode.Rotate:
default:
// special case for rotate
_dirVector.set(0, 0, 0);
}
if (_dirVector.length() === 0) {
// If in rotate mode, make the plane parallel to camera
transform.rotation.copy(this.cameraQuaternion);
} else {
_tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector);
transform.rotation.setFromRotationMatrix(_tempMatrix.elements);
}
super.update();
}
}