1 /*
2  * Copyright (c) 2002-2008 LWJGL Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'LWJGL' nor the names of
17  *   its contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.lwjgl.util.vector;
33 
34 import java.io.Serializable;
35 import java.nio.FloatBuffer;
36 
37 /**
38  * Holds a 4x4 float matrix.
39  *
40  * @author foo
41  */
42 public class Matrix4f extends Matrix implements Serializable {
43 	private static final long serialVersionUID = 1L;
44 
45 	public float m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;
46 
47 	/**
48 	 * Construct a new matrix, initialized to the identity.
49 	 */
Matrix4f()50 	public Matrix4f() {
51 		super();
52 		setIdentity();
53 	}
54 
Matrix4f(final Matrix4f src)55 	public Matrix4f(final Matrix4f src) {
56 		super();
57 		load(src);
58 	}
59 
60 	/**
61 	 * Returns a string representation of this matrix
62 	 */
toString()63 	public String toString() {
64 		StringBuilder buf = new StringBuilder();
65 		buf.append(m00).append(' ').append(m10).append(' ').append(m20).append(' ').append(m30).append('\n');
66 		buf.append(m01).append(' ').append(m11).append(' ').append(m21).append(' ').append(m31).append('\n');
67 		buf.append(m02).append(' ').append(m12).append(' ').append(m22).append(' ').append(m32).append('\n');
68 		buf.append(m03).append(' ').append(m13).append(' ').append(m23).append(' ').append(m33).append('\n');
69 		return buf.toString();
70 	}
71 
72 	/**
73 	 * Set this matrix to be the identity matrix.
74 	 * @return this
75 	 */
setIdentity()76 	public Matrix setIdentity() {
77 		return setIdentity(this);
78 	}
79 
80 	/**
81 	 * Set the given matrix to be the identity matrix.
82 	 * @param m The matrix to set to the identity
83 	 * @return m
84 	 */
setIdentity(Matrix4f m)85 	public static Matrix4f setIdentity(Matrix4f m) {
86 		m.m00 = 1.0f;
87 		m.m01 = 0.0f;
88 		m.m02 = 0.0f;
89 		m.m03 = 0.0f;
90 		m.m10 = 0.0f;
91 		m.m11 = 1.0f;
92 		m.m12 = 0.0f;
93 		m.m13 = 0.0f;
94 		m.m20 = 0.0f;
95 		m.m21 = 0.0f;
96 		m.m22 = 1.0f;
97 		m.m23 = 0.0f;
98 		m.m30 = 0.0f;
99 		m.m31 = 0.0f;
100 		m.m32 = 0.0f;
101 		m.m33 = 1.0f;
102 
103 		return m;
104 	}
105 
106 	/**
107 	 * Set this matrix to 0.
108 	 * @return this
109 	 */
setZero()110 	public Matrix setZero() {
111 		return setZero(this);
112 	}
113 
114 	/**
115 	 * Set the given matrix to 0.
116 	 * @param m The matrix to set to 0
117 	 * @return m
118 	 */
setZero(Matrix4f m)119 	public static Matrix4f setZero(Matrix4f m) {
120 		m.m00 = 0.0f;
121 		m.m01 = 0.0f;
122 		m.m02 = 0.0f;
123 		m.m03 = 0.0f;
124 		m.m10 = 0.0f;
125 		m.m11 = 0.0f;
126 		m.m12 = 0.0f;
127 		m.m13 = 0.0f;
128 		m.m20 = 0.0f;
129 		m.m21 = 0.0f;
130 		m.m22 = 0.0f;
131 		m.m23 = 0.0f;
132 		m.m30 = 0.0f;
133 		m.m31 = 0.0f;
134 		m.m32 = 0.0f;
135 		m.m33 = 0.0f;
136 
137 		return m;
138 	}
139 
140 	/**
141 	 * Load from another matrix4f
142 	 * @param src The source matrix
143 	 * @return this
144 	 */
load(Matrix4f src)145 	public Matrix4f load(Matrix4f src) {
146 		return load(src, this);
147 	}
148 
149 	/**
150 	 * Copy the source matrix to the destination matrix
151 	 * @param src The source matrix
152 	 * @param dest The destination matrix, or null of a new one is to be created
153 	 * @return The copied matrix
154 	 */
load(Matrix4f src, Matrix4f dest)155 	public static Matrix4f load(Matrix4f src, Matrix4f dest) {
156 		if (dest == null)
157 			dest = new Matrix4f();
158 		dest.m00 = src.m00;
159 		dest.m01 = src.m01;
160 		dest.m02 = src.m02;
161 		dest.m03 = src.m03;
162 		dest.m10 = src.m10;
163 		dest.m11 = src.m11;
164 		dest.m12 = src.m12;
165 		dest.m13 = src.m13;
166 		dest.m20 = src.m20;
167 		dest.m21 = src.m21;
168 		dest.m22 = src.m22;
169 		dest.m23 = src.m23;
170 		dest.m30 = src.m30;
171 		dest.m31 = src.m31;
172 		dest.m32 = src.m32;
173 		dest.m33 = src.m33;
174 
175 		return dest;
176 	}
177 
178 	/**
179 	 * Load from a float buffer. The buffer stores the matrix in column major
180 	 * (OpenGL) order.
181 	 *
182 	 * @param buf A float buffer to read from
183 	 * @return this
184 	 */
load(FloatBuffer buf)185 	public Matrix load(FloatBuffer buf) {
186 
187 		m00 = buf.get();
188 		m01 = buf.get();
189 		m02 = buf.get();
190 		m03 = buf.get();
191 		m10 = buf.get();
192 		m11 = buf.get();
193 		m12 = buf.get();
194 		m13 = buf.get();
195 		m20 = buf.get();
196 		m21 = buf.get();
197 		m22 = buf.get();
198 		m23 = buf.get();
199 		m30 = buf.get();
200 		m31 = buf.get();
201 		m32 = buf.get();
202 		m33 = buf.get();
203 
204 		return this;
205 	}
206 
207 	/**
208 	 * Load from a float buffer. The buffer stores the matrix in row major
209 	 * (maths) order.
210 	 *
211 	 * @param buf A float buffer to read from
212 	 * @return this
213 	 */
loadTranspose(FloatBuffer buf)214 	public Matrix loadTranspose(FloatBuffer buf) {
215 
216 		m00 = buf.get();
217 		m10 = buf.get();
218 		m20 = buf.get();
219 		m30 = buf.get();
220 		m01 = buf.get();
221 		m11 = buf.get();
222 		m21 = buf.get();
223 		m31 = buf.get();
224 		m02 = buf.get();
225 		m12 = buf.get();
226 		m22 = buf.get();
227 		m32 = buf.get();
228 		m03 = buf.get();
229 		m13 = buf.get();
230 		m23 = buf.get();
231 		m33 = buf.get();
232 
233 		return this;
234 	}
235 
236 	/**
237 	 * Store this matrix in a float buffer. The matrix is stored in column
238 	 * major (openGL) order.
239 	 * @param buf The buffer to store this matrix in
240 	 */
store(FloatBuffer buf)241 	public Matrix store(FloatBuffer buf) {
242 		buf.put(m00);
243 		buf.put(m01);
244 		buf.put(m02);
245 		buf.put(m03);
246 		buf.put(m10);
247 		buf.put(m11);
248 		buf.put(m12);
249 		buf.put(m13);
250 		buf.put(m20);
251 		buf.put(m21);
252 		buf.put(m22);
253 		buf.put(m23);
254 		buf.put(m30);
255 		buf.put(m31);
256 		buf.put(m32);
257 		buf.put(m33);
258 		return this;
259 	}
260 
261 	/**
262 	 * Store this matrix in a float buffer. The matrix is stored in row
263 	 * major (maths) order.
264 	 * @param buf The buffer to store this matrix in
265 	 */
storeTranspose(FloatBuffer buf)266 	public Matrix storeTranspose(FloatBuffer buf) {
267 		buf.put(m00);
268 		buf.put(m10);
269 		buf.put(m20);
270 		buf.put(m30);
271 		buf.put(m01);
272 		buf.put(m11);
273 		buf.put(m21);
274 		buf.put(m31);
275 		buf.put(m02);
276 		buf.put(m12);
277 		buf.put(m22);
278 		buf.put(m32);
279 		buf.put(m03);
280 		buf.put(m13);
281 		buf.put(m23);
282 		buf.put(m33);
283 		return this;
284 	}
285 
286 	/**
287 	 * Store the rotation portion of this matrix in a float buffer. The matrix is stored in column
288 	 * major (openGL) order.
289 	 * @param buf The buffer to store this matrix in
290 	 */
store3f(FloatBuffer buf)291 	public Matrix store3f(FloatBuffer buf) {
292 		buf.put(m00);
293 		buf.put(m01);
294 		buf.put(m02);
295 		buf.put(m10);
296 		buf.put(m11);
297 		buf.put(m12);
298 		buf.put(m20);
299 		buf.put(m21);
300 		buf.put(m22);
301 		return this;
302 	}
303 
304 	/**
305 	 * Add two matrices together and place the result in a third matrix.
306 	 * @param left The left source matrix
307 	 * @param right The right source matrix
308 	 * @param dest The destination matrix, or null if a new one is to be created
309 	 * @return the destination matrix
310 	 */
add(Matrix4f left, Matrix4f right, Matrix4f dest)311 	public static Matrix4f add(Matrix4f left, Matrix4f right, Matrix4f dest) {
312 		if (dest == null)
313 			dest = new Matrix4f();
314 
315 		dest.m00 = left.m00 + right.m00;
316 		dest.m01 = left.m01 + right.m01;
317 		dest.m02 = left.m02 + right.m02;
318 		dest.m03 = left.m03 + right.m03;
319 		dest.m10 = left.m10 + right.m10;
320 		dest.m11 = left.m11 + right.m11;
321 		dest.m12 = left.m12 + right.m12;
322 		dest.m13 = left.m13 + right.m13;
323 		dest.m20 = left.m20 + right.m20;
324 		dest.m21 = left.m21 + right.m21;
325 		dest.m22 = left.m22 + right.m22;
326 		dest.m23 = left.m23 + right.m23;
327 		dest.m30 = left.m30 + right.m30;
328 		dest.m31 = left.m31 + right.m31;
329 		dest.m32 = left.m32 + right.m32;
330 		dest.m33 = left.m33 + right.m33;
331 
332 		return dest;
333 	}
334 
335 	/**
336 	 * Subtract the right matrix from the left and place the result in a third matrix.
337 	 * @param left The left source matrix
338 	 * @param right The right source matrix
339 	 * @param dest The destination matrix, or null if a new one is to be created
340 	 * @return the destination matrix
341 	 */
sub(Matrix4f left, Matrix4f right, Matrix4f dest)342 	public static Matrix4f sub(Matrix4f left, Matrix4f right, Matrix4f dest) {
343 		if (dest == null)
344 			dest = new Matrix4f();
345 
346 		dest.m00 = left.m00 - right.m00;
347 		dest.m01 = left.m01 - right.m01;
348 		dest.m02 = left.m02 - right.m02;
349 		dest.m03 = left.m03 - right.m03;
350 		dest.m10 = left.m10 - right.m10;
351 		dest.m11 = left.m11 - right.m11;
352 		dest.m12 = left.m12 - right.m12;
353 		dest.m13 = left.m13 - right.m13;
354 		dest.m20 = left.m20 - right.m20;
355 		dest.m21 = left.m21 - right.m21;
356 		dest.m22 = left.m22 - right.m22;
357 		dest.m23 = left.m23 - right.m23;
358 		dest.m30 = left.m30 - right.m30;
359 		dest.m31 = left.m31 - right.m31;
360 		dest.m32 = left.m32 - right.m32;
361 		dest.m33 = left.m33 - right.m33;
362 
363 		return dest;
364 	}
365 
366 	/**
367 	 * Multiply the right matrix by the left and place the result in a third matrix.
368 	 * @param left The left source matrix
369 	 * @param right The right source matrix
370 	 * @param dest The destination matrix, or null if a new one is to be created
371 	 * @return the destination matrix
372 	 */
mul(Matrix4f left, Matrix4f right, Matrix4f dest)373 	public static Matrix4f mul(Matrix4f left, Matrix4f right, Matrix4f dest) {
374 		if (dest == null)
375 			dest = new Matrix4f();
376 
377 		float m00 = left.m00 * right.m00 + left.m10 * right.m01 + left.m20 * right.m02 + left.m30 * right.m03;
378 		float m01 = left.m01 * right.m00 + left.m11 * right.m01 + left.m21 * right.m02 + left.m31 * right.m03;
379 		float m02 = left.m02 * right.m00 + left.m12 * right.m01 + left.m22 * right.m02 + left.m32 * right.m03;
380 		float m03 = left.m03 * right.m00 + left.m13 * right.m01 + left.m23 * right.m02 + left.m33 * right.m03;
381 		float m10 = left.m00 * right.m10 + left.m10 * right.m11 + left.m20 * right.m12 + left.m30 * right.m13;
382 		float m11 = left.m01 * right.m10 + left.m11 * right.m11 + left.m21 * right.m12 + left.m31 * right.m13;
383 		float m12 = left.m02 * right.m10 + left.m12 * right.m11 + left.m22 * right.m12 + left.m32 * right.m13;
384 		float m13 = left.m03 * right.m10 + left.m13 * right.m11 + left.m23 * right.m12 + left.m33 * right.m13;
385 		float m20 = left.m00 * right.m20 + left.m10 * right.m21 + left.m20 * right.m22 + left.m30 * right.m23;
386 		float m21 = left.m01 * right.m20 + left.m11 * right.m21 + left.m21 * right.m22 + left.m31 * right.m23;
387 		float m22 = left.m02 * right.m20 + left.m12 * right.m21 + left.m22 * right.m22 + left.m32 * right.m23;
388 		float m23 = left.m03 * right.m20 + left.m13 * right.m21 + left.m23 * right.m22 + left.m33 * right.m23;
389 		float m30 = left.m00 * right.m30 + left.m10 * right.m31 + left.m20 * right.m32 + left.m30 * right.m33;
390 		float m31 = left.m01 * right.m30 + left.m11 * right.m31 + left.m21 * right.m32 + left.m31 * right.m33;
391 		float m32 = left.m02 * right.m30 + left.m12 * right.m31 + left.m22 * right.m32 + left.m32 * right.m33;
392 		float m33 = left.m03 * right.m30 + left.m13 * right.m31 + left.m23 * right.m32 + left.m33 * right.m33;
393 
394 		dest.m00 = m00;
395 		dest.m01 = m01;
396 		dest.m02 = m02;
397 		dest.m03 = m03;
398 		dest.m10 = m10;
399 		dest.m11 = m11;
400 		dest.m12 = m12;
401 		dest.m13 = m13;
402 		dest.m20 = m20;
403 		dest.m21 = m21;
404 		dest.m22 = m22;
405 		dest.m23 = m23;
406 		dest.m30 = m30;
407 		dest.m31 = m31;
408 		dest.m32 = m32;
409 		dest.m33 = m33;
410 
411 		return dest;
412 	}
413 
414 	/**
415 	 * Transform a Vector by a matrix and return the result in a destination
416 	 * vector.
417 	 * @param left The left matrix
418 	 * @param right The right vector
419 	 * @param dest The destination vector, or null if a new one is to be created
420 	 * @return the destination vector
421 	 */
transform(Matrix4f left, Vector4f right, Vector4f dest)422 	public static Vector4f transform(Matrix4f left, Vector4f right, Vector4f dest) {
423 		if (dest == null)
424 			dest = new Vector4f();
425 
426 		float x = left.m00 * right.x + left.m10 * right.y + left.m20 * right.z + left.m30 * right.w;
427 		float y = left.m01 * right.x + left.m11 * right.y + left.m21 * right.z + left.m31 * right.w;
428 		float z = left.m02 * right.x + left.m12 * right.y + left.m22 * right.z + left.m32 * right.w;
429 		float w = left.m03 * right.x + left.m13 * right.y + left.m23 * right.z + left.m33 * right.w;
430 
431 		dest.x = x;
432 		dest.y = y;
433 		dest.z = z;
434 		dest.w = w;
435 
436 		return dest;
437 	}
438 
439 	/**
440 	 * Transpose this matrix
441 	 * @return this
442 	 */
transpose()443 	public Matrix transpose() {
444 		return transpose(this);
445 	}
446 
447 	/**
448 	 * Translate this matrix
449 	 * @param vec The vector to translate by
450 	 * @return this
451 	 */
translate(Vector2f vec)452 	public Matrix4f translate(Vector2f vec) {
453 		return translate(vec, this);
454 	}
455 
456 	/**
457 	 * Translate this matrix
458 	 * @param vec The vector to translate by
459 	 * @return this
460 	 */
translate(Vector3f vec)461 	public Matrix4f translate(Vector3f vec) {
462 		return translate(vec, this);
463 	}
464 
465 	/**
466 	 * Scales this matrix
467 	 * @param vec The vector to scale by
468 	 * @return this
469 	 */
scale(Vector3f vec)470 	public Matrix4f scale(Vector3f vec) {
471 		return scale(vec, this, this);
472 	}
473 
474 	/**
475 	 * Scales the source matrix and put the result in the destination matrix
476 	 * @param vec The vector to scale by
477 	 * @param src The source matrix
478 	 * @param dest The destination matrix, or null if a new matrix is to be created
479 	 * @return The scaled matrix
480 	 */
scale(Vector3f vec, Matrix4f src, Matrix4f dest)481 	public static Matrix4f scale(Vector3f vec, Matrix4f src, Matrix4f dest) {
482 		if (dest == null)
483 			dest = new Matrix4f();
484 		dest.m00 = src.m00 * vec.x;
485 		dest.m01 = src.m01 * vec.x;
486 		dest.m02 = src.m02 * vec.x;
487 		dest.m03 = src.m03 * vec.x;
488 		dest.m10 = src.m10 * vec.y;
489 		dest.m11 = src.m11 * vec.y;
490 		dest.m12 = src.m12 * vec.y;
491 		dest.m13 = src.m13 * vec.y;
492 		dest.m20 = src.m20 * vec.z;
493 		dest.m21 = src.m21 * vec.z;
494 		dest.m22 = src.m22 * vec.z;
495 		dest.m23 = src.m23 * vec.z;
496 		return dest;
497 	}
498 
499 	/**
500 	 * Rotates the matrix around the given axis the specified angle
501 	 * @param angle the angle, in radians.
502 	 * @param axis The vector representing the rotation axis. Must be normalized.
503 	 * @return this
504 	 */
rotate(float angle, Vector3f axis)505 	public Matrix4f rotate(float angle, Vector3f axis) {
506 		return rotate(angle, axis, this);
507 	}
508 
509 	/**
510 	 * Rotates the matrix around the given axis the specified angle
511 	 * @param angle the angle, in radians.
512 	 * @param axis The vector representing the rotation axis. Must be normalized.
513 	 * @param dest The matrix to put the result, or null if a new matrix is to be created
514 	 * @return The rotated matrix
515 	 */
rotate(float angle, Vector3f axis, Matrix4f dest)516 	public Matrix4f rotate(float angle, Vector3f axis, Matrix4f dest) {
517 		return rotate(angle, axis, this, dest);
518 	}
519 
520 	/**
521 	 * Rotates the source matrix around the given axis the specified angle and
522 	 * put the result in the destination matrix.
523 	 * @param angle the angle, in radians.
524 	 * @param axis The vector representing the rotation axis. Must be normalized.
525 	 * @param src The matrix to rotate
526 	 * @param dest The matrix to put the result, or null if a new matrix is to be created
527 	 * @return The rotated matrix
528 	 */
rotate(float angle, Vector3f axis, Matrix4f src, Matrix4f dest)529 	public static Matrix4f rotate(float angle, Vector3f axis, Matrix4f src, Matrix4f dest) {
530 		if (dest == null)
531 			dest = new Matrix4f();
532 		float c = (float) Math.cos(angle);
533 		float s = (float) Math.sin(angle);
534 		float oneminusc = 1.0f - c;
535 		float xy = axis.x*axis.y;
536 		float yz = axis.y*axis.z;
537 		float xz = axis.x*axis.z;
538 		float xs = axis.x*s;
539 		float ys = axis.y*s;
540 		float zs = axis.z*s;
541 
542 		float f00 = axis.x*axis.x*oneminusc+c;
543 		float f01 = xy*oneminusc+zs;
544 		float f02 = xz*oneminusc-ys;
545 		// n[3] not used
546 		float f10 = xy*oneminusc-zs;
547 		float f11 = axis.y*axis.y*oneminusc+c;
548 		float f12 = yz*oneminusc+xs;
549 		// n[7] not used
550 		float f20 = xz*oneminusc+ys;
551 		float f21 = yz*oneminusc-xs;
552 		float f22 = axis.z*axis.z*oneminusc+c;
553 
554 		float t00 = src.m00 * f00 + src.m10 * f01 + src.m20 * f02;
555 		float t01 = src.m01 * f00 + src.m11 * f01 + src.m21 * f02;
556 		float t02 = src.m02 * f00 + src.m12 * f01 + src.m22 * f02;
557 		float t03 = src.m03 * f00 + src.m13 * f01 + src.m23 * f02;
558 		float t10 = src.m00 * f10 + src.m10 * f11 + src.m20 * f12;
559 		float t11 = src.m01 * f10 + src.m11 * f11 + src.m21 * f12;
560 		float t12 = src.m02 * f10 + src.m12 * f11 + src.m22 * f12;
561 		float t13 = src.m03 * f10 + src.m13 * f11 + src.m23 * f12;
562 		dest.m20 = src.m00 * f20 + src.m10 * f21 + src.m20 * f22;
563 		dest.m21 = src.m01 * f20 + src.m11 * f21 + src.m21 * f22;
564 		dest.m22 = src.m02 * f20 + src.m12 * f21 + src.m22 * f22;
565 		dest.m23 = src.m03 * f20 + src.m13 * f21 + src.m23 * f22;
566 		dest.m00 = t00;
567 		dest.m01 = t01;
568 		dest.m02 = t02;
569 		dest.m03 = t03;
570 		dest.m10 = t10;
571 		dest.m11 = t11;
572 		dest.m12 = t12;
573 		dest.m13 = t13;
574 		return dest;
575 	}
576 
577 	/**
578 	 * Translate this matrix and stash the result in another matrix
579 	 * @param vec The vector to translate by
580 	 * @param dest The destination matrix or null if a new matrix is to be created
581 	 * @return the translated matrix
582 	 */
translate(Vector3f vec, Matrix4f dest)583 	public Matrix4f translate(Vector3f vec, Matrix4f dest) {
584 		return translate(vec, this, dest);
585 	}
586 
587 	/**
588 	 * Translate the source matrix and stash the result in the destination matrix
589 	 * @param vec The vector to translate by
590 	 * @param src The source matrix
591 	 * @param dest The destination matrix or null if a new matrix is to be created
592 	 * @return The translated matrix
593 	 */
translate(Vector3f vec, Matrix4f src, Matrix4f dest)594 	public static Matrix4f translate(Vector3f vec, Matrix4f src, Matrix4f dest) {
595 		if (dest == null)
596 			dest = new Matrix4f();
597 
598 		dest.m30 += src.m00 * vec.x + src.m10 * vec.y + src.m20 * vec.z;
599 		dest.m31 += src.m01 * vec.x + src.m11 * vec.y + src.m21 * vec.z;
600 		dest.m32 += src.m02 * vec.x + src.m12 * vec.y + src.m22 * vec.z;
601 		dest.m33 += src.m03 * vec.x + src.m13 * vec.y + src.m23 * vec.z;
602 
603 		return dest;
604 	}
605 
606 	/**
607 	 * Translate this matrix and stash the result in another matrix
608 	 * @param vec The vector to translate by
609 	 * @param dest The destination matrix or null if a new matrix is to be created
610 	 * @return the translated matrix
611 	 */
translate(Vector2f vec, Matrix4f dest)612 	public Matrix4f translate(Vector2f vec, Matrix4f dest) {
613 		return translate(vec, this, dest);
614 	}
615 
616 	/**
617 	 * Translate the source matrix and stash the result in the destination matrix
618 	 * @param vec The vector to translate by
619 	 * @param src The source matrix
620 	 * @param dest The destination matrix or null if a new matrix is to be created
621 	 * @return The translated matrix
622 	 */
translate(Vector2f vec, Matrix4f src, Matrix4f dest)623 	public static Matrix4f translate(Vector2f vec, Matrix4f src, Matrix4f dest) {
624 		if (dest == null)
625 			dest = new Matrix4f();
626 
627 		dest.m30 += src.m00 * vec.x + src.m10 * vec.y;
628 		dest.m31 += src.m01 * vec.x + src.m11 * vec.y;
629 		dest.m32 += src.m02 * vec.x + src.m12 * vec.y;
630 		dest.m33 += src.m03 * vec.x + src.m13 * vec.y;
631 
632 		return dest;
633 	}
634 
635 	/**
636 	 * Transpose this matrix and place the result in another matrix
637 	 * @param dest The destination matrix or null if a new matrix is to be created
638 	 * @return the transposed matrix
639 	 */
transpose(Matrix4f dest)640 	public Matrix4f transpose(Matrix4f dest) {
641 		return transpose(this, dest);
642 	}
643 
644 	/**
645 	 * Transpose the source matrix and place the result in the destination matrix
646 	 * @param src The source matrix
647 	 * @param dest The destination matrix or null if a new matrix is to be created
648 	 * @return the transposed matrix
649 	 */
transpose(Matrix4f src, Matrix4f dest)650 	public static Matrix4f transpose(Matrix4f src, Matrix4f dest) {
651 		if (dest == null)
652 		   dest = new Matrix4f();
653 		float m00 = src.m00;
654 		float m01 = src.m10;
655 		float m02 = src.m20;
656 		float m03 = src.m30;
657 		float m10 = src.m01;
658 		float m11 = src.m11;
659 		float m12 = src.m21;
660 		float m13 = src.m31;
661 		float m20 = src.m02;
662 		float m21 = src.m12;
663 		float m22 = src.m22;
664 		float m23 = src.m32;
665 		float m30 = src.m03;
666 		float m31 = src.m13;
667 		float m32 = src.m23;
668 		float m33 = src.m33;
669 
670 		dest.m00 = m00;
671 		dest.m01 = m01;
672 		dest.m02 = m02;
673 		dest.m03 = m03;
674 		dest.m10 = m10;
675 		dest.m11 = m11;
676 		dest.m12 = m12;
677 		dest.m13 = m13;
678 		dest.m20 = m20;
679 		dest.m21 = m21;
680 		dest.m22 = m22;
681 		dest.m23 = m23;
682 		dest.m30 = m30;
683 		dest.m31 = m31;
684 		dest.m32 = m32;
685 		dest.m33 = m33;
686 
687 		return dest;
688 	}
689 
690 	/**
691 	 * @return the determinant of the matrix
692 	 */
determinant()693 	public float determinant() {
694 		float f =
695 			m00
696 				* ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32)
697 					- m13 * m22 * m31
698 					- m11 * m23 * m32
699 					- m12 * m21 * m33);
700 		f -= m01
701 			* ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32)
702 				- m13 * m22 * m30
703 				- m10 * m23 * m32
704 				- m12 * m20 * m33);
705 		f += m02
706 			* ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31)
707 				- m13 * m21 * m30
708 				- m10 * m23 * m31
709 				- m11 * m20 * m33);
710 		f -= m03
711 			* ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31)
712 				- m12 * m21 * m30
713 				- m10 * m22 * m31
714 				- m11 * m20 * m32);
715 		return f;
716 	}
717 
718 	/**
719 	 * Calculate the determinant of a 3x3 matrix
720 	 * @return result
721 	 */
722 
determinant3x3(float t00, float t01, float t02, float t10, float t11, float t12, float t20, float t21, float t22)723 	private static float determinant3x3(float t00, float t01, float t02,
724 				     float t10, float t11, float t12,
725 				     float t20, float t21, float t22)
726 	{
727 		return   t00 * (t11 * t22 - t12 * t21)
728 		       + t01 * (t12 * t20 - t10 * t22)
729 		       + t02 * (t10 * t21 - t11 * t20);
730 	}
731 
732 	/**
733 	 * Invert this matrix
734 	 * @return this if successful, null otherwise
735 	 */
invert()736 	public Matrix invert() {
737 		return invert(this, this);
738 	}
739 
740 	/**
741 	 * Invert the source matrix and put the result in the destination
742 	 * @param src The source matrix
743 	 * @param dest The destination matrix, or null if a new matrix is to be created
744 	 * @return The inverted matrix if successful, null otherwise
745 	 */
invert(Matrix4f src, Matrix4f dest)746 	public static Matrix4f invert(Matrix4f src, Matrix4f dest) {
747 		float determinant = src.determinant();
748 
749 		if (determinant != 0) {
750 			/*
751 			 * m00 m01 m02 m03
752 			 * m10 m11 m12 m13
753 			 * m20 m21 m22 m23
754 			 * m30 m31 m32 m33
755 			 */
756 			if (dest == null)
757 				dest = new Matrix4f();
758 			float determinant_inv = 1f/determinant;
759 
760 			// first row
761 			float t00 =  determinant3x3(src.m11, src.m12, src.m13, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33);
762 			float t01 = -determinant3x3(src.m10, src.m12, src.m13, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33);
763 			float t02 =  determinant3x3(src.m10, src.m11, src.m13, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33);
764 			float t03 = -determinant3x3(src.m10, src.m11, src.m12, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32);
765 			// second row
766 			float t10 = -determinant3x3(src.m01, src.m02, src.m03, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33);
767 			float t11 =  determinant3x3(src.m00, src.m02, src.m03, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33);
768 			float t12 = -determinant3x3(src.m00, src.m01, src.m03, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33);
769 			float t13 =  determinant3x3(src.m00, src.m01, src.m02, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32);
770 			// third row
771 			float t20 =  determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m31, src.m32, src.m33);
772 			float t21 = -determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m30, src.m32, src.m33);
773 			float t22 =  determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m30, src.m31, src.m33);
774 			float t23 = -determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m30, src.m31, src.m32);
775 			// fourth row
776 			float t30 = -determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m21, src.m22, src.m23);
777 			float t31 =  determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m20, src.m22, src.m23);
778 			float t32 = -determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m20, src.m21, src.m23);
779 			float t33 =  determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m20, src.m21, src.m22);
780 
781 			// transpose and divide by the determinant
782 			dest.m00 = t00*determinant_inv;
783 			dest.m11 = t11*determinant_inv;
784 			dest.m22 = t22*determinant_inv;
785 			dest.m33 = t33*determinant_inv;
786 			dest.m01 = t10*determinant_inv;
787 			dest.m10 = t01*determinant_inv;
788 			dest.m20 = t02*determinant_inv;
789 			dest.m02 = t20*determinant_inv;
790 			dest.m12 = t21*determinant_inv;
791 			dest.m21 = t12*determinant_inv;
792 			dest.m03 = t30*determinant_inv;
793 			dest.m30 = t03*determinant_inv;
794 			dest.m13 = t31*determinant_inv;
795 			dest.m31 = t13*determinant_inv;
796 			dest.m32 = t23*determinant_inv;
797 			dest.m23 = t32*determinant_inv;
798 			return dest;
799 		} else
800 			return null;
801 	}
802 
803 	/**
804 	 * Negate this matrix
805 	 * @return this
806 	 */
negate()807 	public Matrix negate() {
808 		return negate(this);
809 	}
810 
811 	/**
812 	 * Negate this matrix and place the result in a destination matrix.
813 	 * @param dest The destination matrix, or null if a new matrix is to be created
814 	 * @return the negated matrix
815 	 */
negate(Matrix4f dest)816 	public Matrix4f negate(Matrix4f dest) {
817 		return negate(this, dest);
818 	}
819 
820 	/**
821 	 * Negate this matrix and place the result in a destination matrix.
822 	 * @param src The source matrix
823 	 * @param dest The destination matrix, or null if a new matrix is to be created
824 	 * @return The negated matrix
825 	 */
negate(Matrix4f src, Matrix4f dest)826 	public static Matrix4f negate(Matrix4f src, Matrix4f dest) {
827 		if (dest == null)
828 			dest = new Matrix4f();
829 
830 		dest.m00 = -src.m00;
831 		dest.m01 = -src.m01;
832 		dest.m02 = -src.m02;
833 		dest.m03 = -src.m03;
834 		dest.m10 = -src.m10;
835 		dest.m11 = -src.m11;
836 		dest.m12 = -src.m12;
837 		dest.m13 = -src.m13;
838 		dest.m20 = -src.m20;
839 		dest.m21 = -src.m21;
840 		dest.m22 = -src.m22;
841 		dest.m23 = -src.m23;
842 		dest.m30 = -src.m30;
843 		dest.m31 = -src.m31;
844 		dest.m32 = -src.m32;
845 		dest.m33 = -src.m33;
846 
847 		return dest;
848 	}
849 }
850