diff --git a/examples/src/examples/misc/gizmos.mjs b/examples/src/examples/misc/gizmos.mjs index 2e14d76a30d..b183dfc44d3 100644 --- a/examples/src/examples/misc/gizmos.mjs +++ b/examples/src/examples/misc/gizmos.mjs @@ -13,6 +13,9 @@ function controls({ observer, ReactPCUI, React, jsx, fragment }) { // @ts-ignore window.setType = (/** @type {string} */ value) => setType(value); + // @ts-ignore + window.setProj = (/** @type {number} */ value) => setProj(value); + return fragment( jsx(Panel, { headerText: 'Transform' }, jsx(LabelGroup, { text: 'Type' }, @@ -211,7 +214,7 @@ function controls({ observer, ReactPCUI, React, jsx, fragment }) { ], binding: new BindingTwoWay(), link: { observer, path: 'camera.proj' }, - onSelect: value => setProj((parseInt(value) || 0) - 1) + onSelect: value => setProj((parseInt(value) || 1) - 1) }) ), (proj === pc.PROJECTION_PERSPECTIVE) && @@ -546,7 +549,7 @@ async function example({ pcx, canvas, deviceType, data, glslangPath, twgslPath, gizmoHandler.add(box); this.focus(); - // Change gizmo mode keybinds + // wrappers for control state changes const setType = (/** @type {string} */ value) => { data.set('gizmo.type', value); @@ -554,6 +557,13 @@ async function example({ pcx, canvas, deviceType, data, glslangPath, twgslPath, // @ts-ignore window.top.setType(value); }; + const setProj = (/** @type {number} */ value) => { + data.set('camera.proj', value + 1); + + // call method from top context (same as controls) + // @ts-ignore + window.top.setProj(value); + }; const keydown = (/** @type {KeyboardEvent} */ e) => { gizmoHandler.gizmo.snap = !!e.shiftKey; @@ -577,6 +587,12 @@ async function example({ pcx, canvas, deviceType, data, glslangPath, twgslPath, case '3': setType('scale'); break; + case 'p': + setProj(pc.PROJECTION_PERSPECTIVE); + break; + case 'o': + setProj(pc.PROJECTION_ORTHOGRAPHIC); + break; } }; window.addEventListener('keydown', keydown); diff --git a/extras/gizmo/rotate-gizmo.js b/extras/gizmo/rotate-gizmo.js index 026aa1ff69a..b69456fef0c 100644 --- a/extras/gizmo/rotate-gizmo.js +++ b/extras/gizmo/rotate-gizmo.js @@ -1,4 +1,5 @@ import { + PROJECTION_PERSPECTIVE, math, Color, Quat, @@ -183,9 +184,8 @@ class RotateGizmo extends TransformGizmo { }); app.on('update', () => { - const cameraPos = this._camera.entity.getPosition(); - this._faceAxisLookAt(cameraPos); - this._xyzAxisLookAt(cameraPos); + this._faceAxisLookAtCamera(); + this._xyzAxisLookAtCamera(); if (this._dragging) { const gizmoPos = this.root.getPosition(); @@ -283,14 +283,25 @@ class RotateGizmo extends TransformGizmo { return tmpV1; } - _faceAxisLookAt(position) { - this._shapes.face.entity.lookAt(position); - this._shapes.face.entity.rotateLocal(90, 0, 0); + _faceAxisLookAtCamera() { + if (this._camera.projection === PROJECTION_PERSPECTIVE) { + this._shapes.face.entity.lookAt(this._camera.entity.getPosition()); + this._shapes.face.entity.rotateLocal(90, 0, 0); + } else { + tmpQ1.copy(this._camera.entity.getRotation()); + tmpQ1.getEulerAngles(tmpV1); + this._shapes.face.entity.setEulerAngles(tmpV1); + this._shapes.face.entity.rotateLocal(-90, 0, 0); + } } - _xyzAxisLookAt(position) { - tmpV1.copy(position).sub(this.root.getPosition()); - tmpQ1.copy(this.root.getRotation()).invert().transformVector(tmpV1, tmpV1); + _xyzAxisLookAtCamera() { + if (this._camera.projecion === PROJECTION_PERSPECTIVE) { + tmpV1.copy(this._camera.entity.getPosition()).sub(this.root.getPosition()); + tmpQ1.copy(this.root.getRotation()).invert().transformVector(tmpV1, tmpV1); + } else { + tmpV1.copy(this._camera.entity.forward).mulScalar(-1); + } let angle = Math.atan2(tmpV1.z, tmpV1.y) * math.RAD_TO_DEG; this._shapes.x.entity.setLocalEulerAngles(0, angle - 90, -90); angle = Math.atan2(tmpV1.x, tmpV1.z) * math.RAD_TO_DEG; diff --git a/extras/gizmo/transform-gizmo.js b/extras/gizmo/transform-gizmo.js index 6c3d8172dc5..ed50d43fec7 100644 --- a/extras/gizmo/transform-gizmo.js +++ b/extras/gizmo/transform-gizmo.js @@ -3,6 +3,7 @@ import { CULLFACE_NONE, CULLFACE_BACK, PROJECTION_PERSPECTIVE, + PROJECTION_ORTHOGRAPHIC, BLEND_NORMAL, Color, StandardMaterial, @@ -628,6 +629,9 @@ class TransformGizmo extends Gizmo { } } else { angle = mouseWPos.dot(tmpV2.normalize()) * ROTATE_SCALE; + if (this._camera.projection === PROJECTION_ORTHOGRAPHIC) { + angle /= (this._camera.orthoHeight || 1); + } } }