1 package edu.berkeley.qfat.geom;
3 // FEATURE: precompute/cache determinant?
5 /** an affine matrix; immutable */
16 public final float a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
18 /** the zero matrix */
19 public static final Matrix ZERO = new Matrix(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
21 /** the identity matrix */
22 public static final Matrix ONE = new Matrix(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);
24 /** the identity matrix */
25 public static final Matrix NEGATIVE_ONE = new Matrix(-1,0,0,0,0,-1,0,0,0,0,-1,0,0,0,0,1);
27 public Matrix(float a, float b, float c, float d, float e, float f, float g,
28 float h, float i, float j, float k, float l, float m, float n, float o, float p) {
29 this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; this.g = g; this.h = h; this.i = i;
30 this.j = j; this.k = k; this.l = l; this.m = m; this.n = n; this.o = o; this.p = p;
33 /** a scaling matrix (uniform in all dimensions) */
34 public static Matrix scale(float scale) { return scale(scale, scale, scale); }
36 /** a scaling matrix */
37 public static Matrix scale(float scalex, float scaley, float scalez) {
38 return new Matrix(scalex, 0, 0, 0, 0, scaley, 0, 0, 0, 0, scalez, 0, 0, 0, 0, 1); }
40 /** a translation matrix */
41 public static Matrix translate(Vec translate) {
42 return new Matrix(1, 0, 0, translate.x,
48 /** a rotation matrix, <tt>angle</tt> degrees around <tt>axis</tt> */
49 public static Matrix rotate(Vec axis, float angle) {
50 float q = (float)Math.cos(angle);
51 float s = (float)Math.sin(angle);
53 float a = (float)(q + axis.x*axis.x*t);
54 float f = (float)(q + axis.y*axis.y*t);
55 float k = (float)(q + axis.z*axis.z*t);
56 float tmp1 = axis.x*axis.y*t;
57 float tmp2 = axis.z*s;
58 float e = (float)(tmp1 + tmp2);
59 float b = (float)(tmp1 - tmp2);
60 tmp1 = axis.x*axis.z*t;
62 float i = (float)(tmp1 - tmp2);
63 float c = (float)(tmp1 + tmp2);
64 tmp1 = axis.y*axis.z*t;
66 float j = (float)(tmp1 + tmp2);
67 float g = (float)(tmp1 - tmp2);
68 return new Matrix(a, b, c, 0,
74 public Matrix plus(Matrix x) {
75 return new Matrix(a+x.a, b+x.b, c+x.c, d+x.d, e+x.e, f+x.f, g+x.g, h+x.h, i+x.i, j+x.j, k+x.k, l+x.l, m+x.m, n+x.n, o+x.o, p+x.p);
77 public Matrix minus(Matrix x) {
78 return new Matrix(a-x.a, b-x.b, c-x.c, d-x.d, e-x.e, f-x.f, g-x.g, h-x.h, i-x.i, j-x.j, k-x.k, l-x.l, m-x.m, n-x.n, o-x.o, p-x.p);
80 public Matrix times(float x) {
81 return new Matrix(a*x, b*x, c*x, d*x, e*x, f*x, g*x, h*x, i*x, j*x, k*x, l*x, m*x, n*x, o*x, p*x);
84 /** computes (v^T)(this)(v) */
85 public float preAndPostMultiply(Point point) {
87 ((a*point.x + b*point.y + c*point.z + d) * point.x) +
88 ((e*point.x + f*point.y + g*point.z + h) * point.y) +
89 ((i*point.x + j*point.y + k*point.z + l) * point.z) +
90 ((m*point.x + n*point.y + o*point.z + p) * 1);
94 /** discards bottom row */
95 public Point times(Point p) {
96 // discards bottom row
97 return new Point(a*p.x + b*p.y + c*p.z + d,
98 e*p.x + f*p.y + g*p.z + h,
99 i*p.x + j*p.y + k*p.z + l);
102 /** discards bottom row */
103 public Vec times(Vec p) {
104 return new Vec(a*p.x + b*p.y + c*p.z + d,
105 e*p.x + f*p.y + g*p.z + h,
106 i*p.x + j*p.y + k*p.z + l);
109 /** multiply by another matrix */
110 public Matrix times(Matrix z) {
143 return new Matrix(t00*m00 + t01*m10 + t02*m20 + t03*m30,
144 t00*m01 + t01*m11 + t02*m21 + t03*m31,
145 t00*m02 + t01*m12 + t02*m22 + t03*m32,
146 t00*m03 + t01*m13 + t02*m23 + t03*m33,
147 t10*m00 + t11*m10 + t12*m20 + t13*m30,
148 t10*m01 + t11*m11 + t12*m21 + t13*m31,
149 t10*m02 + t11*m12 + t12*m22 + t13*m32,
150 t10*m03 + t11*m13 + t12*m23 + t13*m33,
151 t20*m00 + t21*m10 + t22*m20 + t23*m30,
152 t20*m01 + t21*m11 + t22*m21 + t23*m31,
153 t20*m02 + t21*m12 + t22*m22 + t23*m32,
154 t20*m03 + t21*m13 + t22*m23 + t23*m33,
155 t30*m00 + t31*m10 + t32*m20 + t33*m30,
156 t30*m01 + t31*m11 + t32*m21 + t33*m31,
157 t30*m02 + t31*m12 + t32*m22 + t33*m32,
158 t30*m03 + t31*m13 + t32*m23 + t33*m33);
161 /** compute the determinant of the matrix */
162 public float determinant() {
180 m03 * m12 * m21 * m30-m02 * m13 * m21 * m30-m03 * m11 * m22 * m30+m01 * m13 * m22 * m30+
181 m02 * m11 * m23 * m30-m01 * m12 * m23 * m30-m03 * m12 * m20 * m31+m02 * m13 * m20 * m31+
182 m03 * m10 * m22 * m31-m00 * m13 * m22 * m31-m02 * m10 * m23 * m31+m00 * m12 * m23 * m31+
183 m03 * m11 * m20 * m32-m01 * m13 * m20 * m32-m03 * m10 * m21 * m32+m00 * m13 * m21 * m32+
184 m01 * m10 * m23 * m32-m00 * m11 * m23 * m32-m02 * m11 * m20 * m33+m01 * m12 * m20 * m33+
185 m02 * m10 * m21 * m33-m00 * m12 * m21 * m33-m01 * m10 * m22 * m33+m00 * m11 * m22 * m33;
188 /** compute the inverse of the matrix, returns null if not invertible */
189 public Matrix inverse() {
190 float determinant = determinant();
191 if (determinant==0) return null;
209 new Matrix(m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33,
210 m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33,
211 m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33,
212 m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23,
213 m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33,
214 m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33,
215 m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33,
216 m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23,
217 m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33,
218 m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33,
219 m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33,
220 m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23,
221 m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32,
222 m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32,
223 m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32,
224 m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22)
225 .times(1/determinant);
228 public String toString() {
230 "\n [ " + a + "\t" + b + "\t" + c + "\t" + d + "\t" + "]" +
231 "\n [ " + e + "\t" + f + "\t" + g + "\t" + h + "\t" + "]" +
232 "\n [ " + i + "\t" + j + "\t" + k + "\t" + l + "\t" + "]" +
233 "\n [ " + m + "\t" + n + "\t" + o + "\t" + p + "\t" + "]\n";
236 public boolean equals(Object oo) {
237 if (oo==null) return false;
238 if (!(oo instanceof Matrix)) return false;
239 Matrix z = (Matrix)oo;
259 public int hashCode() {
261 Float.floatToIntBits(a) ^
262 Float.floatToIntBits(b) ^
263 Float.floatToIntBits(c) ^
264 Float.floatToIntBits(d) ^
265 Float.floatToIntBits(e) ^
266 Float.floatToIntBits(f) ^
267 Float.floatToIntBits(g) ^
268 Float.floatToIntBits(h) ^
269 Float.floatToIntBits(i) ^
270 Float.floatToIntBits(j) ^
271 Float.floatToIntBits(k) ^
272 Float.floatToIntBits(l) ^
273 Float.floatToIntBits(m) ^
274 Float.floatToIntBits(n) ^
275 Float.floatToIntBits(o) ^
276 Float.floatToIntBits(p);