1 package edu.berkeley.qfat.geom;
2 import javax.media.opengl.*;
4 // FEATURE: precompute/cache determinant?
6 /** an affine matrix; immutable */
17 public final float a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
19 /** the zero matrix */
20 public static final Matrix ZERO = new Matrix(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
22 /** the identity matrix */
23 public static final Matrix ONE = new Matrix(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);
25 /** the identity matrix */
26 public static final Matrix NEGATIVE_ONE = new Matrix(-1,0,0,0,0,-1,0,0,0,0,-1,0,0,0,0,1);
28 public Matrix(double a, double b, double c, double d, double e, double f, double g,
29 double h, double i, double j, double k, double l, double m, double n, double o, double p) {
30 this((float)a, (float)b, (float)c, (float)d,
31 (float)e, (float)f, (float)g, (float)h,
32 (float)i, (float)j, (float)k, (float)l,
33 (float)m, (float)n, (float)o, (float)p);
36 public Matrix(float a, float b, float c, float d, float e, float f, float g,
37 float h, float i, float j, float k, float l, float m, float n, float o, float p) {
38 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;
39 this.j = j; this.k = k; this.l = l; this.m = m; this.n = n; this.o = o; this.p = p;
42 /** a scaling matrix (uniform in all dimensions) */
43 public static Matrix scale(float scale) { return scale(scale, scale, scale); }
45 /** a scaling matrix */
46 public static Matrix scale(float scalex, float scaley, float scalez) {
47 return new Matrix(scalex, 0, 0, 0, 0, scaley, 0, 0, 0, 0, scalez, 0, 0, 0, 0, 1); }
49 /** a translation matrix */
50 public static Matrix translate(Vec translate) {
51 return new Matrix(1, 0, 0, translate.x,
57 /** a rotation matrix, <tt>angle</tt> degrees around <tt>axis</tt> */
58 public static Matrix rotate(Vec axis, float angle) {
59 float q = (float)Math.cos(angle);
60 float s = (float)Math.sin(angle);
62 float a = (float)(q + axis.x*axis.x*t);
63 float f = (float)(q + axis.y*axis.y*t);
64 float k = (float)(q + axis.z*axis.z*t);
65 float tmp1 = axis.x*axis.y*t;
66 float tmp2 = axis.z*s;
67 float e = (float)(tmp1 + tmp2);
68 float b = (float)(tmp1 - tmp2);
69 tmp1 = axis.x*axis.z*t;
71 float i = (float)(tmp1 - tmp2);
72 float c = (float)(tmp1 + tmp2);
73 tmp1 = axis.y*axis.z*t;
75 float j = (float)(tmp1 + tmp2);
76 float g = (float)(tmp1 - tmp2);
77 return new Matrix(a, b, c, 0,
83 public static Matrix reflect(Vec v) {
84 Vec reflectionPlaneNormal = v.norm();
85 float a = reflectionPlaneNormal.x;
86 float b = reflectionPlaneNormal.y;
87 float c = reflectionPlaneNormal.z;
89 new Matrix( 1-2*a*a, -2*a*b, -2*a*c, 0,
90 -2*a*b, 1-2*b*b, -2*b*c, 0,
91 -2*a*c, -2*b*c, 1-2*c*c, 0,
95 public Vec getTranslationalComponent() {
96 return new Vec(d, h, l);
99 public Matrix plus(Matrix x) {
100 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);
102 public Matrix minus(Matrix x) {
103 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);
105 public Matrix times(float x) {
106 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);
109 /** computes (v^T)(this)(v) */
110 public float preAndPostMultiply(Point point) {
112 ((a*point.x + b*point.y + c*point.z + d) * point.x) +
113 ((e*point.x + f*point.y + g*point.z + h) * point.y) +
114 ((i*point.x + j*point.y + k*point.z + l) * point.z) +
115 ((m*point.x + n*point.y + o*point.z + p) * 1);
119 /** discards bottom row */
120 public Point times(Point p) {
121 // discards bottom row
122 double x = a*p.x + b*p.y + c*p.z + d;
123 double y = e*p.x + f*p.y + g*p.z + h;
124 double z = i*p.x + j*p.y + k*p.z + l;
125 double q = m*p.x + n*p.y + o*p.z + this.p;
126 return new Point(x/q, y/q, z/q);
129 /** discards bottom row */
130 public Vec times(Vec p) {
131 return new Vec(a*p.x + b*p.y + c*p.z + d,
132 e*p.x + f*p.y + g*p.z + h,
133 i*p.x + j*p.y + k*p.z + l);
136 public Matrix preMultiplyTranslationalComponentBy(Matrix mm) {
137 Vec v = mm.times(getTranslationalComponent());
138 return new Matrix(a, b, c, v.x,
144 /** multiply by another matrix */
145 public Matrix times(Matrix z) {
178 return new Matrix(t00*m00 + t01*m10 + t02*m20 + t03*m30,
179 t00*m01 + t01*m11 + t02*m21 + t03*m31,
180 t00*m02 + t01*m12 + t02*m22 + t03*m32,
181 t00*m03 + t01*m13 + t02*m23 + t03*m33,
182 t10*m00 + t11*m10 + t12*m20 + t13*m30,
183 t10*m01 + t11*m11 + t12*m21 + t13*m31,
184 t10*m02 + t11*m12 + t12*m22 + t13*m32,
185 t10*m03 + t11*m13 + t12*m23 + t13*m33,
186 t20*m00 + t21*m10 + t22*m20 + t23*m30,
187 t20*m01 + t21*m11 + t22*m21 + t23*m31,
188 t20*m02 + t21*m12 + t22*m22 + t23*m32,
189 t20*m03 + t21*m13 + t22*m23 + t23*m33,
190 t30*m00 + t31*m10 + t32*m20 + t33*m30,
191 t30*m01 + t31*m11 + t32*m21 + t33*m31,
192 t30*m02 + t31*m12 + t32*m22 + t33*m32,
193 t30*m03 + t31*m13 + t32*m23 + t33*m33);
196 /** compute the determinant of the matrix */
197 public float determinant() {
215 m03 * m12 * m21 * m30-m02 * m13 * m21 * m30-m03 * m11 * m22 * m30+m01 * m13 * m22 * m30+
216 m02 * m11 * m23 * m30-m01 * m12 * m23 * m30-m03 * m12 * m20 * m31+m02 * m13 * m20 * m31+
217 m03 * m10 * m22 * m31-m00 * m13 * m22 * m31-m02 * m10 * m23 * m31+m00 * m12 * m23 * m31+
218 m03 * m11 * m20 * m32-m01 * m13 * m20 * m32-m03 * m10 * m21 * m32+m00 * m13 * m21 * m32+
219 m01 * m10 * m23 * m32-m00 * m11 * m23 * m32-m02 * m11 * m20 * m33+m01 * m12 * m20 * m33+
220 m02 * m10 * m21 * m33-m00 * m12 * m21 * m33-m01 * m10 * m22 * m33+m00 * m11 * m22 * m33;
223 /** compute the inverse of the matrix, returns null if not invertible */
224 public Matrix inverse() {
225 float determinant = determinant();
226 if (determinant==0) return null;
244 new Matrix(m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33,
245 m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33,
246 m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33,
247 m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23,
248 m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33,
249 m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33,
250 m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33,
251 m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23,
252 m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33,
253 m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33,
254 m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33,
255 m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23,
256 m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32,
257 m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32,
258 m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32,
259 m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22)
260 .times(1/determinant);
263 public String toString() {
265 "\n [ " + a + "\t" + b + "\t" + c + "\t" + d + "\t" + "]" +
266 "\n [ " + e + "\t" + f + "\t" + g + "\t" + h + "\t" + "]" +
267 "\n [ " + i + "\t" + j + "\t" + k + "\t" + l + "\t" + "]" +
268 "\n [ " + m + "\t" + n + "\t" + o + "\t" + p + "\t" + "]\n";
271 public boolean equals(Object oo) {
272 if (oo==null) return false;
273 if (!(oo instanceof Matrix)) return false;
274 Matrix z = (Matrix)oo;
293 private static final float EPSILON = 0.001f;
294 private static boolean near(float a, float b) { return Math.abs(a-b)<EPSILON; }
296 public int hashCode() {
298 Float.floatToIntBits(a) ^
299 Float.floatToIntBits(b) ^
300 Float.floatToIntBits(c) ^
301 Float.floatToIntBits(d) ^
302 Float.floatToIntBits(e) ^
303 Float.floatToIntBits(f) ^
304 Float.floatToIntBits(g) ^
305 Float.floatToIntBits(h) ^
306 Float.floatToIntBits(i) ^
307 Float.floatToIntBits(j) ^
308 Float.floatToIntBits(k) ^
309 Float.floatToIntBits(l) ^
310 Float.floatToIntBits(m) ^
311 Float.floatToIntBits(n) ^
312 Float.floatToIntBits(o) ^
313 Float.floatToIntBits(p);
316 public static Matrix getProjectionMatrix(GL gl) {
317 int view[] = new int[4];
318 double mvmatrix[] = new double[16];
319 double projmatrix[] = new double[16];
320 gl.glGetIntegerv(GL.GL_VIEWPORT, view, 0);
321 gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mvmatrix, 0);
322 gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, projmatrix, 0);
323 Matrix m = new Matrix(mvmatrix[0],
339 Matrix p = new Matrix(projmatrix[0],
356 new Matrix(0.5*view[2], 0, 0, view[0]+view[2]*0.5,
357 0, 0.5*view[3], 0, view[1]+view[3]*0.5,
360 return z.times(p).times(m);