Browse Source

Fix https://forum.babylonjs.com/t/billboardmode-on-a-gltf-assets-doesnt-works-as-it-should/1999

David Catuhe 6 years ago
parent
commit
5df35c076f
1 changed files with 45 additions and 50 deletions
  1. 45 50
      src/Meshes/transformNode.ts

+ 45 - 50
src/Meshes/transformNode.ts

@@ -72,6 +72,12 @@ export class TransformNode extends Node {
     public billboardMode = TransformNode.BILLBOARDMODE_NONE;
 
     /**
+     * Gets or sets a boolean indicating that parent rotation should be preserved when using billboards.
+     * This could be useful for glTF objects where parent rotation helps converting from right handed to left handed
+     */
+    public preserveParentRotationForBillboard = false;
+
+    /**
      * Multiplication factor on scale x/y/z when computing the world matrix. Eg. for a 1x1x1 cube setting this to 2 will make it a 2x2x2 cube
      */
     @serialize()
@@ -916,54 +922,6 @@ export class TransformNode extends Node {
         this._pivotMatrix.multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[4]);
         Tmp.Matrix[4].multiplyToRef(Tmp.Matrix[0], this._tempMatrix);
 
-        // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
-        if (this.billboardMode !== TransformNode.BILLBOARDMODE_NONE && camera) {
-            if ((this.billboardMode & TransformNode.BILLBOARDMODE_ALL) !== TransformNode.BILLBOARDMODE_ALL) {
-                // Need to decompose each rotation here
-                var currentPosition = Tmp.Vector3[3];
-
-                if (this.parent && this.parent.getWorldMatrix) {
-                    if (this._transformToBoneReferal) {
-                        this.parent.getWorldMatrix().multiplyToRef(this._transformToBoneReferal.getWorldMatrix(), Tmp.Matrix[6]);
-                        Vector3.TransformCoordinatesToRef(this.position, Tmp.Matrix[6], currentPosition);
-                    } else {
-                        Vector3.TransformCoordinatesToRef(this.position, this.parent.getWorldMatrix(), currentPosition);
-                    }
-                } else {
-                    currentPosition.copyFrom(this.position);
-                }
-
-                currentPosition.subtractInPlace(camera.globalPosition);
-
-                var finalEuler = Tmp.Vector3[4].copyFromFloats(0, 0, 0);
-                if ((this.billboardMode & TransformNode.BILLBOARDMODE_X) === TransformNode.BILLBOARDMODE_X) {
-                    finalEuler.x = Math.atan2(-currentPosition.y, currentPosition.z);
-                }
-
-                if ((this.billboardMode & TransformNode.BILLBOARDMODE_Y) === TransformNode.BILLBOARDMODE_Y) {
-                    finalEuler.y = Math.atan2(currentPosition.x, currentPosition.z);
-                }
-
-                if ((this.billboardMode & TransformNode.BILLBOARDMODE_Z) === TransformNode.BILLBOARDMODE_Z) {
-                    finalEuler.z = Math.atan2(currentPosition.y, currentPosition.x);
-                }
-
-                Matrix.RotationYawPitchRollToRef(finalEuler.y, finalEuler.x, finalEuler.z, Tmp.Matrix[0]);
-            } else {
-                Tmp.Matrix[1].copyFrom(camera.getViewMatrix());
-
-                Tmp.Matrix[1].setTranslationFromFloats(0, 0, 0);
-                Tmp.Matrix[1].invertToRef(Tmp.Matrix[0]);
-            }
-
-            if (this._scene.useRightHandedSystem) {
-                Matrix.ScalingToRef(1, 1, -1, Tmp.Matrix[1]);
-                Tmp.Matrix[0].multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[0]);
-            }
-
-            this._tempMatrix.multiplyToRef(Tmp.Matrix[0], this._tempMatrix);
-        }
-
         // Post multiply inverse of pivotMatrix
         if (this._postMultiplyPivotMatrix) {
             this._tempMatrix.multiplyToRef(this._pivotMatrixInverse, this._tempMatrix);
@@ -974,7 +932,8 @@ export class TransformNode extends Node {
 
         // Parent
         if (this.parent && this.parent.getWorldMatrix) {
-            if (this.billboardMode !== TransformNode.BILLBOARDMODE_NONE) {
+            // We do not want parent rotation
+            if (this.billboardMode !== TransformNode.BILLBOARDMODE_NONE && !this.preserveParentRotationForBillboard) {
                 if (this._transformToBoneReferal) {
                     this.parent.getWorldMatrix().multiplyToRef(this._transformToBoneReferal.getWorldMatrix(), Tmp.Matrix[7]);
                 } else {
@@ -989,7 +948,6 @@ export class TransformNode extends Node {
                 Tmp.Matrix[7].setTranslation(translation);
 
                 this._localMatrix.multiplyToRef(Tmp.Matrix[7], this._worldMatrix);
-
             } else {
                 if (this._transformToBoneReferal) {
                     this._localMatrix.multiplyToRef(this.parent.getWorldMatrix(), Tmp.Matrix[6]);
@@ -998,11 +956,48 @@ export class TransformNode extends Node {
                     this._localMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
                 }
             }
+
             this._markSyncedWithParent();
         } else {
             this._worldMatrix.copyFrom(this._localMatrix);
         }
 
+        // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
+        if (this.billboardMode !== TransformNode.BILLBOARDMODE_NONE && camera) {
+            let storedTranslation = Tmp.Vector3[0];
+            this._worldMatrix.getTranslationToRef(storedTranslation); // Save translation
+
+            // Cancel camera rotation
+            Tmp.Matrix[1].copyFrom(camera.getViewMatrix());
+            Tmp.Matrix[1].setTranslationFromFloats(0, 0, 0);
+            Tmp.Matrix[1].invertToRef(Tmp.Matrix[0]);
+
+            if ((this.billboardMode & TransformNode.BILLBOARDMODE_ALL) !== TransformNode.BILLBOARDMODE_ALL) {
+                Tmp.Matrix[0].decompose(undefined, Tmp.Quaternion[0], undefined);
+                let eulerAngles = Tmp.Vector3[1];
+                Tmp.Quaternion[0].toEulerAnglesToRef(eulerAngles);
+
+                if ((this.billboardMode & TransformNode.BILLBOARDMODE_X) !== TransformNode.BILLBOARDMODE_X) {
+                    eulerAngles.x = 0;
+                }
+
+                if ((this.billboardMode & TransformNode.BILLBOARDMODE_Y) !== TransformNode.BILLBOARDMODE_Y) {
+                    eulerAngles.y = 0;
+                }
+
+                if ((this.billboardMode & TransformNode.BILLBOARDMODE_Z) !== TransformNode.BILLBOARDMODE_Z) {
+                    eulerAngles.z = 0;
+                }
+
+                Matrix.RotationYawPitchRollToRef(eulerAngles.y, eulerAngles.x, eulerAngles.z, Tmp.Matrix[0]);
+            }
+            this._worldMatrix.setTranslationFromFloats(0, 0, 0);
+            this._worldMatrix.multiplyToRef(Tmp.Matrix[0], this._worldMatrix);
+
+            // Restore translation
+            this._worldMatrix.setTranslation(Tmp.Vector3[0]);
+        }
+
         // Normal matrix
         if (!this.ignoreNonUniformScaling) {
             if (this.scaling.isNonUniform) {