// 3D Engine // // Matrix 4x4. // // Author Matthew Caryl // Created 4.5.97 // // The scaling transform of factor S is refered to as S() // The x rotation transform of angle X is refered to as X() // The y rotation transform of angle Y is refered to as Y() // The z rotation transform of angle Z is refered to as Z() // The translation transform by (X, Y, Z) is refered to as T() // // Although under copywrite to the author (Matthew Caryl) this code can be copied and modified for non-commercial // purposes as long as any derivatives contain this condition. package ADT; public class Matrix { // // Public interface // // M = I public Matrix() { setScale(1f); } // M = N public Matrix(Matrix n) { set(n); } // M = N public void set(Matrix n) { m00 = n.m00; m01 = n.m01; m02 = n.m02; m03 = n.m03; m10 = n.m10; m11 = n.m11; m12 = n.m12; m13 = n.m13; m20 = n.m20; m21 = n.m21; m22 = n.m22; m23 = n.m23; m30 = n.m30; m31 = n.m31; m32 = n.m32; m33 = n.m33; } // M = S() public void setScale(float S) { m00 = S; m01 = 0f; m02 = 0f; m03 = 0f; m10 = 0f; m11 = S; m12 = 0f; m13 = 0f; m20 = 0f; m21 = 0f; m22 = S; m23 = 0f; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = S(), assuming previously a scale matrix public void resetScale(float S) { m00 = S; m11 = S; m22 = S; } // M = S() * M public void scaleBy(float S) { m00 *= S; m01 *= S; m02 *= S; m03 *= S; m10 *= S; m11 *= S; m12 *= S; m13 *= S; m20 *= S; m21 *= S; m22 *= S; m23 *= S; } // M = X() public void setRotateX(float X) { float sin = (float) Math.sin(X), cos = (float) Math.cos(X); m00 = 1f; m01 = 0f; m02 = 0f; m03 = 0f; m10 = 0f; m11 = cos; m12 = sin; m13 = 0f; m20 = 0f; m21 = -sin; m22 = cos; m23 = 0f; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = X(), assuming previously a x rotation matrix public void resetRotateX(float X) { float sin = (float) Math.sin(X), cos = (float) Math.cos(X); m11 = cos; m12 = sin; m21 = -sin; m22 = cos; } // M = X() * M public void rotateByX(float X) { float sin = (float) Math.sin(X), cos = (float) Math.cos(X); float om10 = m10, om11 = m11, om12 = m12, om13 = m13; m10 = cos * m10 + sin * m20; m11 = cos * m11 + sin * m21; m12 = cos * m12 + sin * m22; m13 = cos * m13 + sin * m23; m20 = -sin * om10 + cos * m20; m21 = -sin * om11 + cos * m21; m22 = -sin * om12 + cos * m22; m23 = -sin * om13 + cos * m23; } // M = Y() public void setRotateY(float Y) { float sin = (float) Math.sin(Y), cos = (float) Math.cos(Y); m00 = cos; m01 = 0f; m02 = -sin; m03 = 0f; m10 = 0f; m11 = 1f; m12 = 0f; m13 = 0f; m20 = sin; m21 = 0f; m22 = cos; m23 = 0f; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = Y(), assuming previously a y rotation matrix public void resetRotateY(float Y) { float sin = (float) Math.sin(Y), cos = (float) Math.cos(Y); m00 = cos; m02 = -sin; m20 = sin; m22 = cos; } // M = Y() * M public void rotateByY(float Y) { float sin = (float) Math.sin(Y); float cos = (float) Math.cos(Y); float om00 = m00, om01 = m01, om02 = m02, om03 = m03; m00 = cos * m00 - sin * m20; m01 = cos * m01 - sin * m21; m02 = cos * m02 - sin * m22; m03 = cos * m03 - sin * m23; m20 = sin * om00 + cos * m20; m21 = sin * om01 + cos * m21; m22 = sin * om02 + cos * m22; m23 = sin * om03 + cos * m23; } // M = Z() public void setRotateZ(float Z) { float sin = (float) Math.sin(Z), cos = (float) Math.cos(Z); m00 = cos; m01 = sin; m02 = 0f; m03 = 0f; m10 = -sin; m11 = cos; m12 = 0f; m13 = 0f; m20 = 0f; m21 = 0f; m22 = 1f; m23 = 0f; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = Z(), assuming previously a z rotation matrix public void resetRotateZ(float Z) { float sin = (float) Math.sin(Z), cos = (float) Math.cos(Z); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } // M = Z() * M public void rotateByZ(float Z) { float sin = (float) Math.sin(Z), cos = (float) Math.cos(Z); float om00 = m00, om01 = m01, om02 = m02, om03 = m03; m00 = cos * m00 + sin * m10; m01 = cos * m01 + sin * m11; m02 = cos * m02 + sin * m12; m03 = cos * m03 + sin * m13; m10 = -sin * om00 + cos * m10; m11 = -sin * om01 + cos * m11; m12 = -sin * om02 + cos * m12; m13 = -sin * om03 + cos * m13; } // M = X() * Y() * Z() public void setRotate(float X, float Y, float Z) { setRotateZ(Z); rotateByY(Y); rotateByX(X); } // M = X() * Y() * Z(), assuming previously a rotation matrix public void resetRotate(float X, float Y, float Z) { setRotateZ(Z); rotateByY(Y); rotateByX(X); } // M = X() * Y() * Z() * M public void rotateBy(float X, float Y, float Z) { rotateByZ(Z); rotateByY(Y); rotateByX(X); } // M = T() public void setTranslate(float X, float Y, float Z) { m00 = 1f; m01 = 0f; m02 = 0f; m03 = X; m10 = 0f; m11 = 1f; m12 = 0f; m13 = Y; m20 = 0f; m21 = 0f; m22 = 1f; m23 = Z; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = T(), assuming previously a translation matrix public void resetTranslate(float X, float Y, float Z) { m03 = X; m13 = Y; m23 = Z; } // M = T() * M public void translateBy(float X, float Y, float Z) { m00 += m30 * X; m01 += m31 * X; m02 += m32 * X; m03 += m33 * X; m10 += m30 * Y; m11 += m31 * Y; m12 += m32 * Y; m13 += m33 * Y; m20 += m30 * Z; m21 += m31 * Z; m22 += m32 * Z; m23 += m33 * Z; } // M = parallel projection transform public void setParallel() { m00 = 1f; m01 = 0f; m02 = 0f; m03 = 0f; m10 = 0f; m11 = 1f; m12 = 0f; m13 = 0f; m20 = 0f; m21 = 0f; m22 = 1f; m23 = 0f; m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f; } // M = perspective projection transform public void setPerspective(float Zf) { m00 = 1f; m01 = 0f; m02 = 0f; m03 = 0f; m10 = 0f; m11 = 1f; m12 = 0f; m13 = 0f; m20 = 0f; m21 = 0f; m22 = 1f; m23 = 0f; m30 = 0f; m31 = 0f; m32 = -1f / Zf; m33 = 1f; } // M = M * N public void multiply(Matrix n) { float om00 = m00, om01 = m01, om02 = m02, om03 = m03; float om10 = m10, om11 = m11, om12 = m12, om13 = m13; float om20 = m20, om21 = m21, om22 = m22, om23 = m23; float om30 = m30, om31 = m31, om32 = m32, om33 = m33; m00 = om00 * n.m00 + om01 * n.m10 + om02 * n.m20 + om03 * n.m30; m01 = om00 * n.m01 + om01 * n.m11 + om02 * n.m21 + om03 * n.m31; m02 = om00 * n.m02 + om01 * n.m12 + om02 * n.m22 + om03 * n.m32; m03 = om00 * n.m03 + om01 * n.m13 + om02 * n.m23 + om03 * n.m33; m10 = om10 * n.m00 + om11 * n.m10 + om12 * n.m20 + om13 * n.m30; m11 = om10 * n.m01 + om11 * n.m11 + om12 * n.m21 + om13 * n.m31; m12 = om10 * n.m02 + om11 * n.m12 + om12 * n.m22 + om13 * n.m32; m13 = om10 * n.m03 + om11 * n.m13 + om12 * n.m23 + om13 * n.m33; m20 = om20 * n.m00 + om21 * n.m10 + om22 * n.m20 + om23 * n.m30; m21 = om20 * n.m01 + om21 * n.m11 + om22 * n.m21 + om23 * n.m31; m22 = om20 * n.m02 + om21 * n.m12 + om22 * n.m22 + om23 * n.m32; m23 = om20 * n.m03 + om21 * n.m13 + om22 * n.m23 + om23 * n.m33; m30 = om30 * n.m00 + om31 * n.m10 + om32 * n.m20 + om33 * n.m30; m31 = om30 * n.m01 + om31 * n.m11 + om32 * n.m21 + om33 * n.m31; m32 = om30 * n.m02 + om31 * n.m12 + om32 * n.m22 + om33 * n.m32; m33 = om30 * n.m03 + om31 * n.m13 + om32 * n.m23 + om33 * n.m33; } // D = M * S public void transform(Vector s, Vector d) { d.x = m00 * s.x + m01 * s.y + m02 * s.z + m03 * s.w; d.y = m10 * s.x + m11 * s.y + m12 * s.z + m13 * s.w; d.z = m20 * s.x + m21 * s.y + m22 * s.z + m23 * s.w; d.w = m30 * s.x + m31 * s.y + m32 * s.z + m33 * s.w; } // D[] = M * S[] public void transform(Vector[] s, Vector[] d) { for (int i = s.length - 1; i >= 0; i--) { d[i].x = m00 * s[i].x + m01 * s[i].y + m02 * s[i].z + m03 * s[i].w; d[i].y = m10 * s[i].x + m11 * s[i].y + m12 * s[i].z + m13 * s[i].w; d[i].z = m20 * s[i].x + m21 * s[i].y + m22 * s[i].z + m23 * s[i].w; d[i].w = m30 * s[i].x + m31 * s[i].y + m32 * s[i].z + m33 * s[i].w; } } // // Private interface // private float m00, m01, m02, m03; private float m10, m11, m12, m13; private float m20, m21, m22, m23; private float m30, m31, m32, m33; }