Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / src / javajs / util / M4.java
index 0fb491b..c19ed88 100644 (file)
-/*\r
-   Copyright (C) 1997,1998,1999\r
-   Kenji Hiranabe, Eiwa System Management, Inc.\r
-\r
-   This program is free software.\r
-   Implemented by Kenji Hiranabe(hiranabe@esm.co.jp),\r
-   conforming to the Java(TM) 3D API specification by Sun Microsystems.\r
-\r
-   Permission to use, copy, modify, distribute and sell this software\r
-   and its documentation for any purpose is hereby granted without fee,\r
-   provided that the above copyright notice appear in all copies and\r
-   that both that copyright notice and this permission notice appear\r
-   in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc.\r
-   makes no representations about the suitability of this software for any\r
-   purpose.  It is provided "AS IS" with NO WARRANTY.\r
-*/\r
-package javajs.util;\r
-\r
-/**\r
- * A single precision floating point 4 by 4 matrix.\r
- * \r
- * @author Kenji hiranabe\r
- * \r
- *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique\r
- *         constructor and method names for the optimization of compiled\r
- *         JavaScript using Java2Script\r
- */\r
-public class M4 extends M34 {\r
-\r
-  /**\r
-   * The fourth element of the first row.\r
-   */\r
-  public float m03;\r
-\r
-  /**\r
-   * The fourth element of the second row.\r
-   */\r
-  public float m13;\r
-\r
-  /**\r
-   * The fourth element of the third row.\r
-   */\r
-  public float m23;\r
-\r
-  /**\r
-   * The first element of the fourth row.\r
-   */\r
-  public float m30;\r
-\r
-  /**\r
-   * The second element of the fourth row.\r
-   */\r
-  public float m31;\r
-\r
-  /**\r
-   * The third element of the fourth row.\r
-   */\r
-  public float m32;\r
-\r
-  /**\r
-   * The fourth element of the fourth row.\r
-   */\r
-  public float m33 = 0;\r
-\r
-  /**\r
-   * all zeros\r
-   * @j2sIgnore\r
-   */\r
-  public M4() {\r
-  }\r
-  /**\r
-   * Constructs and initializes a Matrix4f from the specified 16 element array.\r
-   * this.m00 =v[0], this.m01=v[1], etc.\r
-   * \r
-   * @param v\r
-   *        the array of length 16 containing in order\r
-   * @return m\r
-   */\r
-  public static M4 newA16(float[] v) {\r
-    M4 m = new M4();\r
-    m.m00 = v[0];\r
-    m.m01 = v[1];\r
-    m.m02 = v[2];\r
-    m.m03 = v[3];\r
-\r
-    m.m10 = v[4];\r
-    m.m11 = v[5];\r
-    m.m12 = v[6];\r
-    m.m13 = v[7];\r
-\r
-    m.m20 = v[8];\r
-    m.m21 = v[9];\r
-    m.m22 = v[10];\r
-    m.m23 = v[11];\r
-\r
-    m.m30 = v[12];\r
-    m.m31 = v[13];\r
-    m.m32 = v[14];\r
-    m.m33 = v[15];\r
-\r
-    return m;\r
-  }\r
-\r
-  /**\r
-   * Constructs a new matrix with the same values as the Matrix4f parameter.\r
-   * \r
-   * @param m1\r
-   *        the source matrix\r
-   * @return m\r
-   */\r
-  public static M4 newM4(M4 m1) {\r
-    M4 m = new M4();\r
-    if (m1 == null) {\r
-      m.setIdentity();\r
-      return m;\r
-    }\r
-    m.setToM3(m1);\r
-    m.m03 = m1.m03;\r
-    m.m13 = m1.m13;\r
-    m.m23 = m1.m23;\r
-    m.m30 = m1.m30;\r
-    m.m31 = m1.m31;\r
-    m.m32 = m1.m32;\r
-    m.m33 = m1.m33;\r
-    return m;\r
-  }\r
-\r
-  /**\r
-   * Constructs and initializes a Matrix4f from the rotation matrix and\r
-   * translation.\r
-   * \r
-   * @param m1\r
-   *        The rotation matrix representing the rotational components\r
-   * @param t\r
-   *        The translational components of the matrix\r
-   * @return m\r
-   */\r
-  public static M4 newMV(M3 m1, T3 t) {\r
-    M4 m = new M4();\r
-    m.setMV(m1, t);\r
-    return m;\r
-  }\r
-\r
-  /**\r
-   * Sets this matrix to all zeros.\r
-   */\r
-  public void setZero() {\r
-    clear33();\r
-    m03 = m13 = m23 = m30 = m31 = m32 = m33 = 0.0f;\r
-  }\r
-\r
-  /**\r
-   * Sets this Matrix4f to identity.\r
-   */\r
-  public void setIdentity() {\r
-    setZero();\r
-    m00 = m11 = m22 = m33 = 1.0f;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to a copy of the passed matrix m1.\r
-   * \r
-   * @param m1\r
-   *        the matrix to be copied\r
-   * @return this\r
-   */\r
-  public M4 setM4(M4 m1) {\r
-    setM33(m1);\r
-    m03 = m1.m03;\r
-    m13 = m1.m13;\r
-    m23 = m1.m23;\r
-    m30 = m1.m30;\r
-    m31 = m1.m31;\r
-    m32 = m1.m32;\r
-    m33 = m1.m33;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Initializes a Matrix4f from the rotation matrix and translation.\r
-   * \r
-   * @param m1\r
-   *        The rotation matrix representing the rotational components\r
-   * @param t\r
-   *        The translational components of the matrix\r
-   */\r
-  public void setMV(M3 m1, T3 t) {\r
-    setM33(m1);\r
-    setTranslation(t);\r
-    m33 = 1;\r
-  }\r
-\r
-  /**\r
-   * Sets the rotational component (upper 3x3) of this matrix to the matrix\r
-   * values in the single precision Matrix3f argument; the other elements of\r
-   * this matrix are initialized as if this were an identity matrix (ie, affine\r
-   * matrix with no translational component).\r
-   * \r
-   * @param m1\r
-   *        the 3x3 matrix\r
-   */\r
-  public void setToM3(M34 m1) {\r
-    setM33(m1);\r
-    m03 = m13 = m23 = m30 = m31 = m32 = 0.0f;\r
-    m33 = 1.0f;\r
-  }\r
-\r
-  /**\r
-   * Sets the rotational component (upper 3x3) of this matrix \r
-   * to a rotation given by an axis angle\r
-   * \r
-   * @param a\r
-   *        the axis and angle to be converted\r
-   */\r
-  public void setToAA(A4 a) {\r
-    setIdentity();\r
-    setAA33(a);\r
-  }\r
-\r
-  /**\r
-   * Sets the values in this Matrix4f equal to the row-major array parameter\r
-   * (ie, the first four elements of the array will be copied into the first row\r
-   * of this matrix, etc.).\r
-   * \r
-   * @param m\r
-   */\r
-  public void setA(float m[]) {\r
-    m00 = m[0];\r
-    m01 = m[1];\r
-    m02 = m[2];\r
-    m03 = m[3];\r
-    m10 = m[4];\r
-    m11 = m[5];\r
-    m12 = m[6];\r
-    m13 = m[7];\r
-    m20 = m[8];\r
-    m21 = m[9];\r
-    m22 = m[10];\r
-    m23 = m[11];\r
-    m30 = m[12];\r
-    m31 = m[13];\r
-    m32 = m[14];\r
-    m33 = m[15];\r
-  }\r
-\r
-  /**\r
-   * Modifies the translational components of this matrix to the values of the\r
-   * Vector3f argument; the other values of this matrix are not modified.\r
-   * \r
-   * @param trans\r
-   *        the translational component\r
-   */\r
-  public void setTranslation(T3 trans) {\r
-    m03 = trans.x;\r
-    m13 = trans.y;\r
-    m23 = trans.z;\r
-  }\r
-\r
-  /**\r
-   * Sets the specified element of this matrix4f to the value provided.\r
-   * \r
-   * @param row\r
-   *        the row number to be modified (zero indexed)\r
-   * @param col\r
-   *        the column number to be modified (zero indexed)\r
-   * @param v\r
-   *        the new value\r
-   */\r
-  public void setElement(int row, int col, float v) {\r
-    if (row < 3 && col < 3) {\r
-      set33(row, col, v);\r
-      return;\r
-    }\r
-    if (row > 3 || col > 3)\r
-      err();\r
-    switch (row) {\r
-    case 0:\r
-      m03 = v;\r
-      return;\r
-    case 1:\r
-      m13 = v;\r
-      return;\r
-    case 2:\r
-      m23 = v;\r
-      return;\r
-    }\r
-    switch (col) {\r
-    case 0:\r
-      m30 = v;\r
-      return;\r
-    case 1:\r
-      m31 = v;\r
-      return;\r
-    case 2:\r
-      m32 = v;\r
-      return;\r
-    case 3:\r
-      m33 = v;\r
-      return;\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Retrieves the value at the specified row and column of this matrix.\r
-   * \r
-   * @param row\r
-   *        the row number to be retrieved (zero indexed)\r
-   * @param col\r
-   *        the column number to be retrieved (zero indexed)\r
-   * @return the value at the indexed element\r
-   */\r
-  public float getElement(int row, int col) {\r
-    if (row < 3 && col < 3)\r
-      return get33(row, col);\r
-    if (row > 3 || col > 3) {\r
-      err();\r
-      return 0;\r
-    }\r
-    switch (row) {\r
-    case 0:\r
-      return m03;\r
-    case 1:\r
-      return m13;\r
-    case 2:\r
-      return m23;\r
-    default:\r
-      switch (col) {\r
-      case 0:\r
-        return m30;\r
-      case 1:\r
-        return m31;\r
-      case 2:\r
-        return m32;\r
-      default:\r
-        return m33;\r
-      }\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Retrieves the translational components of this matrix.\r
-   * \r
-   * @param trans\r
-   *        the vector that will receive the translational component\r
-   */\r
-  public void getTranslation(T3 trans) {\r
-    trans.x = m03;\r
-    trans.y = m13;\r
-    trans.z = m23;\r
-  }\r
-\r
-  /**\r
-   * Gets the upper 3x3 values of this matrix and places them into the matrix\r
-   * m1.\r
-   * \r
-   * @param m1\r
-   *        The matrix that will hold the values\r
-   */\r
-  public void getRotationScale(M3 m1) {\r
-    m1.m00 = m00;\r
-    m1.m01 = m01;\r
-    m1.m02 = m02;\r
-    m1.m10 = m10;\r
-    m1.m11 = m11;\r
-    m1.m12 = m12;\r
-    m1.m20 = m20;\r
-    m1.m21 = m21;\r
-    m1.m22 = m22;\r
-  }\r
-\r
-  /**\r
-   * Replaces the upper 3x3 matrix values of this matrix with the values in the\r
-   * matrix m1.\r
-   * \r
-   * @param m1\r
-   *        The matrix that will be the new upper 3x3\r
-   */\r
-  public void setRotationScale(M3 m1) {\r
-    m00 = m1.m00;\r
-    m01 = m1.m01;\r
-    m02 = m1.m02;\r
-    m10 = m1.m10;\r
-    m11 = m1.m11;\r
-    m12 = m1.m12;\r
-    m20 = m1.m20;\r
-    m21 = m1.m21;\r
-    m22 = m1.m22;\r
-  }\r
-\r
-  /**\r
-   * Sets the specified row of this matrix4f to the four values provided.\r
-   * \r
-   * @param row\r
-   *        the row number to be modified (zero indexed)\r
-   * @param v\r
-   *        the replacement row\r
-   */\r
-  public void setRowA(int row, float v[]) {\r
-    if (row < 3)\r
-      setRow33(row, v);\r
-    switch (row) {\r
-    case 0:\r
-      m03 = v[3];\r
-      return;\r
-    case 1:\r
-      m13 = v[3];\r
-      return;\r
-    case 2:\r
-      m23 = v[3];\r
-      return;\r
-    case 3:\r
-      m30 = v[0];\r
-      m31 = v[1];\r
-      m32 = v[2];\r
-      m33 = v[3];\r
-      return;\r
-    }\r
-    err();\r
-  }\r
-\r
-  /**\r
-   * Copies the matrix values in the specified row into the array parameter.\r
-   * \r
-   * @param row\r
-   *        the matrix row\r
-   * @param v\r
-   *        The array into which the matrix row values will be copied\r
-   */\r
-  @Override\r
-  public void getRow(int row, float v[]) {\r
-    if (row < 3)\r
-      getRow33(row, v);\r
-    switch (row) {\r
-    case 0:\r
-      v[3] = m03;\r
-      return;\r
-    case 1:\r
-      v[3] = m13;\r
-      return;\r
-    case 2:\r
-      v[3] = m23;\r
-      return;\r
-    case 3:\r
-      v[0] = m30;\r
-      v[1] = m31;\r
-      v[2] = m32;\r
-      v[3] = m33;\r
-      return;\r
-    }\r
-    err();\r
-  }\r
-\r
-  /**\r
-   * Sets the specified column of this matrix4f to the four values provided.\r
-   * \r
-   * @param column\r
-   *        the column number to be modified (zero indexed)\r
-   * @param x\r
-   *        the first row element\r
-   * @param y\r
-   *        the second row element\r
-   * @param z\r
-   *        the third row element\r
-   * @param w\r
-   *        the fourth row element\r
-   */\r
-  public void setColumn4(int column, float x, float y, float z, float w) {\r
-    if (column == 0) {\r
-      m00 = x;\r
-      m10 = y;\r
-      m20 = z;\r
-      m30 = w;\r
-    } else if (column == 1) {\r
-      m01 = x;\r
-      m11 = y;\r
-      m21 = z;\r
-      m31 = w;\r
-    } else if (column == 2) {\r
-      m02 = x;\r
-      m12 = y;\r
-      m22 = z;\r
-      m32 = w;\r
-    } else if (column == 3) {\r
-      m03 = x;\r
-      m13 = y;\r
-      m23 = z;\r
-      m33 = w;\r
-    } else {\r
-      err();\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Sets the specified column of this matrix4f to the four values provided.\r
-   * \r
-   * @param column\r
-   *        the column number to be modified (zero indexed)\r
-   * @param v\r
-   *        the replacement column\r
-   */\r
-  public void setColumnA(int column, float v[]) {\r
-    if (column < 3)\r
-      setColumn33(column, v);\r
-    switch (column) {\r
-    case 0:\r
-      m30 = v[3];\r
-      return;\r
-    case 1:\r
-      m31 = v[3];\r
-      return;\r
-    case 2:\r
-      m32 = v[3];\r
-      return;\r
-    case 3:\r
-      m03 = v[0];\r
-      m13 = v[1];\r
-      m23 = v[2];\r
-      m33 = v[3];\r
-      return;\r
-    default:\r
-      err();\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Copies the matrix values in the specified column into the array parameter.\r
-   * \r
-   * @param column\r
-   *        the matrix column\r
-   * @param v\r
-   *        The array into which the matrix column values will be copied\r
-   */\r
-  public void getColumn(int column, float v[]) {\r
-    if (column < 3)\r
-      getColumn33(column, v);\r
-    switch (column) {\r
-    case 0:\r
-      v[3] = m30;\r
-      return;\r
-    case 1:\r
-      v[3] = m31;\r
-      return;\r
-    case 2:\r
-      v[3] = m32;\r
-      return;\r
-    case 3:\r
-      v[0] = m03;\r
-      v[1] = m13;\r
-      v[2] = m23;\r
-      v[3] = m33;\r
-      return;\r
-    default:\r
-      err();\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to the matrix difference of itself and matrix\r
-   * m1 (this = this - m1).\r
-   * \r
-   * @param m1\r
-   *        the other matrix\r
-   */\r
-  public void sub(M4 m1) {\r
-    sub33(m1);\r
-    m03 -= m1.m03;\r
-    m13 -= m1.m13;\r
-    m23 -= m1.m23;\r
-    m30 -= m1.m30;\r
-    m31 -= m1.m31;\r
-    m32 -= m1.m32;\r
-    m33 -= m1.m33;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to its transpose.\r
-   */\r
-  public void transpose() {\r
-    transpose33();\r
-    float tmp = m03;\r
-    m03 = m30;\r
-    m30 = tmp;\r
-\r
-    tmp = m13;\r
-    m13 = m31;\r
-    m31 = tmp;\r
-\r
-    tmp = m23;\r
-    m23 = m32;\r
-    m32 = tmp;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to its inverse.\r
-   * @return this\r
-   */\r
-  public M4 invert() {\r
-    float s = determinant4();\r
-    if (s == 0.0)\r
-      return this;\r
-    s = 1 / s;\r
-    // alias-safe way.\r
-    // less *,+,- calculation than expanded expression.\r
-    set(m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13\r
-        * (m21 * m32 - m22 * m31), m21 * (m02 * m33 - m03 * m32) + m22\r
-        * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31), m31\r
-        * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33\r
-        * (m01 * m12 - m02 * m11), m01 * (m13 * m22 - m12 * m23) + m02\r
-        * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22),\r
-\r
-    m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10\r
-        * (m23 * m32 - m22 * m33), m22 * (m00 * m33 - m03 * m30) + m23\r
-        * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33), m32\r
-        * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30\r
-        * (m03 * m12 - m02 * m13), m02 * (m13 * m20 - m10 * m23) + m03\r
-        * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22),\r
-\r
-    m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11\r
-        * (m23 * m30 - m20 * m33), m23 * (m00 * m31 - m01 * m30) + m20\r
-        * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33), m33\r
-        * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31\r
-        * (m03 * m10 - m00 * m13), m03 * (m11 * m20 - m10 * m21) + m00\r
-        * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20),\r
-\r
-    m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12\r
-        * (m21 * m30 - m20 * m31), m20 * (m02 * m31 - m01 * m32) + m21\r
-        * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31), m30\r
-        * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32\r
-        * (m01 * m10 - m00 * m11), m00 * (m11 * m22 - m12 * m21) + m01\r
-        * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20));\r
-    scale(s);\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Sets 16 values\r
-   * \r
-   * @param m00\r
-   * @param m01\r
-   * @param m02\r
-   * @param m03\r
-   * @param m10\r
-   * @param m11\r
-   * @param m12\r
-   * @param m13\r
-   * @param m20\r
-   * @param m21\r
-   * @param m22\r
-   * @param m23\r
-   * @param m30\r
-   * @param m31\r
-   * @param m32\r
-   * @param m33\r
-   */\r
-  private void set(float m00, float m01, float m02, float m03, float m10,\r
-                   float m11, float m12, float m13, float m20, float m21,\r
-                   float m22, float m23, float m30, float m31, float m32,\r
-                   float m33) {\r
-    this.m00 = m00;\r
-    this.m01 = m01;\r
-    this.m02 = m02;\r
-    this.m03 = m03;\r
-    this.m10 = m10;\r
-    this.m11 = m11;\r
-    this.m12 = m12;\r
-    this.m13 = m13;\r
-    this.m20 = m20;\r
-    this.m21 = m21;\r
-    this.m22 = m22;\r
-    this.m23 = m23;\r
-    this.m30 = m30;\r
-    this.m31 = m31;\r
-    this.m32 = m32;\r
-    this.m33 = m33;\r
-  }\r
-  /**\r
-   * Computes the determinant of this matrix.\r
-   * \r
-   * @return the determinant of the matrix\r
-   */\r
-  public float determinant4() {\r
-    // less *,+,- calculation than expanded expression.\r
-    return (m00 * m11 - m01 * m10) * (m22 * m33 - m23 * m32)\r
-        - (m00 * m12 - m02 * m10) * (m21 * m33 - m23 * m31)\r
-        + (m00 * m13 - m03 * m10) * (m21 * m32 - m22 * m31)\r
-        + (m01 * m12 - m02 * m11) * (m20 * m33 - m23 * m30)\r
-        - (m01 * m13 - m03 * m11) * (m20 * m32 - m22 * m30)\r
-        + (m02 * m13 - m03 * m12) * (m20 * m31 - m21 * m30);\r
-\r
-  }\r
-\r
-  /**\r
-   * Multiplies each element of this matrix by a scalar.\r
-   * \r
-   * @param scalar\r
-   *        The scalar multiplier.\r
-   */\r
-  private void scale(float scalar) {\r
-    mul33(scalar);\r
-    m03 *= scalar;\r
-    m13 *= scalar;\r
-    m23 *= scalar;\r
-    m30 *= scalar;\r
-    m31 *= scalar;\r
-    m32 *= scalar;\r
-    m33 *= scalar;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to the result of multiplying itself with\r
-   * matrix m1.\r
-   * \r
-   * @param m1\r
-   *        the other matrix\r
-   */\r
-  public void mul(M4 m1) {\r
-    mul2(this, m1);\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to the result of multiplying the two argument\r
-   * matrices together.\r
-   * \r
-   * @param m1\r
-   *        the first matrix\r
-   * @param m2\r
-   *        the second matrix\r
-   */\r
-  public void mul2(M4 m1, M4 m2) {\r
-    // alias-safe way.\r
-    set(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30,\r
-        m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31,\r
-        m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32,\r
-        m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33,\r
-\r
-        m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30,\r
-        m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31,\r
-        m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32,\r
-        m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33,\r
-\r
-        m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30,\r
-        m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31,\r
-        m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32,\r
-        m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33,\r
-\r
-        m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30,\r
-        m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31,\r
-        m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32,\r
-        m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33);\r
-  }\r
-\r
-  /**\r
-   * Transform the vector vec using this Matrix4f and place the result back into\r
-   * vec.\r
-   * \r
-   * @param vec\r
-   *        the single precision vector to be transformed\r
-   */\r
-  public void transform(T4 vec) {\r
-    transform2(vec, vec);\r
-  }\r
-\r
-  /**\r
-   * Transform the vector vec using this Matrix4f and place the result into\r
-   * vecOut.\r
-   * \r
-   * @param vec\r
-   *        the single precision vector to be transformed\r
-   * @param vecOut\r
-   *        the vector into which the transformed values are placed\r
-   */\r
-  public void transform2(T4 vec, T4 vecOut) {\r
-    // alias-safe\r
-    vecOut.set4(m00 * vec.x + m01 * vec.y + m02 * vec.z + m03 * vec.w, m10\r
-        * vec.x + m11 * vec.y + m12 * vec.z + m13 * vec.w, m20 * vec.x + m21\r
-        * vec.y + m22 * vec.z + m23 * vec.w, m30 * vec.x + m31 * vec.y + m32\r
-        * vec.z + m33 * vec.w);\r
-  }\r
-\r
-  /**\r
-   * Transforms the point parameter with this Matrix4f and places the result\r
-   * back into point. The fourth element of the point input parameter is assumed\r
-   * to be one.\r
-   * \r
-   * @param point\r
-   *        the input point to be transformed.\r
-   */\r
-  public void rotTrans(T3 point) {\r
-    rotTrans2(point, point);\r
-  }\r
-\r
-  /**\r
-   * Transforms the point parameter with this Matrix4f and places the result\r
-   * into pointOut. The fourth element of the point input parameter is assumed to\r
-   * be one. point may be pointOut\r
-   * \r
-   * @param point\r
-   *        the input point to be transformed.\r
-   * @param pointOut\r
-   *        the transformed point\r
-   * @return pointOut\r
-   */\r
-  public T3 rotTrans2(T3 point, T3 pointOut) {\r
-      pointOut.set(\r
-          m00 * point.x + m01 * point.y + m02 * point.z + m03, \r
-          m10 * point.x + m11 * point.y + m12 * point.z + m13, \r
-          m20 * point.x + m21 * point.y + m22 * point.z + m23);\r
-      return pointOut;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to a rotation matrix about the w axis by the\r
-   * passed angle.\r
-   * \r
-   * @param angle\r
-   *        the angle to rotate about the W axis in radians\r
-   * @return this\r
-   */\r
-  public M4 setAsXYRotation(float angle) {\r
-    setIdentity();\r
-    double c = Math.cos(angle);\r
-    double s = Math.sin(angle);\r
-    m22 = (float) c;\r
-    m23 = (float) -s;\r
-    m32 = (float) s;\r
-    m33 = (float) c;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to a rotation matrix about the w axis by the\r
-   * passed angle.\r
-   * \r
-   * @param angle\r
-   *        the angle to rotate about the W axis in radians\r
-   * @return this\r
-   */\r
-  public M4 setAsYZRotation(float angle) {\r
-    setIdentity();\r
-    double c = Math.cos(angle);\r
-    double s = Math.sin(angle);\r
-    m00 = (float) c;\r
-    m03 = (float) -s;\r
-    m30 = (float) s;\r
-    m33 = (float) c;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Sets the value of this matrix to a rotation matrix about the w axis by the\r
-   * passed angle.\r
-   * \r
-   * @param angle\r
-   *        the angle to rotate about the W axis in radians\r
-   * @return this\r
-   */\r
-  public M4 setAsXZRotation(float angle) {\r
-    setIdentity();\r
-    double c = Math.cos(angle);\r
-    double s = Math.sin(angle);\r
-    m11 = (float) c;\r
-    m13 = (float) -s;\r
-    m31 = (float) s;\r
-    m33 = (float) c;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Returns true if the Object o is of type Matrix4f and all of the data\r
-   * members of t1 are equal to the corresponding data members in this Matrix4f.\r
-   * \r
-   * @param o\r
-   *        the object with which the comparison is made.\r
-   */\r
-  @Override\r
-  public boolean equals(Object o) {\r
-    if (!(o instanceof M4))\r
-      return false;\r
-    M4 m = (M4) o;\r
-    return (this.m00 == m.m00 && this.m01 == m.m01 && this.m02 == m.m02\r
-        && this.m03 == m.m03 && this.m10 == m.m10 && this.m11 == m.m11\r
-        && this.m12 == m.m12 && this.m13 == m.m13 && this.m20 == m.m20\r
-        && this.m21 == m.m21 && this.m22 == m.m22 && this.m23 == m.m23\r
-        && this.m30 == m.m30 && this.m31 == m.m31 && this.m32 == m.m32 && this.m33 == m.m33);\r
-  }\r
-\r
-  /**\r
-   * Returns a hash number based on the data values in this object. Two\r
-   * different Matrix4f objects with identical data values (ie, returns true for\r
-   * equals(Matrix4f) ) will return the same hash number. Two objects with\r
-   * different data members may return the same hash value, although this is not\r
-   * likely.\r
-   * \r
-   * @return the integer hash value\r
-   */\r
-  @Override\r
-  public int hashCode() {\r
-    return T3.floatToIntBits0(m00) ^ T3.floatToIntBits0(m01)\r
-        ^ T3.floatToIntBits0(m02) ^ T3.floatToIntBits0(m03)\r
-        ^ T3.floatToIntBits0(m10) ^ T3.floatToIntBits0(m11)\r
-        ^ T3.floatToIntBits0(m12) ^ T3.floatToIntBits0(m13)\r
-        ^ T3.floatToIntBits0(m20) ^ T3.floatToIntBits0(m21)\r
-        ^ T3.floatToIntBits0(m22) ^ T3.floatToIntBits0(m23)\r
-        ^ T3.floatToIntBits0(m30) ^ T3.floatToIntBits0(m31)\r
-        ^ T3.floatToIntBits0(m32) ^ T3.floatToIntBits0(m33);\r
-  }\r
-\r
-  /**\r
-   * Returns a string that contains the values of this Matrix4f.\r
-   * \r
-   * @return the String representation\r
-   */\r
-  @Override\r
-  public String toString() {\r
-    return "[\n  [" + m00 + "\t" + m01 + "\t" + m02 + "\t" + m03 + "]"\r
-        + "\n  [" + m10 + "\t" + m11 + "\t" + m12 + "\t" + m13 + "]" + "\n  ["\r
-        + m20 + "\t" + m21 + "\t" + m22 + "\t" + m23 + "]" + "\n  [" + m30\r
-        + "\t" + m31 + "\t" + m32 + "\t" + m33 + "] ]";\r
-  }\r
-  public M4 round(float f) {\r
-    m00 = rnd(m00, f);\r
-    m01 = rnd(m01, f);\r
-    m02 = rnd(m02, f);\r
-    m03 = rnd(m03, f);\r
-    m10 = rnd(m10, f);\r
-    m11 = rnd(m11, f);\r
-    m12 = rnd(m12, f);\r
-    m13 = rnd(m13, f);\r
-    m20 = rnd(m20, f);\r
-    m21 = rnd(m21, f);\r
-    m22 = rnd(m22, f);\r
-    m23 = rnd(m23, f);\r
-    m30 = rnd(m30, f);\r
-    m31 = rnd(m31, f);\r
-    m32 = rnd(m32, f);\r
-    m33 = rnd(m33, f);\r
-    return this;\r
-  }\r
-\r
-  private float rnd(float n, float f) {\r
-    return (Math.abs(n) < f ? 0 : n);\r
-  }\r
-}\r
+/*
+   Copyright (C) 1997,1998,1999
+   Kenji Hiranabe, Eiwa System Management, Inc.
+
+   This program is free software.
+   Implemented by Kenji Hiranabe(hiranabe@esm.co.jp),
+   conforming to the Java(TM) 3D API specification by Sun Microsystems.
+
+   Permission to use, copy, modify, distribute and sell this software
+   and its documentation for any purpose is hereby granted without fee,
+   provided that the above copyright notice appear in all copies and
+   that both that copyright notice and this permission notice appear
+   in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc.
+   makes no representations about the suitability of this software for any
+   purpose.  It is provided "AS IS" with NO WARRANTY.
+*/
+package javajs.util;
+
+/**
+ * A single precision floating point 4 by 4 matrix.
+ * 
+ * @author Kenji hiranabe
+ * 
+ *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
+ *         constructor and method names for the optimization of compiled
+ *         JavaScript using Java2Script
+ */
+public class M4 extends M34 {
+
+  /**
+   * The fourth element of the first row.
+   */
+  public float m03;
+
+  /**
+   * The fourth element of the second row.
+   */
+  public float m13;
+
+  /**
+   * The fourth element of the third row.
+   */
+  public float m23;
+
+  /**
+   * The first element of the fourth row.
+   */
+  public float m30;
+
+  /**
+   * The second element of the fourth row.
+   */
+  public float m31;
+
+  /**
+   * The third element of the fourth row.
+   */
+  public float m32;
+
+  /**
+   * The fourth element of the fourth row.
+   */
+  public float m33 = 0;
+
+  /**
+   * all zeros
+   * @j2sIgnore
+   */
+  public M4() {
+  }
+  /**
+   * Constructs and initializes a Matrix4f from the specified 16 element array.
+   * this.m00 =v[0], this.m01=v[1], etc.
+   * 
+   * @param v
+   *        the array of length 16 containing in order
+   * @return m
+   */
+  public static M4 newA16(float[] v) {
+    M4 m = new M4();
+    m.m00 = v[0];
+    m.m01 = v[1];
+    m.m02 = v[2];
+    m.m03 = v[3];
+
+    m.m10 = v[4];
+    m.m11 = v[5];
+    m.m12 = v[6];
+    m.m13 = v[7];
+
+    m.m20 = v[8];
+    m.m21 = v[9];
+    m.m22 = v[10];
+    m.m23 = v[11];
+
+    m.m30 = v[12];
+    m.m31 = v[13];
+    m.m32 = v[14];
+    m.m33 = v[15];
+
+    return m;
+  }
+
+  /**
+   * Constructs a new matrix with the same values as the Matrix4f parameter.
+   * 
+   * @param m1
+   *        the source matrix
+   * @return m
+   */
+  public static M4 newM4(M4 m1) {
+    M4 m = new M4();
+    if (m1 == null) {
+      m.setIdentity();
+      return m;
+    }
+    m.setToM3(m1);
+    m.m03 = m1.m03;
+    m.m13 = m1.m13;
+    m.m23 = m1.m23;
+    m.m30 = m1.m30;
+    m.m31 = m1.m31;
+    m.m32 = m1.m32;
+    m.m33 = m1.m33;
+    return m;
+  }
+
+  /**
+   * Constructs and initializes a Matrix4f from the rotation matrix and
+   * translation.
+   * 
+   * @param m1
+   *        The rotation matrix representing the rotational components
+   * @param t
+   *        The translational components of the matrix
+   * @return m
+   */
+  public static M4 newMV(M3 m1, T3 t) {
+    M4 m = new M4();
+    m.setMV(m1, t);
+    return m;
+  }
+
+  /**
+   * Sets this matrix to all zeros.
+   */
+  public void setZero() {
+    clear33();
+    m03 = m13 = m23 = m30 = m31 = m32 = m33 = 0.0f;
+  }
+
+  /**
+   * Sets this Matrix4f to identity.
+   */
+  public void setIdentity() {
+    setZero();
+    m00 = m11 = m22 = m33 = 1.0f;
+  }
+
+  /**
+   * Sets the value of this matrix to a copy of the passed matrix m1.
+   * 
+   * @param m1
+   *        the matrix to be copied
+   * @return this
+   */
+  public M4 setM4(M4 m1) {
+    setM33(m1);
+    m03 = m1.m03;
+    m13 = m1.m13;
+    m23 = m1.m23;
+    m30 = m1.m30;
+    m31 = m1.m31;
+    m32 = m1.m32;
+    m33 = m1.m33;
+    return this;
+  }
+
+  /**
+   * Initializes a Matrix4f from the rotation matrix and translation.
+   * 
+   * @param m1
+   *        The rotation matrix representing the rotational components
+   * @param t
+   *        The translational components of the matrix
+   */
+  public void setMV(M3 m1, T3 t) {
+    setM33(m1);
+    setTranslation(t);
+    m33 = 1;
+  }
+
+  /**
+   * Sets the rotational component (upper 3x3) of this matrix to the matrix
+   * values in the single precision Matrix3f argument; the other elements of
+   * this matrix are initialized as if this were an identity matrix (ie, affine
+   * matrix with no translational component).
+   * 
+   * @param m1
+   *        the 3x3 matrix
+   */
+  public void setToM3(M34 m1) {
+    setM33(m1);
+    m03 = m13 = m23 = m30 = m31 = m32 = 0.0f;
+    m33 = 1.0f;
+  }
+
+  /**
+   * Sets the rotational component (upper 3x3) of this matrix 
+   * to a rotation given by an axis angle
+   * 
+   * @param a
+   *        the axis and angle to be converted
+   */
+  public void setToAA(A4 a) {
+    setIdentity();
+    setAA33(a);
+  }
+
+  /**
+   * Sets the values in this Matrix4f equal to the row-major array parameter
+   * (ie, the first four elements of the array will be copied into the first row
+   * of this matrix, etc.).
+   * 
+   * @param m
+   */
+  public void setA(float m[]) {
+    m00 = m[0];
+    m01 = m[1];
+    m02 = m[2];
+    m03 = m[3];
+    m10 = m[4];
+    m11 = m[5];
+    m12 = m[6];
+    m13 = m[7];
+    m20 = m[8];
+    m21 = m[9];
+    m22 = m[10];
+    m23 = m[11];
+    m30 = m[12];
+    m31 = m[13];
+    m32 = m[14];
+    m33 = m[15];
+  }
+
+  /**
+   * Modifies the translational components of this matrix to the values of the
+   * Vector3f argument; the other values of this matrix are not modified.
+   * 
+   * @param trans
+   *        the translational component
+   */
+  public void setTranslation(T3 trans) {
+    m03 = trans.x;
+    m13 = trans.y;
+    m23 = trans.z;
+  }
+
+  /**
+   * Sets the specified element of this matrix4f to the value provided.
+   * 
+   * @param row
+   *        the row number to be modified (zero indexed)
+   * @param col
+   *        the column number to be modified (zero indexed)
+   * @param v
+   *        the new value
+   */
+  public void setElement(int row, int col, float v) {
+    if (row < 3 && col < 3) {
+      set33(row, col, v);
+      return;
+    }
+    if (row > 3 || col > 3)
+      err();
+    switch (row) {
+    case 0:
+      m03 = v;
+      return;
+    case 1:
+      m13 = v;
+      return;
+    case 2:
+      m23 = v;
+      return;
+    }
+    switch (col) {
+    case 0:
+      m30 = v;
+      return;
+    case 1:
+      m31 = v;
+      return;
+    case 2:
+      m32 = v;
+      return;
+    case 3:
+      m33 = v;
+      return;
+    }
+  }
+
+  /**
+   * Retrieves the value at the specified row and column of this matrix.
+   * 
+   * @param row
+   *        the row number to be retrieved (zero indexed)
+   * @param col
+   *        the column number to be retrieved (zero indexed)
+   * @return the value at the indexed element
+   */
+  public float getElement(int row, int col) {
+    if (row < 3 && col < 3)
+      return get33(row, col);
+    if (row > 3 || col > 3) {
+      err();
+      return 0;
+    }
+    switch (row) {
+    case 0:
+      return m03;
+    case 1:
+      return m13;
+    case 2:
+      return m23;
+    default:
+      switch (col) {
+      case 0:
+        return m30;
+      case 1:
+        return m31;
+      case 2:
+        return m32;
+      default:
+        return m33;
+      }
+    }
+  }
+
+  /**
+   * Retrieves the translational components of this matrix.
+   * 
+   * @param trans
+   *        the vector that will receive the translational component
+   */
+  public void getTranslation(T3 trans) {
+    trans.x = m03;
+    trans.y = m13;
+    trans.z = m23;
+  }
+
+  /**
+   * Gets the upper 3x3 values of this matrix and places them into the matrix
+   * m1.
+   * 
+   * @param m1
+   *        The matrix that will hold the values
+   */
+  public void getRotationScale(M3 m1) {
+    m1.m00 = m00;
+    m1.m01 = m01;
+    m1.m02 = m02;
+    m1.m10 = m10;
+    m1.m11 = m11;
+    m1.m12 = m12;
+    m1.m20 = m20;
+    m1.m21 = m21;
+    m1.m22 = m22;
+  }
+
+  /**
+   * Replaces the upper 3x3 matrix values of this matrix with the values in the
+   * matrix m1.
+   * 
+   * @param m1
+   *        The matrix that will be the new upper 3x3
+   */
+  public void setRotationScale(M3 m1) {
+    m00 = m1.m00;
+    m01 = m1.m01;
+    m02 = m1.m02;
+    m10 = m1.m10;
+    m11 = m1.m11;
+    m12 = m1.m12;
+    m20 = m1.m20;
+    m21 = m1.m21;
+    m22 = m1.m22;
+  }
+
+  /**
+   * Sets the specified row of this matrix4f to the four values provided.
+   * 
+   * @param row
+   *        the row number to be modified (zero indexed)
+   * @param v
+   *        the replacement row
+   */
+  public void setRowA(int row, float v[]) {
+    if (row < 3)
+      setRow33(row, v);
+    switch (row) {
+    case 0:
+      m03 = v[3];
+      return;
+    case 1:
+      m13 = v[3];
+      return;
+    case 2:
+      m23 = v[3];
+      return;
+    case 3:
+      m30 = v[0];
+      m31 = v[1];
+      m32 = v[2];
+      m33 = v[3];
+      return;
+    }
+    err();
+  }
+
+  /**
+   * Copies the matrix values in the specified row into the array parameter.
+   * 
+   * @param row
+   *        the matrix row
+   * @param v
+   *        The array into which the matrix row values will be copied
+   */
+  @Override
+  public void getRow(int row, float v[]) {
+    if (row < 3)
+      getRow33(row, v);
+    switch (row) {
+    case 0:
+      v[3] = m03;
+      return;
+    case 1:
+      v[3] = m13;
+      return;
+    case 2:
+      v[3] = m23;
+      return;
+    case 3:
+      v[0] = m30;
+      v[1] = m31;
+      v[2] = m32;
+      v[3] = m33;
+      return;
+    }
+    err();
+  }
+
+  /**
+   * Sets the specified column of this matrix4f to the four values provided.
+   * 
+   * @param column
+   *        the column number to be modified (zero indexed)
+   * @param x
+   *        the first row element
+   * @param y
+   *        the second row element
+   * @param z
+   *        the third row element
+   * @param w
+   *        the fourth row element
+   */
+  public void setColumn4(int column, float x, float y, float z, float w) {
+    if (column == 0) {
+      m00 = x;
+      m10 = y;
+      m20 = z;
+      m30 = w;
+    } else if (column == 1) {
+      m01 = x;
+      m11 = y;
+      m21 = z;
+      m31 = w;
+    } else if (column == 2) {
+      m02 = x;
+      m12 = y;
+      m22 = z;
+      m32 = w;
+    } else if (column == 3) {
+      m03 = x;
+      m13 = y;
+      m23 = z;
+      m33 = w;
+    } else {
+      err();
+    }
+  }
+
+  /**
+   * Sets the specified column of this matrix4f to the four values provided.
+   * 
+   * @param column
+   *        the column number to be modified (zero indexed)
+   * @param v
+   *        the replacement column
+   */
+  public void setColumnA(int column, float v[]) {
+    if (column < 3)
+      setColumn33(column, v);
+    switch (column) {
+    case 0:
+      m30 = v[3];
+      return;
+    case 1:
+      m31 = v[3];
+      return;
+    case 2:
+      m32 = v[3];
+      return;
+    case 3:
+      m03 = v[0];
+      m13 = v[1];
+      m23 = v[2];
+      m33 = v[3];
+      return;
+    default:
+      err();
+    }
+  }
+
+  /**
+   * Copies the matrix values in the specified column into the array parameter.
+   * 
+   * @param column
+   *        the matrix column
+   * @param v
+   *        The array into which the matrix column values will be copied
+   */
+  public void getColumn(int column, float v[]) {
+    if (column < 3)
+      getColumn33(column, v);
+    switch (column) {
+    case 0:
+      v[3] = m30;
+      return;
+    case 1:
+      v[3] = m31;
+      return;
+    case 2:
+      v[3] = m32;
+      return;
+    case 3:
+      v[0] = m03;
+      v[1] = m13;
+      v[2] = m23;
+      v[3] = m33;
+      return;
+    default:
+      err();
+    }
+  }
+
+  /**
+   * Sets the value of this matrix to the matrix difference of itself and matrix
+   * m1 (this = this - m1).
+   * 
+   * @param m1
+   *        the other matrix
+   */
+  public void sub(M4 m1) {
+    sub33(m1);
+    m03 -= m1.m03;
+    m13 -= m1.m13;
+    m23 -= m1.m23;
+    m30 -= m1.m30;
+    m31 -= m1.m31;
+    m32 -= m1.m32;
+    m33 -= m1.m33;
+  }
+
+  /**
+   * Sets the value of this matrix to its transpose.
+   */
+  public void transpose() {
+    transpose33();
+    float tmp = m03;
+    m03 = m30;
+    m30 = tmp;
+
+    tmp = m13;
+    m13 = m31;
+    m31 = tmp;
+
+    tmp = m23;
+    m23 = m32;
+    m32 = tmp;
+  }
+
+  /**
+   * Sets the value of this matrix to its inverse.
+   * @return this
+   */
+  public M4 invert() {
+    float s = determinant4();
+    if (s == 0.0)
+      return this;
+    s = 1 / s;
+    // alias-safe way.
+    // less *,+,- calculation than expanded expression.
+    set(m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13
+        * (m21 * m32 - m22 * m31), m21 * (m02 * m33 - m03 * m32) + m22
+        * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31), m31
+        * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33
+        * (m01 * m12 - m02 * m11), m01 * (m13 * m22 - m12 * m23) + m02
+        * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22),
+
+    m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10
+        * (m23 * m32 - m22 * m33), m22 * (m00 * m33 - m03 * m30) + m23
+        * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33), m32
+        * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30
+        * (m03 * m12 - m02 * m13), m02 * (m13 * m20 - m10 * m23) + m03
+        * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22),
+
+    m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11
+        * (m23 * m30 - m20 * m33), m23 * (m00 * m31 - m01 * m30) + m20
+        * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33), m33
+        * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31
+        * (m03 * m10 - m00 * m13), m03 * (m11 * m20 - m10 * m21) + m00
+        * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20),
+
+    m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12
+        * (m21 * m30 - m20 * m31), m20 * (m02 * m31 - m01 * m32) + m21
+        * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31), m30
+        * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32
+        * (m01 * m10 - m00 * m11), m00 * (m11 * m22 - m12 * m21) + m01
+        * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20));
+    scale(s);
+    return this;
+  }
+
+  /**
+   * Sets 16 values
+   * 
+   * @param m00
+   * @param m01
+   * @param m02
+   * @param m03
+   * @param m10
+   * @param m11
+   * @param m12
+   * @param m13
+   * @param m20
+   * @param m21
+   * @param m22
+   * @param m23
+   * @param m30
+   * @param m31
+   * @param m32
+   * @param m33
+   */
+  private void set(float m00, float m01, float m02, float m03, float m10,
+                   float m11, float m12, float m13, float m20, float m21,
+                   float m22, float m23, float m30, float m31, float m32,
+                   float m33) {
+    this.m00 = m00;
+    this.m01 = m01;
+    this.m02 = m02;
+    this.m03 = m03;
+    this.m10 = m10;
+    this.m11 = m11;
+    this.m12 = m12;
+    this.m13 = m13;
+    this.m20 = m20;
+    this.m21 = m21;
+    this.m22 = m22;
+    this.m23 = m23;
+    this.m30 = m30;
+    this.m31 = m31;
+    this.m32 = m32;
+    this.m33 = m33;
+  }
+  /**
+   * Computes the determinant of this matrix.
+   * 
+   * @return the determinant of the matrix
+   */
+  public float determinant4() {
+    // less *,+,- calculation than expanded expression.
+    return (m00 * m11 - m01 * m10) * (m22 * m33 - m23 * m32)
+        - (m00 * m12 - m02 * m10) * (m21 * m33 - m23 * m31)
+        + (m00 * m13 - m03 * m10) * (m21 * m32 - m22 * m31)
+        + (m01 * m12 - m02 * m11) * (m20 * m33 - m23 * m30)
+        - (m01 * m13 - m03 * m11) * (m20 * m32 - m22 * m30)
+        + (m02 * m13 - m03 * m12) * (m20 * m31 - m21 * m30);
+
+  }
+
+  /**
+   * Multiplies each element of this matrix by a scalar.
+   * 
+   * @param scalar
+   *        The scalar multiplier.
+   */
+  private void scale(float scalar) {
+    mul33(scalar);
+    m03 *= scalar;
+    m13 *= scalar;
+    m23 *= scalar;
+    m30 *= scalar;
+    m31 *= scalar;
+    m32 *= scalar;
+    m33 *= scalar;
+  }
+
+  /**
+   * Sets the value of this matrix to the result of multiplying itself with
+   * matrix m1.
+   * 
+   * @param m1
+   *        the other matrix
+   */
+  public void mul(M4 m1) {
+    mul2(this, m1);
+  }
+
+  /**
+   * Sets the value of this matrix to the result of multiplying the two argument
+   * matrices together.
+   * 
+   * @param m1
+   *        the first matrix
+   * @param m2
+   *        the second matrix
+   */
+  public void mul2(M4 m1, M4 m2) {
+    // alias-safe way.
+    set(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30,
+        m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31,
+        m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32,
+        m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33,
+
+        m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30,
+        m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31,
+        m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32,
+        m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33,
+
+        m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30,
+        m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31,
+        m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32,
+        m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33,
+
+        m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30,
+        m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31,
+        m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32,
+        m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33);
+  }
+
+  /**
+   * Transform the vector vec using this Matrix4f and place the result back into
+   * vec.
+   * 
+   * @param vec
+   *        the single precision vector to be transformed
+   */
+  public void transform(T4 vec) {
+    transform2(vec, vec);
+  }
+
+  /**
+   * Transform the vector vec using this Matrix4f and place the result into
+   * vecOut.
+   * 
+   * @param vec
+   *        the single precision vector to be transformed
+   * @param vecOut
+   *        the vector into which the transformed values are placed
+   */
+  public void transform2(T4 vec, T4 vecOut) {
+    // alias-safe
+    vecOut.set4(m00 * vec.x + m01 * vec.y + m02 * vec.z + m03 * vec.w, m10
+        * vec.x + m11 * vec.y + m12 * vec.z + m13 * vec.w, m20 * vec.x + m21
+        * vec.y + m22 * vec.z + m23 * vec.w, m30 * vec.x + m31 * vec.y + m32
+        * vec.z + m33 * vec.w);
+  }
+
+  /**
+   * Transforms the point parameter with this Matrix4f and places the result
+   * back into point. The fourth element of the point input parameter is assumed
+   * to be one.
+   * 
+   * @param point
+   *        the input point to be transformed.
+   */
+  public void rotTrans(T3 point) {
+    rotTrans2(point, point);
+  }
+
+  /**
+   * Transforms the point parameter with this Matrix4f and places the result
+   * into pointOut. The fourth element of the point input parameter is assumed to
+   * be one. point may be pointOut
+   * 
+   * @param point
+   *        the input point to be transformed.
+   * @param pointOut
+   *        the transformed point
+   * @return pointOut
+   */
+  public T3 rotTrans2(T3 point, T3 pointOut) {
+      pointOut.set(
+          m00 * point.x + m01 * point.y + m02 * point.z + m03, 
+          m10 * point.x + m11 * point.y + m12 * point.z + m13, 
+          m20 * point.x + m21 * point.y + m22 * point.z + m23);
+      return pointOut;
+  }
+
+  /**
+   * Sets the value of this matrix to a rotation matrix about the w axis by the
+   * passed angle.
+   * 
+   * @param angle
+   *        the angle to rotate about the W axis in radians
+   * @return this
+   */
+  public M4 setAsXYRotation(float angle) {
+    setIdentity();
+    double c = Math.cos(angle);
+    double s = Math.sin(angle);
+    m22 = (float) c;
+    m23 = (float) -s;
+    m32 = (float) s;
+    m33 = (float) c;
+    return this;
+  }
+
+  /**
+   * Sets the value of this matrix to a rotation matrix about the w axis by the
+   * passed angle.
+   * 
+   * @param angle
+   *        the angle to rotate about the W axis in radians
+   * @return this
+   */
+  public M4 setAsYZRotation(float angle) {
+    setIdentity();
+    double c = Math.cos(angle);
+    double s = Math.sin(angle);
+    m00 = (float) c;
+    m03 = (float) -s;
+    m30 = (float) s;
+    m33 = (float) c;
+    return this;
+  }
+
+  /**
+   * Sets the value of this matrix to a rotation matrix about the w axis by the
+   * passed angle.
+   * 
+   * @param angle
+   *        the angle to rotate about the W axis in radians
+   * @return this
+   */
+  public M4 setAsXZRotation(float angle) {
+    setIdentity();
+    double c = Math.cos(angle);
+    double s = Math.sin(angle);
+    m11 = (float) c;
+    m13 = (float) -s;
+    m31 = (float) s;
+    m33 = (float) c;
+    return this;
+  }
+
+  /**
+   * Returns true if the Object o is of type Matrix4f and all of the data
+   * members of t1 are equal to the corresponding data members in this Matrix4f.
+   * 
+   * @param o
+   *        the object with which the comparison is made.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof M4))
+      return false;
+    M4 m = (M4) o;
+    return (this.m00 == m.m00 && this.m01 == m.m01 && this.m02 == m.m02
+        && this.m03 == m.m03 && this.m10 == m.m10 && this.m11 == m.m11
+        && this.m12 == m.m12 && this.m13 == m.m13 && this.m20 == m.m20
+        && this.m21 == m.m21 && this.m22 == m.m22 && this.m23 == m.m23
+        && this.m30 == m.m30 && this.m31 == m.m31 && this.m32 == m.m32 && this.m33 == m.m33);
+  }
+
+  /**
+   * Returns a hash number based on the data values in this object. Two
+   * different Matrix4f objects with identical data values (ie, returns true for
+   * equals(Matrix4f) ) will return the same hash number. Two objects with
+   * different data members may return the same hash value, although this is not
+   * likely.
+   * 
+   * @return the integer hash value
+   */
+  @Override
+  public int hashCode() {
+    return T3.floatToIntBits0(m00) ^ T3.floatToIntBits0(m01)
+        ^ T3.floatToIntBits0(m02) ^ T3.floatToIntBits0(m03)
+        ^ T3.floatToIntBits0(m10) ^ T3.floatToIntBits0(m11)
+        ^ T3.floatToIntBits0(m12) ^ T3.floatToIntBits0(m13)
+        ^ T3.floatToIntBits0(m20) ^ T3.floatToIntBits0(m21)
+        ^ T3.floatToIntBits0(m22) ^ T3.floatToIntBits0(m23)
+        ^ T3.floatToIntBits0(m30) ^ T3.floatToIntBits0(m31)
+        ^ T3.floatToIntBits0(m32) ^ T3.floatToIntBits0(m33);
+  }
+
+  /**
+   * Returns a string that contains the values of this Matrix4f.
+   * 
+   * @return the String representation
+   */
+  @Override
+  public String toString() {
+    return "[\n  [" + m00 + "\t" + m01 + "\t" + m02 + "\t" + m03 + "]"
+        + "\n  [" + m10 + "\t" + m11 + "\t" + m12 + "\t" + m13 + "]" + "\n  ["
+        + m20 + "\t" + m21 + "\t" + m22 + "\t" + m23 + "]" + "\n  [" + m30
+        + "\t" + m31 + "\t" + m32 + "\t" + m33 + "] ]";
+  }
+  public M4 round(float f) {
+    m00 = rnd(m00, f);
+    m01 = rnd(m01, f);
+    m02 = rnd(m02, f);
+    m03 = rnd(m03, f);
+    m10 = rnd(m10, f);
+    m11 = rnd(m11, f);
+    m12 = rnd(m12, f);
+    m13 = rnd(m13, f);
+    m20 = rnd(m20, f);
+    m21 = rnd(m21, f);
+    m22 = rnd(m22, f);
+    m23 = rnd(m23, f);
+    m30 = rnd(m30, f);
+    m31 = rnd(m31, f);
+    m32 = rnd(m32, f);
+    m33 = rnd(m33, f);
+    return this;
+  }
+
+  private float rnd(float n, float f) {
+    return (Math.abs(n) < f ? 0 : n);
+  }
+}