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  *
39  * Holds a 3x3 matrix.
40  *
41  * @author cix_foo <cix_foo@users.sourceforge.net>
42  * @version $Revision$
43  * $Id$
44  */
45 
46 public class Matrix3f extends Matrix implements Serializable {
47 
48 	private static final long serialVersionUID = 1L;
49 
50 	public float m00,
51 		m01,
52 		m02,
53 		m10,
54 		m11,
55 		m12,
56 		m20,
57 		m21,
58 		m22;
59 
60 	/**
61 	 * Constructor for Matrix3f. Matrix is initialised to the identity.
62 	 */
Matrix3f()63 	public Matrix3f() {
64 		super();
65 		setIdentity();
66 	}
67 
68 	/**
69 	 * Load from another matrix
70 	 * @param src The source matrix
71 	 * @return this
72 	 */
load(Matrix3f src)73 	public Matrix3f load(Matrix3f src) {
74 		return load(src, this);
75 	}
76 
77 	/**
78 	 * Copy source matrix to destination matrix
79 	 * @param src The source matrix
80 	 * @param dest The destination matrix, or null of a new matrix is to be created
81 	 * @return The copied matrix
82 	 */
load(Matrix3f src, Matrix3f dest)83 	public static Matrix3f load(Matrix3f src, Matrix3f dest) {
84 		if (dest == null)
85 			dest = new Matrix3f();
86 
87 		dest.m00 = src.m00;
88 		dest.m10 = src.m10;
89 		dest.m20 = src.m20;
90 		dest.m01 = src.m01;
91 		dest.m11 = src.m11;
92 		dest.m21 = src.m21;
93 		dest.m02 = src.m02;
94 		dest.m12 = src.m12;
95 		dest.m22 = src.m22;
96 
97 		return dest;
98 	}
99 
100 	/**
101 	 * Load from a float buffer. The buffer stores the matrix in column major
102 	 * (OpenGL) order.
103 	 *
104 	 * @param buf A float buffer to read from
105 	 * @return this
106 	 */
load(FloatBuffer buf)107 	public Matrix load(FloatBuffer buf) {
108 
109 		m00 = buf.get();
110 		m01 = buf.get();
111 		m02 = buf.get();
112 		m10 = buf.get();
113 		m11 = buf.get();
114 		m12 = buf.get();
115 		m20 = buf.get();
116 		m21 = buf.get();
117 		m22 = buf.get();
118 
119 		return this;
120 	}
121 
122 	/**
123 	 * Load from a float buffer. The buffer stores the matrix in row major
124 	 * (maths) order.
125 	 *
126 	 * @param buf A float buffer to read from
127 	 * @return this
128 	 */
loadTranspose(FloatBuffer buf)129 	public Matrix loadTranspose(FloatBuffer buf) {
130 
131 		m00 = buf.get();
132 		m10 = buf.get();
133 		m20 = buf.get();
134 		m01 = buf.get();
135 		m11 = buf.get();
136 		m21 = buf.get();
137 		m02 = buf.get();
138 		m12 = buf.get();
139 		m22 = buf.get();
140 
141 		return this;
142 	}
143 
144 	/**
145 	 * Store this matrix in a float buffer. The matrix is stored in column
146 	 * major (openGL) order.
147 	 * @param buf The buffer to store this matrix in
148 	 */
store(FloatBuffer buf)149 	public Matrix store(FloatBuffer buf) {
150 		buf.put(m00);
151 		buf.put(m01);
152 		buf.put(m02);
153 		buf.put(m10);
154 		buf.put(m11);
155 		buf.put(m12);
156 		buf.put(m20);
157 		buf.put(m21);
158 		buf.put(m22);
159 		return this;
160 	}
161 
162 	/**
163 	 * Store this matrix in a float buffer. The matrix is stored in row
164 	 * major (maths) order.
165 	 * @param buf The buffer to store this matrix in
166 	 */
storeTranspose(FloatBuffer buf)167 	public Matrix storeTranspose(FloatBuffer buf) {
168 		buf.put(m00);
169 		buf.put(m10);
170 		buf.put(m20);
171 		buf.put(m01);
172 		buf.put(m11);
173 		buf.put(m21);
174 		buf.put(m02);
175 		buf.put(m12);
176 		buf.put(m22);
177 		return this;
178 	}
179 
180 	/**
181 	 * Add two matrices together and place the result in a third matrix.
182 	 * @param left The left source matrix
183 	 * @param right The right source matrix
184 	 * @param dest The destination matrix, or null if a new one is to be created
185 	 * @return the destination matrix
186 	 */
add(Matrix3f left, Matrix3f right, Matrix3f dest)187 	public static Matrix3f add(Matrix3f left, Matrix3f right, Matrix3f dest) {
188 		if (dest == null)
189 			dest = new Matrix3f();
190 
191 		dest.m00 = left.m00 + right.m00;
192 		dest.m01 = left.m01 + right.m01;
193 		dest.m02 = left.m02 + right.m02;
194 		dest.m10 = left.m10 + right.m10;
195 		dest.m11 = left.m11 + right.m11;
196 		dest.m12 = left.m12 + right.m12;
197 		dest.m20 = left.m20 + right.m20;
198 		dest.m21 = left.m21 + right.m21;
199 		dest.m22 = left.m22 + right.m22;
200 
201 		return dest;
202 	}
203 
204 	/**
205 	 * Subtract the right matrix from the left and place the result in a third matrix.
206 	 * @param left The left source matrix
207 	 * @param right The right source matrix
208 	 * @param dest The destination matrix, or null if a new one is to be created
209 	 * @return the destination matrix
210 	 */
sub(Matrix3f left, Matrix3f right, Matrix3f dest)211 	public static Matrix3f sub(Matrix3f left, Matrix3f right, Matrix3f dest) {
212 		if (dest == null)
213 			dest = new Matrix3f();
214 
215 		dest.m00 = left.m00 - right.m00;
216 		dest.m01 = left.m01 - right.m01;
217 		dest.m02 = left.m02 - right.m02;
218 		dest.m10 = left.m10 - right.m10;
219 		dest.m11 = left.m11 - right.m11;
220 		dest.m12 = left.m12 - right.m12;
221 		dest.m20 = left.m20 - right.m20;
222 		dest.m21 = left.m21 - right.m21;
223 		dest.m22 = left.m22 - right.m22;
224 
225 		return dest;
226 	}
227 
228 	/**
229 	 * Multiply the right matrix by the left and place the result in a third matrix.
230 	 * @param left The left source matrix
231 	 * @param right The right source matrix
232 	 * @param dest The destination matrix, or null if a new one is to be created
233 	 * @return the destination matrix
234 	 */
mul(Matrix3f left, Matrix3f right, Matrix3f dest)235 	public static Matrix3f mul(Matrix3f left, Matrix3f right, Matrix3f dest) {
236 		if (dest == null)
237 			dest = new Matrix3f();
238 
239 		float m00 =
240 			left.m00 * right.m00 + left.m10 * right.m01 + left.m20 * right.m02;
241 		float m01 =
242 			left.m01 * right.m00 + left.m11 * right.m01 + left.m21 * right.m02;
243 		float m02 =
244 			left.m02 * right.m00 + left.m12 * right.m01 + left.m22 * right.m02;
245 		float m10 =
246 			left.m00 * right.m10 + left.m10 * right.m11 + left.m20 * right.m12;
247 		float m11 =
248 			left.m01 * right.m10 + left.m11 * right.m11 + left.m21 * right.m12;
249 		float m12 =
250 			left.m02 * right.m10 + left.m12 * right.m11 + left.m22 * right.m12;
251 		float m20 =
252 			left.m00 * right.m20 + left.m10 * right.m21 + left.m20 * right.m22;
253 		float m21 =
254 			left.m01 * right.m20 + left.m11 * right.m21 + left.m21 * right.m22;
255 		float m22 =
256 			left.m02 * right.m20 + left.m12 * right.m21 + left.m22 * right.m22;
257 
258 		dest.m00 = m00;
259 		dest.m01 = m01;
260 		dest.m02 = m02;
261 		dest.m10 = m10;
262 		dest.m11 = m11;
263 		dest.m12 = m12;
264 		dest.m20 = m20;
265 		dest.m21 = m21;
266 		dest.m22 = m22;
267 
268 		return dest;
269 	}
270 
271 	/**
272 	 * Transform a Vector by a matrix and return the result in a destination
273 	 * vector.
274 	 * @param left The left matrix
275 	 * @param right The right vector
276 	 * @param dest The destination vector, or null if a new one is to be created
277 	 * @return the destination vector
278 	 */
transform(Matrix3f left, Vector3f right, Vector3f dest)279 	public static Vector3f transform(Matrix3f left, Vector3f right, Vector3f dest) {
280 		if (dest == null)
281 			dest = new Vector3f();
282 
283 		float x = left.m00 * right.x + left.m10 * right.y + left.m20 * right.z;
284 		float y = left.m01 * right.x + left.m11 * right.y + left.m21 * right.z;
285 		float z = left.m02 * right.x + left.m12 * right.y + left.m22 * right.z;
286 
287 		dest.x = x;
288 		dest.y = y;
289 		dest.z = z;
290 
291 		return dest;
292 	}
293 
294 	/**
295 	 * Transpose this matrix
296 	 * @return this
297 	 */
transpose()298 	public Matrix transpose() {
299 		return transpose(this, this);
300 	}
301 
302 	/**
303 	 * Transpose this matrix and place the result in another matrix
304 	 * @param dest The destination matrix or null if a new matrix is to be created
305 	 * @return the transposed matrix
306 	 */
transpose(Matrix3f dest)307 	public Matrix3f transpose(Matrix3f dest) {
308 		return transpose(this, dest);
309 	}
310 
311 	/**
312 	 * Transpose the source matrix and place the result into the destination matrix
313 	 * @param src The source matrix to be transposed
314 	 * @param dest The destination matrix or null if a new matrix is to be created
315 	 * @return the transposed matrix
316 	 */
transpose(Matrix3f src, Matrix3f dest)317 	public static Matrix3f transpose(Matrix3f src, Matrix3f dest) {
318 		if (dest == null)
319 		   dest = new Matrix3f();
320 		float m00 = src.m00;
321 		float m01 = src.m10;
322 		float m02 = src.m20;
323 		float m10 = src.m01;
324 		float m11 = src.m11;
325 		float m12 = src.m21;
326 		float m20 = src.m02;
327 		float m21 = src.m12;
328 		float m22 = src.m22;
329 
330 		dest.m00 = m00;
331 		dest.m01 = m01;
332 		dest.m02 = m02;
333 		dest.m10 = m10;
334 		dest.m11 = m11;
335 		dest.m12 = m12;
336 		dest.m20 = m20;
337 		dest.m21 = m21;
338 		dest.m22 = m22;
339 		return dest;
340 	}
341 
342 	/**
343 	 * @return the determinant of the matrix
344 	 */
determinant()345 	public float determinant() {
346 		float f =
347 			m00 * (m11 * m22 - m12 * m21)
348 				+ m01 * (m12 * m20 - m10 * m22)
349 				+ m02 * (m10 * m21 - m11 * m20);
350 		return f;
351 	}
352 
353 	/**
354 	 * Returns a string representation of this matrix
355 	 */
toString()356 	public String toString() {
357 		StringBuilder buf = new StringBuilder();
358 		buf.append(m00).append(' ').append(m10).append(' ').append(m20).append(' ').append('\n');
359 		buf.append(m01).append(' ').append(m11).append(' ').append(m21).append(' ').append('\n');
360 		buf.append(m02).append(' ').append(m12).append(' ').append(m22).append(' ').append('\n');
361 		return buf.toString();
362 	}
363 
364 	/**
365 	 * Invert this matrix
366 	 * @return this if successful, null otherwise
367 	 */
invert()368 	public Matrix invert() {
369 		return invert(this, this);
370 	}
371 
372 	/**
373 	 * Invert the source matrix and put the result into the destination matrix
374 	 * @param src The source matrix to be inverted
375 	 * @param dest The destination matrix, or null if a new one is to be created
376 	 * @return The inverted matrix if successful, null otherwise
377 	 */
invert(Matrix3f src, Matrix3f dest)378 	public static Matrix3f invert(Matrix3f src, Matrix3f dest) {
379 		float determinant = src.determinant();
380 
381 		if (determinant != 0) {
382 			if (dest == null)
383 				dest = new Matrix3f();
384 			 /* do it the ordinary way
385 			  *
386 			  * inv(A) = 1/det(A) * adj(T), where adj(T) = transpose(Conjugate Matrix)
387 			  *
388 			  * m00 m01 m02
389 			  * m10 m11 m12
390 			  * m20 m21 m22
391 			  */
392 			 float determinant_inv = 1f/determinant;
393 
394 			 // get the conjugate matrix
395 			 float t00 = src.m11 * src.m22 - src.m12* src.m21;
396 			 float t01 = - src.m10 * src.m22 + src.m12 * src.m20;
397 			 float t02 = src.m10 * src.m21 - src.m11 * src.m20;
398 			 float t10 = - src.m01 * src.m22 + src.m02 * src.m21;
399 			 float t11 = src.m00 * src.m22 - src.m02 * src.m20;
400 			 float t12 = - src.m00 * src.m21 + src.m01 * src.m20;
401 			 float t20 = src.m01 * src.m12 - src.m02 * src.m11;
402 			 float t21 = -src.m00 * src.m12 + src.m02 * src.m10;
403 			 float t22 = src.m00 * src.m11 - src.m01 * src.m10;
404 
405 			 dest.m00 = t00*determinant_inv;
406 			 dest.m11 = t11*determinant_inv;
407 			 dest.m22 = t22*determinant_inv;
408 			 dest.m01 = t10*determinant_inv;
409 			 dest.m10 = t01*determinant_inv;
410 			 dest.m20 = t02*determinant_inv;
411 			 dest.m02 = t20*determinant_inv;
412 			 dest.m12 = t21*determinant_inv;
413 			 dest.m21 = t12*determinant_inv;
414 			 return dest;
415 		} else
416 			 return null;
417 	}
418 
419 
420 	/**
421 	 * Negate this matrix
422 	 * @return this
423 	 */
negate()424 	public Matrix negate() {
425 		return negate(this);
426 	}
427 
428 	/**
429 	 * Negate this matrix and place the result in a destination matrix.
430 	 * @param dest The destination matrix, or null if a new matrix is to be created
431 	 * @return the negated matrix
432 	 */
negate(Matrix3f dest)433 	public Matrix3f negate(Matrix3f dest) {
434 		return negate(this, dest);
435 	}
436 
437 	/**
438 	 * Negate the source matrix and place the result in the destination matrix.
439 	 * @param src The source matrix
440 	 * @param dest The destination matrix, or null if a new matrix is to be created
441 	 * @return the negated matrix
442 	 */
negate(Matrix3f src, Matrix3f dest)443 	public static Matrix3f negate(Matrix3f src, Matrix3f dest) {
444 		if (dest == null)
445 			dest = new Matrix3f();
446 
447 		dest.m00 = -src.m00;
448 		dest.m01 = -src.m02;
449 		dest.m02 = -src.m01;
450 		dest.m10 = -src.m10;
451 		dest.m11 = -src.m12;
452 		dest.m12 = -src.m11;
453 		dest.m20 = -src.m20;
454 		dest.m21 = -src.m22;
455 		dest.m22 = -src.m21;
456 		return dest;
457 	}
458 
459 	/**
460 	 * Set this matrix to be the identity matrix.
461 	 * @return this
462 	 */
setIdentity()463 	public Matrix setIdentity() {
464 		return setIdentity(this);
465 	}
466 
467 	/**
468 	 * Set the matrix to be the identity matrix.
469 	 * @param m The matrix to be set to the identity
470 	 * @return m
471 	 */
setIdentity(Matrix3f m)472 	public static Matrix3f setIdentity(Matrix3f m) {
473 		m.m00 = 1.0f;
474 		m.m01 = 0.0f;
475 		m.m02 = 0.0f;
476 		m.m10 = 0.0f;
477 		m.m11 = 1.0f;
478 		m.m12 = 0.0f;
479 		m.m20 = 0.0f;
480 		m.m21 = 0.0f;
481 		m.m22 = 1.0f;
482 		return m;
483 	}
484 
485 	/**
486 	 * Set this matrix to 0.
487 	 * @return this
488 	 */
setZero()489 	public Matrix setZero() {
490 		return setZero(this);
491 	}
492 
493 	/**
494 	 * Set the matrix matrix to 0.
495 	 * @param m The matrix to be set to 0
496 	 * @return m
497 	 */
setZero(Matrix3f m)498 	public static Matrix3f setZero(Matrix3f m) {
499 		m.m00 = 0.0f;
500 		m.m01 = 0.0f;
501 		m.m02 = 0.0f;
502 		m.m10 = 0.0f;
503 		m.m11 = 0.0f;
504 		m.m12 = 0.0f;
505 		m.m20 = 0.0f;
506 		m.m21 = 0.0f;
507 		m.m22 = 0.0f;
508 		return m;
509 	}
510 }
511