/* * Matrix -- Collection of methods for working with 3D transformation matricies. * * Copyright (C) 2001 by Joseph A. Huwaldt . * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. **/ package jahuwaldt.gl; /** * A set of static utility methods for working with matricies. * In particular, these methods are geared for working efficiently * with OpenGL transformation matrices. * *

Modified by: Joseph A. Huwaldt

* * @author Joseph A. Huwaldt Date: January 13, 2001 * @version January 30, 2001 **/ public class Matrix { /** * The value for Math.PI as a float instead of a double. **/ public static final float PI = (float)Math.PI; /** * Convert's an angle in radians to one in degrees. * * @param rad The angle in radians to be converted. * @return The angle in degrees. **/ public static final float rad2Deg(float rad) { return rad*180/PI; } /** * Convert's an angle in degrees to one in radians. * * @param deg The angle in degrees to be converted. * @return The angle in radians. **/ public static final float deg2Rad(float deg) { return deg*PI/180; } /** * Set a 4x4 transformation matrix to the identity matrix. * Equiv. to: T = I * * I = 1 0 0 0 * 0 1 0 0 * 0 0 1 0 * 0 0 0 1 * * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setIdentity(float mtx[]) { mtx[0] = mtx[5] = mtx[10] = mtx[15] = 1; mtx[1] = mtx[2] = mtx[3] = mtx[4] = 0; mtx[6] = mtx[7] = mtx[8] = mtx[9] = 0; mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0; return mtx; } /** * Create a new 4x4 transformation matrix set to the identity matrix. * Equiv. to: T = I * * I = 1 0 0 0 * 0 1 0 0 * 0 0 1 0 * 0 0 0 1 * * @return A reference to a 4x4 identity matrix is returned. **/ public static final float[] identity() { float[] mtx = new float[16]; mtx[0] = mtx[5] = mtx[10] = mtx[15] = 1; return mtx; } /** * Set a 4x4 transformation matrix which rotates about the X-axis. * Equiv. to: T = Rx * * Rx = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the X-axis in radians. * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setRotateX(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); mtx[0] = 1.0f; mtx[1] = 0.0f; mtx[2] = 0.0f; mtx[3] = 0.0f; mtx[4] = 0.0f; mtx[5] = rcos; mtx[6] = rsin; mtx[7] = 0.0f; mtx[8] = 0.0f; mtx[9] = -rsin; mtx[10] = rcos; mtx[11] = 0.0f; mtx[12] = 0.0f; mtx[13] = 0.0f; mtx[14] = 0.0f; mtx[15] = 1.0f; return mtx; } /** * Set a 4x4 transformation matrix which rotates about the Y-axis. * Equiv. to: T = Ry * * Ry = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the Y-axis in radians. * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setRotateY(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); mtx[0] = rcos; mtx[1] = 0.0f; mtx[2] = -rsin; mtx[3] = 0.0f; mtx[4] = 0.0f; mtx[5] = 1.0f; mtx[6] = 0.0f; mtx[7] = 0.0f; mtx[8] = rsin; mtx[9] = 0.0f; mtx[10] = rcos; mtx[11] = 0.0f; mtx[12] = 0.0f; mtx[13] = 0.0f; mtx[14] = 0.0f; mtx[15] = 1.0f; return mtx; } /** * Set a 4x4 transformation matrix which rotates about the Z-axis. * Equiv. to: T = Rz * * Rz = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the Z-axis in radians. * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setRotateZ(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); mtx[0] = rcos; mtx[1] = rsin; mtx[2] = 0.0f; mtx[3] = 0.0f; mtx[4] = -rsin; mtx[5] = rcos; mtx[6] = 0.0f; mtx[7] = 0.0f; mtx[8] = 0.0f; mtx[9] = 0.0f; mtx[10] = 1.0f; mtx[11] = 0.0f; mtx[12] = 0.0f; mtx[13] = 0.0f; mtx[14] = 0.0f; mtx[15] = 1.0f; return mtx; } /** * Set a 4x4 transformation matrix which scales in each * axis direction by the specified scale factors. * Equiv. to: T = S * * S = sx 0 0 0 * 0 sy 0 0 * 0 0 sz 0 * 0 0 0 1 * * @param sx The scale factor in the X-axis direction. * @param sy The scale factor in the Y-axis direction. * @param sz The scale factor in the Z-axis direction. * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setScale(float sx, float sy, float sz, float mtx[]) { mtx[0] = sx; mtx[5] = sy; mtx[10] = sz; mtx[15] = 1; mtx[1] = mtx[2] = mtx[3] = mtx[4] = 0; mtx[6] = mtx[7] = mtx[8] = mtx[9] = 0; mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0; return mtx; } /** * Set a 4x4 transformation matrix which translates in each * axis direction by the specified amounts. * Equiv. to: T = Tr * * Tr = 1 0 0 tx * 0 1 0 ty * 0 0 1 tz * 0 0 0 1 * * @param tx The translation amount in the X-axis direction. * @param ty The translation amount in the Y-axis direction. * @param tz The translation amount in the Z-axis direction. * @param mtx The 4x4 matrix to be set. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] setTranslate(float tx, float ty, float tz, float mtx[]) { mtx[0] = 1; mtx[1] = mtx[2] = 0; mtx[3] = tx; mtx[4] = 0; mtx[5] = 1; mtx[6] = 0; mtx[7] = ty; mtx[8] = mtx[9] = 0; mtx[10] = 1; mtx[11] = tz; mtx[12] = mtx[13] = mtx[14] = 0; mtx[15] = 1; return mtx; } /** * Multiplies two 4x4 matricies together, and returns the * result in a new output matrix. The multiplication is done * fast, at the expense of code. * * @param mtx1 The 1st matrix being multiplied. * @param mtx2 The 2nd matrix being multiplied. * @return The output matrix containing the input matrices multiplied. **/ public static final float[] multiply(float mtx1[], float mtx2[]) { float nmtx[] = new float[16]; float m0 = mtx1[0], m1 = mtx1[1], m2 = mtx1[2], m3 = mtx1[3]; nmtx[0] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; nmtx[1] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; nmtx[2] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; nmtx[3] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[4]; m1 = mtx1[5]; m2 = mtx1[6]; m3 = mtx1[7]; nmtx[4] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; nmtx[5] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; nmtx[6] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; nmtx[7] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[8]; m1 = mtx1[9]; m2 = mtx1[10]; m3 = mtx1[11]; nmtx[8] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; nmtx[9] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; nmtx[10] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; nmtx[11] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[12]; m1 = mtx1[13]; m2 = mtx1[14]; m3 = mtx1[15]; nmtx[12] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; nmtx[13] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; nmtx[14] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; nmtx[15] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; return nmtx; } /** * Multiplies two 4x4 matricies together, and places them * in the specified output matrix. The multiplication is done * fast, at the expense of code. The output matrix may not * be the same as one of the input matrices or the results * are undefined. * * @param mtx1 The 1st matrix being multiplied. * @param mtx2 The 2nd matrix being multiplied. * @param dest The output matrix (results go here). Must not be * one of the input matrices. * @return A reference to the output matrix "dest" is returned. **/ public static final float[] multiply(float mtx1[], float mtx2[], float dest[]) { float m0 = mtx1[0], m1 = mtx1[1], m2 = mtx1[2], m3 = mtx1[3]; dest[0] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; dest[1] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; dest[2] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; dest[3] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[4]; m1 = mtx1[5]; m2 = mtx1[6]; m3 = mtx1[7]; dest[4] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; dest[5] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; dest[6] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; dest[7] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[8]; m1 = mtx1[9]; m2 = mtx1[10]; m3 = mtx1[11]; dest[8] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; dest[9] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; dest[10] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; dest[11] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; m0 = mtx1[12]; m1 = mtx1[13]; m2 = mtx1[14]; m3 = mtx1[15]; dest[12] = m0*mtx2[0] + m1*mtx2[4] + m2*mtx2[8] + m3*mtx2[12]; dest[13] = m0*mtx2[1] + m1*mtx2[5] + m2*mtx2[9] + m3*mtx2[13]; dest[14] = m0*mtx2[2] + m1*mtx2[6] + m2*mtx2[10] + m3*mtx2[14]; dest[15] = m0*mtx2[3] + m1*mtx2[7] + m2*mtx2[11] + m3*mtx2[15]; return dest; } /**************************************************************** * The following are matrix post concatenation routines that * * can be used as speedy replacements for the more standard * * matrix mult. routine to generate combined rotations. * ****************************************************************/ /** * Multiply an existing 4x4 transformation matrix by an X-axis * rotation matrix quickly. This is much faster than calling * setRotateX() followed by multiply(). * Equiv. to: T = T*Rx * * Rx = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the X-axis in radians. * @param mtx The 4x4 matrix to be multiplied by the rotation matrix. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] rotateX(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); for (int i = 0 ; i < 4 ; i++) { int i1 = i*4 + 1; int i2 = i1 + 1; float t = mtx[i1]; mtx[i1] = t*rcos - mtx[i2]*rsin; mtx[i2] = t*rsin + mtx[i2]*rcos; } return mtx; } /** * Multiply an existing 4x4 transformation matrix by a Y-axis * rotation matrix quickly. This is much faster than calling * setRotateY() followed by multiply(). * Equiv. to: T = T*Ry * * Ry = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the Y-axis in radians. * @param mtx The 4x4 matrix to be multiplied by the rotation matrix. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] rotateY(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); for (int i = 0 ; i < 4 ; i++) { int i0 = i*4; int i2 = i0 + 2; float t = mtx[i0]; mtx[i0] = t*rcos + mtx[i2]*rsin; mtx[i2] = mtx[i2]*rcos - t*rsin; } return mtx; } /** * Multiply an existing 4x4 transformation matrix by a Z-axis * rotation matrix quickly. This is much faster than calling * setRotateZ() followed by multiply(). * Equiv. to: T = T*Rz * * Rz = 1 0 0 0 * 0 cos(a) sin(a) 0 * 0 -sin(a) cos(a) 0 * 0 0 0 1 * * @param angle The rotation angle about the Y-axis in radians. * @param mtx The 4x4 matrix to be multiplied by the rotation matrix. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] rotateZ(float angle, float mtx[]) { float rsin = (float)Math.sin(angle); float rcos = (float)Math.cos(angle); for (int i = 0 ; i < 4 ; i++) { int i0 = i*4; int i1 = i0 + 1; float t = mtx[i0]; mtx[i0] = t*rcos - mtx[i1]*rsin; mtx[i1] = t*rsin + mtx[i1]*rcos; } return mtx; } /** * Multiply an existing 4x4 transformation matrix by a set of * scale factors quickly. This is much faster than calling * setScale() followed by multiply(). * Equiv. to: T = T*S * * S = sx 0 0 0 * 0 sy 0 0 * 0 0 sz 0 * 0 0 0 1 * * @param sx The scale factor in the X-axis direction. * @param sy The scale factor in the Y-axis direction. * @param sz The scale factor in the Z-axis direction. * @param mtx The 4x4 matrix to be multiplied by the scale factor matrix. * @param A reference to the output matrix "mtx" is returned. **/ public static final float[] scale(float sx, float sy, float sz, float mtx[]) { for (int i = 0 ; i < 4 ; i++) { int i0 = i*4; mtx[i0] *= sx; mtx[i0 + 1] *= sy; mtx[i0 + 2] *= sz; } return mtx; } /** * Multiply an existing 4x4 transformation matrix by a * translation matrix quickly. This is much faster than calling * setTranslate() followed by multiply(). * Equiv. to: T = T*Tr * * Tr = 1 0 0 Tx * 0 1 0 Ty * 0 0 1 Tz * 0 0 0 1 * * @param tx The translation amount in the X-axis direction. * @param ty The translation amount in the Y-axis direction. * @param tz The translation amount in the Z-axis direction. * @param mtx The 4x4 matrix to be multiplied by the translation matrix. * @return A reference to the output matrix "mtx" is returned. **/ public static final float[] translate(float tx, float ty, float tz, float mtx[]) { for (int i=0 ; i < 4 ; i++) { int i0 = i*4; int i3 = i0 + 3; mtx[i0] += mtx[i3]*tx; mtx[i0 + 1] += mtx[i3]*ty; mtx[i0 + 2] += mtx[i3]*tz; } return mtx; } }