浏览代码

Create a static FromUnitVectors method on quaternion

michalzr 4 年之前
父节点
当前提交
3dfd81e369
共有 2 个文件被更改,包括 31 次插入5 次删除
  1. 2 5
      materialsLibrary/src/sky/skyMaterial.ts
  2. 29 0
      src/Maths/math.vector.ts

+ 2 - 5
materialsLibrary/src/sky/skyMaterial.ts

@@ -307,11 +307,8 @@ export class SkyMaterial extends PushMaterial {
             this.sunPosition.y = this.distance * Math.sin(phi) * Math.sin(theta);
             this.sunPosition.z = this.distance * Math.sin(phi) * Math.cos(theta);
 
-            var crossProduct = Vector3.Cross(Vector3.Up(), this.up);
-            var dotProduct = Vector3.Dot(Vector3.Up(), this.up);
-            var quaternion = new Quaternion(crossProduct.x, crossProduct.y, crossProduct.z, 1.0 + dotProduct);
-            quaternion.normalize();
-            this.sunPosition.rotateByQuaternionToRef(quaternion, this.sunPosition);
+            const rotation = Quaternion.FromUnitVectors(Vector3.Up(), this.up);
+            this.sunPosition.rotateByQuaternionToRef(rotation, this.sunPosition);
         }
 
         this._activeEffect.setVector3("sunPosition", this.sunPosition);

+ 29 - 0
src/Maths/math.vector.ts

@@ -3453,6 +3453,35 @@ export class Quaternion {
     }
 
     /**
+     * Creates a rotation quaternion that rotates vector vecFrom to vector vecTo
+     * @param vecFrom defines the direction vector from which to rotate
+     * @param vecTo defines the direction vector to which to rotate
+     * @returns the new quaternion
+     */
+    public static FromUnitVectors(vecFrom: DeepImmutable<Vector3>, vecTo: DeepImmutable<Vector3>): Quaternion {
+        let result: Quaternion;
+        const r = Vector3.Dot(vecFrom, vecTo) + 1;
+
+        if (r < Epsilon) {
+            if (Math.abs(vecFrom.x) > Math.abs(vecFrom.z)) {
+                result = new Quaternion(-vecFrom.y, vecFrom.x, 0, 0);
+            } else {
+                result = new Quaternion(0, - vecFrom.z, vecFrom.y, 0);
+            }
+        } else {
+            const crossProduct = Vector3.Cross(vecFrom, vecTo);
+            result = new Quaternion(
+                crossProduct.x,
+                crossProduct.y,
+                crossProduct.z,
+                r
+            );
+        }
+
+        return result.normalize();
+    }
+
+    /**
      * Creates a new quaternion from the given Euler float angles (y, x, z)
      * @param yaw defines the rotation around Y axis
      * @param pitch defines the rotation around X axis