UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

122 lines (92 loc) 3.93 kB
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(); } }