FileDocCategorySizeDatePackage
Matrix.javaAPI DocAndroid 1.5 API21889Wed May 06 22:42:00 BST 2009android.opengl

Matrix

public class Matrix extends Object
Matrix math utilities. These methods operate on OpenGL ES format matrices and vectors stored in float arrays. Matrices are 4 x 4 column-vector matrices stored in column-major order:
m[offset + 0] m[offset + 4] m[offset + 8] m[offset + 12]
m[offset + 1] m[offset + 5] m[offset + 9] m[offset + 13]
m[offset + 2] m[offset + 6] m[offset + 10] m[offset + 14]
m[offset + 3] m[offset + 7] m[offset + 11] m[offset + 15]
Vectors are 4 row x 1 column column-vectors stored in order:
v[offset + 0]
v[offset + 1]
v[offset + 2]
v[offset + 3]

Fields Summary
Constructors Summary
Methods Summary
public static voidfrustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far)
Define a projection matrix in terms of six clip planes

param
m the float array that holds the perspective matrix
param
offset the offset into float array m where the perspective matrix data is written
param
left
param
right
param
bottom
param
top
param
near
param
far

        if (left == right) {
            throw new IllegalArgumentException("left == right");
        }
        if (top == bottom) {
            throw new IllegalArgumentException("top == bottom");
        }
        if (near == far) {
            throw new IllegalArgumentException("near == far");
        }
        if (near <= 0.0f) {
            throw new IllegalArgumentException("near <= 0.0f");
        }
        if (far <= 0.0f) {
            throw new IllegalArgumentException("far <= 0.0f");
        }
        final float r_width  = 1.0f / (right - left);
        final float r_height = 1.0f / (top - bottom);
        final float r_depth  = 1.0f / (near - far);
        final float x = 2.0f * (near * r_width);
        final float y = 2.0f * (near * r_height);
        final float A = 2.0f * ((right + left) * r_width);
        final float B = (top + bottom) * r_height;
        final float C = (far + near) * r_depth;
        final float D = 2.0f * (far * near * r_depth);
        m[offset + 0] = x;
        m[offset + 5] = y;
        m[offset + 8] = A;
        m[offset +  9] = B;
        m[offset + 10] = C;
        m[offset + 14] = D;
        m[offset + 11] = -1.0f;
        m[offset +  1] = 0.0f;
        m[offset +  2] = 0.0f;
        m[offset +  3] = 0.0f;
        m[offset +  4] = 0.0f;
        m[offset +  6] = 0.0f;
        m[offset +  7] = 0.0f;
        m[offset + 12] = 0.0f;
        m[offset + 13] = 0.0f;
        m[offset + 15] = 0.0f;
    
public static booleaninvertM(float[] mInv, int mInvOffset, float[] m, int mOffset)
Inverts a 4 x 4 matrix.

param
mInv the array that holds the output inverted matrix
param
mInvOffset an offset into mInv where the inverted matrix is stored.
param
m the input array
param
mOffset an offset into m where the matrix is stored.
return
true if the matrix could be inverted, false if it could not.

        // Invert a 4 x 4 matrix using Cramer's Rule

        // array of transpose source matrix
        float[] src = new float[16];

        // transpose matrix
        transposeM(src, 0, m, mOffset);

        // temp array for pairs
        float[] tmp = new float[12];

        // calculate pairs for first 8 elements (cofactors)
        tmp[0] = src[10] * src[15];
        tmp[1] = src[11] * src[14];
        tmp[2] = src[9] * src[15];
        tmp[3] = src[11] * src[13];
        tmp[4] = src[9] * src[14];
        tmp[5] = src[10] * src[13];
        tmp[6] = src[8] * src[15];
        tmp[7] = src[11] * src[12];
        tmp[8] = src[8] * src[14];
        tmp[9] = src[10] * src[12];
        tmp[10] = src[8] * src[13];
        tmp[11] = src[9] * src[12];

        // Holds the destination matrix while we're building it up.
        float[] dst = new float[16];

        // calculate first 8 elements (cofactors)
        dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
        dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
        dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
        dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
        dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
        dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
        dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
        dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
        dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
        dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
        dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
        dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
        dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
        dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
        dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
        dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];

        // calculate pairs for second 8 elements (cofactors)
        tmp[0] = src[2] * src[7];
        tmp[1] = src[3] * src[6];
        tmp[2] = src[1] * src[7];
        tmp[3] = src[3] * src[5];
        tmp[4] = src[1] * src[6];
        tmp[5] = src[2] * src[5];
        tmp[6] = src[0] * src[7];
        tmp[7] = src[3] * src[4];
        tmp[8] = src[0] * src[6];
        tmp[9] = src[2] * src[4];
        tmp[10] = src[0] * src[5];
        tmp[11] = src[1] * src[4];

        // calculate second 8 elements (cofactors)
        dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
        dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
        dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
        dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
        dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
        dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
        dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
        dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
        dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
        dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
        dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
        dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
        dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
        dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
        dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
        dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];

        // calculate determinant
        float det =
                src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3]
                        * dst[3];

        if (det == 0.0f) {

        }

        // calculate matrix inverse
        det = 1 / det;
        for (int j = 0; j < 16; j++)
            mInv[j + mInvOffset] = dst[j] * det;

        return true;
    
