Kaynağa Gözat

Merge pull request #6156 from bghgary/gizmo-fix

Fix gizmo math to account for handedness
David Catuhe 6 yıl önce
ebeveyn
işleme
2aad1413b9
2 değiştirilmiş dosya ile 28 ekleme ve 20 silme
  1. 27 19
      src/Gizmos/gizmo.ts
  2. 1 1
      tests/validation/config.json

+ 27 - 19
src/Gizmos/gizmo.ts

@@ -2,7 +2,7 @@ import { Observer } from "../Misc/observable";
 import { Nullable } from "../types";
 import { WebVRFreeCamera } from "../Cameras/VR/webVRCamera";
 import { Scene, IDisposable } from "../scene";
-import { Quaternion, Matrix, Vector3 } from "../Maths/math";
+import { Quaternion, Vector3 } from "../Maths/math";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Mesh } from "../Meshes/mesh";
 import { _TimeToken } from "../Instrumentation/timeToken";
@@ -16,12 +16,11 @@ export class Gizmo implements IDisposable {
      * The root mesh of the gizmo
      */
     public _rootMesh: Mesh;
-    private _attachedMesh: Nullable<AbstractMesh>;
+    private _attachedMesh: Nullable<AbstractMesh> = null;
     /**
      * Ratio for the scale of the gizmo (Default: 1)
      */
     public scaleRatio = 1;
-    private _tmpMatrix = new Matrix();
     /**
      * If a custom mesh has been set (Default: false)
      */
@@ -71,6 +70,7 @@ export class Gizmo implements IDisposable {
     }
 
     private _beforeRenderObserver: Nullable<Observer<Scene>>;
+    private _tempVector = new Vector3();
 
     /**
      * Creates a gizmo
@@ -79,42 +79,50 @@ export class Gizmo implements IDisposable {
     constructor(
         /** The utility layer the gizmo will be added to */
         public gizmoLayer: UtilityLayerRenderer = UtilityLayerRenderer.DefaultUtilityLayer) {
+
         this._rootMesh = new Mesh("gizmoRootNode", gizmoLayer.utilityLayerScene);
+        this._rootMesh.rotationQuaternion = Quaternion.Identity();
+
         this._beforeRenderObserver = this.gizmoLayer.utilityLayerScene.onBeforeRenderObservable.add(() => {
             this._update();
         });
-        this.attachedMesh = null;
     }
 
-    private _tempVector = new Vector3();
     /**
-     * @hidden
      * Updates the gizmo to match the attached mesh's position/rotation
      */
     protected _update() {
         if (this.attachedMesh) {
             const effectiveMesh = this.attachedMesh._effectiveMesh || this.attachedMesh;
-            if (this.updateGizmoRotationToMatchAttachedMesh) {
-                if (!this._rootMesh.rotationQuaternion) {
-                    this._rootMesh.rotationQuaternion = Quaternion.RotationYawPitchRoll(this._rootMesh.rotation.y, this._rootMesh.rotation.x, this._rootMesh.rotation.z);
-                }
 
-                effectiveMesh.computeWorldMatrix().getRotationMatrixToRef(this._tmpMatrix);
-                Quaternion.FromRotationMatrixToRef(this._tmpMatrix, this._rootMesh.rotationQuaternion);
-            } else if (this._rootMesh.rotationQuaternion) {
-                this._rootMesh.rotationQuaternion.set(0, 0, 0, 1);
-            }
+            // Position
             if (this.updateGizmoPositionToMatchAttachedMesh) {
                 this._rootMesh.position.copyFrom(effectiveMesh.absolutePosition);
             }
-            if (this._updateScale && this.gizmoLayer.utilityLayerScene.activeCamera && this.attachedMesh) {
-                var cameraPosition = this.gizmoLayer.utilityLayerScene.activeCamera.globalPosition;
-                if ((<WebVRFreeCamera>this.gizmoLayer.utilityLayerScene.activeCamera).devicePosition) {
-                    cameraPosition = (<WebVRFreeCamera>this.gizmoLayer.utilityLayerScene.activeCamera).devicePosition;
+
+            // Rotation
+            if (this.updateGizmoRotationToMatchAttachedMesh) {
+                effectiveMesh.getWorldMatrix().decompose(undefined, this._rootMesh.rotationQuaternion!);
+            }
+            else {
+                this._rootMesh.rotationQuaternion!.set(0, 0, 0, 1);
+            }
+
+            // Scale
+            if (this._updateScale) {
+                const activeCamera = this.gizmoLayer.utilityLayerScene.activeCamera!;
+                var cameraPosition = activeCamera.globalPosition;
+                if ((<WebVRFreeCamera>activeCamera).devicePosition) {
+                    cameraPosition = (<WebVRFreeCamera>activeCamera).devicePosition;
                 }
                 this._rootMesh.position.subtractToRef(cameraPosition, this._tempVector);
                 var dist = this._tempVector.length() * this.scaleRatio;
                 this._rootMesh.scaling.set(dist, dist, dist);
+
+                // Account for handedness, similar to Matrix.decompose
+                if (effectiveMesh._getWorldMatrixDeterminant() < 0) {
+                    this._rootMesh.scaling.y *= -1;
+                }
             }
         }
     }

+ 1 - 1
tests/validation/config.json

@@ -3,7 +3,7 @@
   "tests": [
     {
       "title": "Nested BBG",
-      "playgroundId": "#ZG0C8B#0",
+      "playgroundId": "#ZG0C8B#1",
       "referenceImage": "nested_BBG.png"
     },
     {