Browse Source

more Mat4 methods

Alexander Rose 7 years ago
parent
commit
e8937bd7cb
1 changed files with 160 additions and 1 deletions
  1. 160 1
      src/mol-math/linear-algebra/3d.ts

+ 160 - 1
src/mol-math/linear-algebra/3d.ts

@@ -77,7 +77,7 @@ export namespace Mat4 {
         mat[15] = 1;
         return mat;
     }
-    
+
     export function ofRows(rows: number[][]): Mat4 {
         const out = zero();
         for (let i = 0; i < 4; i++) {
@@ -463,6 +463,165 @@ export namespace Mat4 {
         }
         return true;
     }
+
+    /**
+     * Generates a frustum matrix with the given bounds
+     */
+    export function frustum(out: Mat4, left: number, right: number, bottom: number, top: number, near: number, far: number) {
+        let rl = 1 / (right - left);
+        let tb = 1 / (top - bottom);
+        let nf = 1 / (near - far);
+        out[0] = (near * 2) * rl;
+        out[1] = 0;
+        out[2] = 0;
+        out[3] = 0;
+        out[4] = 0;
+        out[5] = (near * 2) * tb;
+        out[6] = 0;
+        out[7] = 0;
+        out[8] = (right + left) * rl;
+        out[9] = (top + bottom) * tb;
+        out[10] = (far + near) * nf;
+        out[11] = -1;
+        out[12] = 0;
+        out[13] = 0;
+        out[14] = (far * near * 2) * nf;
+        out[15] = 0;
+        return out;
+    }
+
+    /**
+     * Generates a perspective projection matrix with the given bounds
+     */
+    export function perspective(out: Mat4, fovy: number, aspect: number, near: number, far: number) {
+        let f = 1.0 / Math.tan(fovy / 2);
+        let nf = 1 / (near - far);
+        out[0] = f / aspect;
+        out[1] = 0;
+        out[2] = 0;
+        out[3] = 0;
+        out[4] = 0;
+        out[5] = f;
+        out[6] = 0;
+        out[7] = 0;
+        out[8] = 0;
+        out[9] = 0;
+        out[10] = (far + near) * nf;
+        out[11] = -1;
+        out[12] = 0;
+        out[13] = 0;
+        out[14] = (2 * far * near) * nf;
+        out[15] = 0;
+        return out;
+    }
+
+    /**
+     * Generates a orthogonal projection matrix with the given bounds
+     */
+    export function ortho(out: Mat4, left: number, right: number, bottom: number, top: number, near: number, far: number) {
+        let lr = 1 / (left - right);
+        let bt = 1 / (bottom - top);
+        let nf = 1 / (near - far);
+        out[0] = -2 * lr;
+        out[1] = 0;
+        out[2] = 0;
+        out[3] = 0;
+        out[4] = 0;
+        out[5] = -2 * bt;
+        out[6] = 0;
+        out[7] = 0;
+        out[8] = 0;
+        out[9] = 0;
+        out[10] = 2 * nf;
+        out[11] = 0;
+        out[12] = (left + right) * lr;
+        out[13] = (top + bottom) * bt;
+        out[14] = (far + near) * nf;
+        out[15] = 1;
+        return out;
+    }
+
+    /**
+     * Generates a look-at matrix with the given eye position, focal point, and up axis
+     */
+    export function lookAt(out: Mat4, eye: Vec3, center: Vec3, up: Vec3) {
+        let x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
+        let eyex = eye[0];
+        let eyey = eye[1];
+        let eyez = eye[2];
+        let upx = up[0];
+        let upy = up[1];
+        let upz = up[2];
+        let centerx = center[0];
+        let centery = center[1];
+        let centerz = center[2];
+
+        if (Math.abs(eyex - centerx) < EPSILON.Value &&
+            Math.abs(eyey - centery) < EPSILON.Value &&
+            Math.abs(eyez - centerz) < EPSILON.Value
+        ) {
+            return setIdentity(out);
+        }
+
+        z0 = eyex - centerx;
+        z1 = eyey - centery;
+        z2 = eyez - centerz;
+
+        len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
+        z0 *= len;
+        z1 *= len;
+        z2 *= len;
+
+        x0 = upy * z2 - upz * z1;
+        x1 = upz * z0 - upx * z2;
+        x2 = upx * z1 - upy * z0;
+        len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
+        if (!len) {
+            x0 = 0;
+            x1 = 0;
+            x2 = 0;
+        } else {
+            len = 1 / len;
+            x0 *= len;
+            x1 *= len;
+            x2 *= len;
+        }
+
+        y0 = z1 * x2 - z2 * x1;
+        y1 = z2 * x0 - z0 * x2;
+        y2 = z0 * x1 - z1 * x0;
+
+        len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
+        if (!len) {
+            y0 = 0;
+            y1 = 0;
+            y2 = 0;
+        } else {
+            len = 1 / len;
+            y0 *= len;
+            y1 *= len;
+            y2 *= len;
+        }
+
+        out[0] = x0;
+        out[1] = y0;
+        out[2] = z0;
+        out[3] = 0;
+        out[4] = x1;
+        out[5] = y1;
+        out[6] = z1;
+        out[7] = 0;
+        out[8] = x2;
+        out[9] = y2;
+        out[10] = z2;
+        out[11] = 0;
+        out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+        out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+        out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+        out[15] = 1;
+
+        return out;
+    }
 }
 
 export namespace Vec3 {