public static floatlength(float x, float y, float z)
Computes the length of a vector

param
x x coordinate of a vector
param
y y coordinate of a vector
param
z z coordinate of a vector
return
the length of a vector

        return (float) Math.sqrt(x * x + y * y + z * z);
    
public static native voidmultiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset)
Multiply two 4x4 matrices together and store the result in a third 4x4 matrix. In matrix notation: result = lhs x rhs. Due to the way matrix multiplication works, the result matrix will have the same effect as first multiplying by the rhs matrix, then multiplying by the lhs matrix. This is the opposite of what you might expect. The same float array may be passed for result, lhs, and/or rhs. However, the result element values are undefined if the result elements overlap either the lhs or rhs elements.

param
result The float array that holds the result.
param
resultOffset The offset into the result array where the result is stored.
param
lhs The float array that holds the left-hand-side matrix.
param
lhsOffset The offset into the lhs array where the lhs is stored
param
rhs The float array that holds the right-hand-side matrix.
param
rhsOffset The offset into the rhs array where the rhs is stored.
throws
IllegalArgumentException if result, lhs, or rhs are null, or if resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or rhsOffset + 16 > rhs.length.

public static native voidmultiplyMV(float[] resultVec, int resultVecOffset, float[] lhsMat, int lhsMatOffset, float[] rhsVec, int rhsVecOffset)
Multiply a 4 element vector by a 4x4 matrix and store the result in a 4 element column vector. In matrix notation: result = lhs x rhs The same float array may be passed for resultVec, lhsMat, and/or rhsVec. However, the resultVec element values are undefined if the resultVec elements overlap either the lhsMat or rhsVec elements.

param
resultVec The float array that holds the result vector.
param
resultVecOffset The offset into the result array where the result vector is stored.
param
lhsMat The float array that holds the left-hand-side matrix.
param
lhsMatOffset The offset into the lhs array where the lhs is stored
param
rhsVec The float array that holds the right-hand-side vector.
param
rhsVecOffset The offset into the rhs vector where the rhs vector is stored.
throws
IllegalArgumentException if resultVec, lhsMat, or rhsVec are null, or if resultVecOffset + 4 > resultVec.length or lhsMatOffset + 16 > lhsMat.length or rhsVecOffset + 4 > rhsVec.length.

public static voidorthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
Computes an orthographic projection matrix.

param
m returns the result
param
mOffset
param
left
param
right
param
bottom
param
top
param
near
param
far

        if (left == right) {
            throw new IllegalArgumentException("left == right");
        }
        if (bottom == top) {
            throw new IllegalArgumentException("bottom == top");
        }
        if (near == far) {
            throw new IllegalArgumentException("near == far");
        }

        final float r_width  = 1.0f / (right - left);
        final float r_height = 1.0f / (top - bottom);
        final float r_depth  = 1.0f / (far - near);
        final float x =  2.0f * (r_width);
        final float y =  2.0f * (r_height);
        final float z = -2.0f * (r_depth);
        final float tx = -(right + left) * r_width;
        final float ty = -(top + bottom) * r_height;
        final float tz = -(far + near) * r_depth;
        m[mOffset + 0] = x;
        m[mOffset + 5] = y;
        m[mOffset +10] = z;
        m[mOffset +12] = tx;
        m[mOffset +13] = ty;
        m[mOffset +14] = tz;
        m[mOffset +15] = 1.0f;
        m[mOffset + 1] = 0.0f;
        m[mOffset + 2] = 0.0f;
        m[mOffset + 3] = 0.0f;
        m[mOffset + 4] = 0.0f;
        m[mOffset + 6] = 0.0f;
        m[mOffset + 7] = 0.0f;
        m[mOffset + 8] = 0.0f;
        m[mOffset + 9] = 0.0f;
        m[mOffset + 11] = 0.0f;
    
public static voidrotateM(float[] rm, int rmOffset, float[] m, int mOffset, float a, float x, float y, float z)
Rotates matrix m by angle a (in degrees) around the axis (x, y, z)

param
rm returns the result
param
rmOffset index into rm where the result matrix starts
param
m source matrix
param
mOffset index into m where the source matrix starts
param
a angle to rotate in degrees
param
x scale factor x
param
y scale factor y
param
z scale factor z

        float[] r = new float[16];
        setRotateM(r, 0, a, x, y, z);
        multiplyMM(rm, rmOffset, m, mOffset, r, 0);
    
public static voidrotateM(float[] m, int mOffset, float a, float x, float y, float z)
Rotates matrix m in place by angle a (in degrees) around the axis (x, y, z)

param
m source matrix
param
mOffset index into m where the matrix starts
param
a angle to rotate in degrees
param
x scale factor x
param
y scale factor y
param
z scale factor z

        float[] temp = new float[32];
        setRotateM(temp, 0, a, x, y, z);
        multiplyMM(temp, 16, m, mOffset, temp, 0);
        System.arraycopy(temp, 16, m, mOffset, 16);
    
public static voidscaleM(float[] m, int mOffset, float x, float y, float z)
Scales matrix m in place by sx, sy, and sz

param
m matrix to scale
param
mOffset index into m where the matrix starts
param
x scale factor x
param
y scale factor y
param
z scale factor z

        for (int i=0 ; i<4 ; i++) {
            int mi = mOffset + i;
            m[     mi] *= x;
            m[ 4 + mi] *= y;
            m[ 8 + mi] *= z;
        }
    
public static voidscaleM(float[] sm, int smOffset, float[] m, int mOffset, float x, float y, float z)
Scales matrix m by x, y, and z, putting the result in sm

param
sm returns the result
param
smOffset index into sm where the result matrix starts
param
m source matrix
param
mOffset index into m where the source matrix starts
param
x scale factor x
param
y scale factor y
param
z scale factor z

        for (int i=0 ; i<4 ; i++) {
            int smi = smOffset + i;
            int mi = mOffset + i;
            sm[     smi] = m[     mi] * x;
            sm[ 4 + smi] = m[ 4 + mi] * y;
            sm[ 8 + smi] = m[ 8 + mi] * z;
            sm[12 + smi] = m[12 + mi];
        }
    
public static voidsetIdentityM(float[] sm, int smOffset)
Sets matrix m to the identity matrix.

param
sm returns the result
param
smOffset index into sm where the result matrix starts

        for (int i=0 ; i<16 ; i++) {
            sm[smOffset + i] = 0;
        }
        for(int i = 0; i < 16; i += 5) {
            sm[smOffset + i] = 1.0f;
        }
    
public static voidsetRotateEulerM(float[] rm, int rmOffset, float x, float y, float z)
Converts Euler angles to a rotation matrix

param
rm returns the result
param
rmOffset index into rm where the result matrix starts
param
x angle of rotation, in degrees
param
y angle of rotation, in degrees
param
z angle of rotation, in degrees

        x *= (float) (Math.PI / 180.0f);
        y *= (float) (Math.PI / 180.0f);
        z *= (float) (Math.PI / 180.0f);
        float cx = (float) Math.cos(x);
        float sx = (float) Math.sin(x);
        float cy = (float) Math.cos(y);
        float sy = (float) Math.sin(y);
        float cz = (float) Math.cos(z);
        float sz = (float) Math.sin(z);
        float cxsy = cx * sy;
        float sxsy = sx * sy;

        rm[rmOffset + 0]  =   cy * cz;
        rm[rmOffset + 1]  =  -cy * sz;
        rm[rmOffset + 2]  =   sy;
        rm[rmOffset + 3]  =  0.0f;

        rm[rmOffset + 4]  =  cxsy * cz + cx * sz;
        rm[rmOffset + 5]  = -cxsy * sz + cx * cz;
        rm[rmOffset + 6]  =  -sx * cy;
        rm[rmOffset + 7]  =  0.0f;

        rm[rmOffset + 8]  = -sxsy * cz + sx * sz;
        rm[rmOffset + 9]  =  sxsy * sz + sx * cz;
        rm[rmOffset + 10] =  cx * cy;
        rm[rmOffset + 11] =  0.0f;

        rm[rmOffset + 12] =  0.0f;
        rm[rmOffset + 13] =  0.0f;
        rm[rmOffset + 14] =  0.0f;
        rm[rmOffset + 15] =  1.0f;
    
public static voidsetRotateM(float[] rm, int rmOffset, float a, float x, float y, float z)
Rotates matrix m by angle a (in degrees) around the axis (x, y, z)

param
rm returns the result
param
rmOffset index into rm where the result matrix starts
param
a angle to rotate in degrees
param
x scale factor x
param
y scale factor y
param
z scale factor z

        rm[rmOffset + 3] = 0;
        rm[rmOffset + 7] = 0;
        rm[rmOffset + 11]= 0;
        rm[rmOffset + 12]= 0;
        rm[rmOffset + 13]= 0;
        rm[rmOffset + 14]= 0;
        rm[rmOffset + 15]= 1;
        a *= (float) (Math.PI / 180.0f);
        float s = (float) Math.sin(a);
        float c = (float) Math.cos(a);
        if (1.0f == x && 0.0f == y && 0.0f == z) {
            rm[rmOffset + 5] = c;   rm[rmOffset + 10]= c;
            rm[rmOffset + 6] = s;   rm[rmOffset + 9] = -s;
            rm[rmOffset + 1] = 0;   rm[rmOffset + 2] = 0;
            rm[rmOffset + 4] = 0;   rm[rmOffset + 8] = 0;
            rm[rmOffset + 0] = 1;
        } else if (0.0f == x && 1.0f == y && 0.0f == z) {
            rm[rmOffset + 0] = c;   rm[rmOffset + 10]= c;
            rm[rmOffset + 8] = s;   rm[rmOffset + 2] = -s;
            rm[rmOffset + 1] = 0;   rm[rmOffset + 4] = 0;
            rm[rmOffset + 6] = 0;   rm[rmOffset + 9] = 0;
            rm[rmOffset + 5] = 1;
        } else if (0.0f == x && 0.0f == y && 1.0f == z) {
            rm[rmOffset + 0] = c;   rm[rmOffset + 5] = c;
            rm[rmOffset + 1] = s;   rm[rmOffset + 4] = -s;
            rm[rmOffset + 2] = 0;   rm[rmOffset + 6] = 0;
            rm[rmOffset + 8] = 0;   rm[rmOffset + 9] = 0;
            rm[rmOffset + 10]= 1;
        } else {
            float len = length(x, y, z);
            if (1.0f != len) {
                float recipLen = 1.0f / len;
                x *= recipLen;
                y *= recipLen;
                z *= recipLen;
            }
            float nc = 1.0f - c;
            float xy = x * y;
            float yz = y * z;
            float zx = z * x;
            float xs = x * s;
            float ys = y * s;
            float zs = z * s;
            rm[rmOffset +  0] = x*x*nc +  c;
            rm[rmOffset +  4] =  xy*nc - zs;
            rm[rmOffset +  8] =  zx*nc + ys;
            rm[rmOffset +  1] =  xy*nc + zs;
            rm[rmOffset +  5] = y*y*nc +  c;
            rm[rmOffset +  9] =  yz*nc - xs;
            rm[rmOffset +  2] =  zx*nc - ys;
            rm[rmOffset +  6] =  yz*nc + xs;
            rm[rmOffset + 10] = z*z*nc +  c;
        }
    
public static voidtranslateM(float[] tm, int tmOffset, float[] m, int mOffset, float x, float y, float z)
Translates matrix m by x, y, and z, putting the result in tm

param
tm returns the result
param
tmOffset index into sm where the result matrix starts
param
m source matrix
param
mOffset index into m where the source matrix starts
param
x translation factor x
param
y translation factor y
param
z translation factor z

        for (int i=0 ; i<12 ; i++) {
            tm[tmOffset + i] = m[mOffset + i];
        }
        for (int i=0 ; i<4 ; i++) {
            int tmi = tmOffset + i;
            int mi = mOffset + i;
            tm[12 + tmi] = m[mi] * x + m[4 + mi] * y + m[8 + mi] * z +
                m[12 + mi];
        }
    
public static voidtranslateM(float[] m, int mOffset, float x, float y, float z)
Translates matrix m by x, y, and z in place.

param
m matrix
param
mOffset index into m where the matrix starts
param
x translation factor x
param
y translation factor y
param
z translation factor z

        for (int i=0 ; i<4 ; i++) {
            int mi = mOffset + i;
            m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
        }
    
public static voidtransposeM(float[] mTrans, int mTransOffset, float[] m, int mOffset)
Transposes a 4 x 4 matrix.

param
mTrans the array that holds the output inverted matrix
param
mTransOffset an offset into mInv where the inverted matrix is stored.
param
m the input array
param
mOffset an offset into m where the matrix is stored.

        for (int i = 0; i < 4; i++) {
            int mBase = i * 4 + mOffset;
            mTrans[i + mTransOffset] = m[mBase];
            mTrans[i + 4 + mTransOffset] = m[mBase + 1];
            mTrans[i + 8 + mTransOffset] = m[mBase + 2];
            mTrans[i + 12 + mTransOffset] = m[mBase + 3];
        }