JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
Matrix4f.java
Go to the documentation of this file.
1/**
2 * Copyright 2014-2023 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.math;
30
31import java.nio.FloatBuffer;
32
33import com.jogamp.math.geom.AABBox;
34import com.jogamp.math.geom.Frustum;
35import com.jogamp.math.geom.Frustum.Plane;
36
37/**
38 * Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
39 * <p>
40 * Implementation covers {@link FloatUtil} matrix functionality, exposed in an object oriented manner.
41 * </p>
42 * <p>
43 * Unlike {@link com.jogamp.math.util.PMVMatrix4f PMVMatrix4f}, this class only represents one single matrix.
44 * </p>
45 * <p>
46 * For array operations the layout is expected in column-major order
47 * matching OpenGL's implementation, illustration:
48 * <pre>
49 Row-Major Column-Major (OpenGL):
50
51 | 0 1 2 tx |
52 | |
53 | 4 5 6 ty |
54 M = | |
55 | 8 9 10 tz |
56 | |
57 | 12 13 14 15 |
58
59 R C R C
60 m[0*4+3] = tx; m[0+4*3] = tx;
61 m[1*4+3] = ty; m[1+4*3] = ty;
62 m[2*4+3] = tz; m[2+4*3] = tz;
63
64 RC (std subscript order) RC (std subscript order)
65 m03 = tx; m03 = tx;
66 m13 = ty; m13 = ty;
67 m23 = tz; m23 = tz;
68
69 * </pre>
70 * </p>
71 * <p>
72 * <ul>
73 * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li>
74 * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li>
75 * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li>
76 * </ul>
77 * </p>
78 * <p>
79 * Implementation utilizes unrolling of small vertices and matrices wherever possible
80 * while trying to access memory in a linear fashion for performance reasons, see:
81 * <ul>
82 * <li><a href="https://lessthanoptimal.github.io/Java-Matrix-Benchmark/">java-matrix-benchmark</a></li>
83 * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li>
84 * </ul>
85 * </p>
86 * @see com.jogamp.math.util.PMVMatrix4f
87 * @see FloatUtil
88 */
89public final class Matrix4f {
90
91 /**
92 * Creates a new identity matrix.
93 */
94 public Matrix4f() {
95 m00 = m11 = m22 = m33 = 1.0f;
96 // remaining fields have default init to zero
97 }
98
99 /**
100 * Creates a new matrix copying the values of the given {@code src} matrix.
101 */
102 public Matrix4f(final Matrix4f src) {
103 load(src);
104 }
105
106 /**
107 * Creates a new matrix based on given float[4*4] column major order.
108 * @param m 4x4 matrix in column-major order
109 */
110 public Matrix4f(final float[] m) {
111 load(m);
112 }
113
114 /**
115 * Creates a new matrix based on given float[4*4] column major order.
116 * @param m 4x4 matrix in column-major order
117 * @param m_off offset for matrix {@code m}
118 */
119 public Matrix4f(final float[] m, final int m_off) {
120 load(m, m_off);
121 }
122
123 /**
124 * Creates a new matrix based on given {@link FloatBuffer} 4x4 column major order.
125 * @param m 4x4 matrix in column-major order
126 */
127 public Matrix4f(final FloatBuffer m) {
128 load(m);
129 }
130
131 //
132 // Write to Matrix via set(..) or load(..)
133 //
134
135 /** Sets the {@code i}th component with float {@code v} 0 <= i < 16 */
136 public void set(final int i, final float v) {
137 switch (i) {
138 case 0+4*0: m00 = v; break;
139 case 1+4*0: m10 = v; break;
140 case 2+4*0: m20 = v; break;
141 case 3+4*0: m30 = v; break;
142
143 case 0+4*1: m01 = v; break;
144 case 1+4*1: m11 = v; break;
145 case 2+4*1: m21 = v; break;
146 case 3+4*1: m31 = v; break;
147
148 case 0+4*2: m02 = v; break;
149 case 1+4*2: m12 = v; break;
150 case 2+4*2: m22 = v; break;
151 case 3+4*2: m32 = v; break;
152
153 case 0+4*3: m03 = v; break;
154 case 1+4*3: m13 = v; break;
155 case 2+4*3: m23 = v; break;
156 case 3+4*3: m33 = v; break;
157 default: throw new IndexOutOfBoundsException();
158 }
159 }
160
161 /**
162 * Set this matrix to identity.
163 * <pre>
164 Translation matrix (Column Order):
165 1 0 0 0
166 0 1 0 0
167 0 0 1 0
168 0 0 0 1
169 * </pre>
170 * @return this matrix for chaining
171 */
172 public final Matrix4f loadIdentity() {
173 m00 = m11 = m22 = m33 = 1.0f;
174 m01 = m02 = m03 =
175 m10 = m12 = m13 =
176 m20 = m21 = m23 =
177 m30 = m31 = m32 = 0.0f;
178 return this;
179 }
180
181 /**
182 * Load the values of the given matrix {@code src} to this matrix.
183 * @param src the source values
184 * @return this matrix for chaining
185 */
186 public Matrix4f load(final Matrix4f src) {
187 m00 = src.m00; m10 = src.m10; m20 = src.m20; m30 = src.m30;
188 m01 = src.m01; m11 = src.m11; m21 = src.m21; m31 = src.m31;
189 m02 = src.m02; m12 = src.m12; m22 = src.m22; m32 = src.m32;
190 m03 = src.m03; m13 = src.m13; m23 = src.m23; m33 = src.m33;
191 return this;
192 }
193
194 /**
195 * Load the values of the given matrix {@code src} to this matrix.
196 * @param src 4x4 matrix float[16] in column-major order
197 * @return this matrix for chaining
198 */
199 public Matrix4f load(final float[] src) {
200 m00 = src[0+0*4]; // column 0
201 m10 = src[1+0*4];
202 m20 = src[2+0*4];
203 m30 = src[3+0*4];
204 m01 = src[0+1*4]; // column 1
205 m11 = src[1+1*4];
206 m21 = src[2+1*4];
207 m31 = src[3+1*4];
208 m02 = src[0+2*4]; // column 2
209 m12 = src[1+2*4];
210 m22 = src[2+2*4];
211 m32 = src[3+2*4];
212 m03 = src[0+3*4]; // column 3
213 m13 = src[1+3*4];
214 m23 = src[2+3*4];
215 m33 = src[3+3*4];
216 return this;
217 }
218
219 /**
220 * Load the values of the given matrix {@code src} to this matrix.
221 * @param src 4x4 matrix float[16] in column-major order
222 * @param src_off offset for matrix {@code src}
223 * @return this matrix for chaining
224 */
225 public Matrix4f load(final float[] src, final int src_off) {
226 m00 = src[src_off+0+0*4];
227 m10 = src[src_off+1+0*4];
228 m20 = src[src_off+2+0*4];
229 m30 = src[src_off+3+0*4];
230 m01 = src[src_off+0+1*4];
231 m11 = src[src_off+1+1*4];
232 m21 = src[src_off+2+1*4];
233 m31 = src[src_off+3+1*4];
234 m02 = src[src_off+0+2*4];
235 m12 = src[src_off+1+2*4];
236 m22 = src[src_off+2+2*4];
237 m32 = src[src_off+3+2*4];
238 m03 = src[src_off+0+3*4];
239 m13 = src[src_off+1+3*4];
240 m23 = src[src_off+2+3*4];
241 m33 = src[src_off+3+3*4];
242 return this;
243 }
244
245 /**
246 * Load the values of the given matrix {@code src} to this matrix.
247 * <p>
248 * Implementation uses relative {@link FloatBuffer#get()},
249 * hence caller may want to issue {@link FloatBuffer#reset()} thereafter.
250 * </p>
251 * @param src 4x4 matrix {@link FloatBuffer} in column-major order
252 * @return this matrix for chaining
253 */
254 public Matrix4f load(final FloatBuffer src) {
255 m00 = src.get();
256 m10 = src.get();
257 m20 = src.get();
258 m30 = src.get();
259 m01 = src.get();
260 m11 = src.get();
261 m21 = src.get();
262 m31 = src.get();
263 m02 = src.get();
264 m12 = src.get();
265 m22 = src.get();
266 m32 = src.get();
267 m03 = src.get();
268 m13 = src.get();
269 m23 = src.get();
270 m33 = src.get();
271 return this;
272 }
273
274 //
275 // Read out Matrix via get(..)
276 //
277
278 /** Gets the {@code i}th component, 0 <= i < 16 */
279 public float get(final int i) {
280 switch (i) {
281 case 0+4*0: return m00;
282 case 1+4*0: return m10;
283 case 2+4*0: return m20;
284 case 3+4*0: return m30;
285
286 case 0+4*1: return m01;
287 case 1+4*1: return m11;
288 case 2+4*1: return m21;
289 case 3+4*1: return m31;
290
291 case 0+4*2: return m02;
292 case 1+4*2: return m12;
293 case 2+4*2: return m22;
294 case 3+4*2: return m32;
295
296 case 0+4*3: return m03;
297 case 1+4*3: return m13;
298 case 2+4*3: return m23;
299 case 3+4*3: return m33;
300
301 default: throw new IndexOutOfBoundsException();
302 }
303 }
304
305 /**
306 * Get the named column of the given column-major matrix to v_out.
307 * @param column named column to copy
308 * @param v_out the column-vector storage
309 * @return given result vector <i>v_out</i> for chaining
310 */
311 public Vec4f getColumn(final int column, final Vec4f v_out) {
312 v_out.set( get(0+column*4),
313 get(1+column*4),
314 get(2+column*4),
315 get(3+column*4) );
316 return v_out;
317 }
318
319 /**
320 * Get the named column of the given column-major matrix to v_out.
321 * @param column named column to copy
322 * @param v_out the column-vector storage
323 * @return given result vector <i>v_out</i> for chaining
324 */
325 public Vec3f getColumn(final int column, final Vec3f v_out) {
326 v_out.set( get(0+column*4),
327 get(1+column*4),
328 get(2+column*4) );
329 return v_out;
330 }
331
332 /**
333 * Get the named row of the given column-major matrix to v_out.
334 * @param row named row to copy
335 * @param v_out the row-vector storage
336 * @return given result vector <i>v_out</i> for chaining
337 */
338 public Vec4f getRow(final int row, final Vec4f v_out) {
339 v_out.set( get(row+0*4),
340 get(row+1*4),
341 get(row+2*4),
342 get(row+3*4) );
343 return v_out;
344 }
345
346 /**
347 * Get the named row of the given column-major matrix to v_out.
348 * @param row named row to copy
349 * @param v_out the row-vector storage
350 * @return given result vector <i>v_out</i> for chaining
351 */
352 public Vec3f getRow(final int row, final Vec3f v_out) {
353 v_out.set( get(row+0*4),
354 get(row+1*4),
355 get(row+2*4) );
356 return v_out;
357 }
358
359 /**
360 * Get this matrix into the given float[16] array at {@code dst_off} in column major order.
361 *
362 * @param dst float[16] array storage in column major order
363 * @param dst_off offset
364 * @return {@code dst} for chaining
365 */
366 public float[] get(final float[] dst, final int dst_off) {
367 dst[dst_off+0+0*4] = m00;
368 dst[dst_off+1+0*4] = m10;
369 dst[dst_off+2+0*4] = m20;
370 dst[dst_off+3+0*4] = m30;
371 dst[dst_off+0+1*4] = m01;
372 dst[dst_off+1+1*4] = m11;
373 dst[dst_off+2+1*4] = m21;
374 dst[dst_off+3+1*4] = m31;
375 dst[dst_off+0+2*4] = m02;
376 dst[dst_off+1+2*4] = m12;
377 dst[dst_off+2+2*4] = m22;
378 dst[dst_off+3+2*4] = m32;
379 dst[dst_off+0+3*4] = m03;
380 dst[dst_off+1+3*4] = m13;
381 dst[dst_off+2+3*4] = m23;
382 dst[dst_off+3+3*4] = m33;
383 return dst;
384 }
385
386 /**
387 * Get this matrix into the given float[16] array in column major order.
388 *
389 * @param dst float[16] array storage in column major order
390 * @return {@code dst} for chaining
391 */
392 public float[] get(final float[] dst) {
393 dst[0+0*4] = m00;
394 dst[1+0*4] = m10;
395 dst[2+0*4] = m20;
396 dst[3+0*4] = m30;
397 dst[0+1*4] = m01;
398 dst[1+1*4] = m11;
399 dst[2+1*4] = m21;
400 dst[3+1*4] = m31;
401 dst[0+2*4] = m02;
402 dst[1+2*4] = m12;
403 dst[2+2*4] = m22;
404 dst[3+2*4] = m32;
405 dst[0+3*4] = m03;
406 dst[1+3*4] = m13;
407 dst[2+3*4] = m23;
408 dst[3+3*4] = m33;
409 return dst;
410 }
411
412 /**
413 * Get this matrix into the given {@link FloatBuffer} in column major order.
414 * <p>
415 * Implementation uses relative {@link FloatBuffer#put(float)},
416 * hence caller may want to issue {@link FloatBuffer#reset()} thereafter.
417 * </p>
418 *
419 * @param dst {@link FloatBuffer} array storage in column major order
420 * @return {@code dst} for chaining
421 */
422 public FloatBuffer get(final FloatBuffer dst) {
423 dst.put( m00 );
424 dst.put( m10 );
425 dst.put( m20 );
426 dst.put( m30 );
427 dst.put( m01 );
428 dst.put( m11 );
429 dst.put( m21 );
430 dst.put( m31 );
431 dst.put( m02 );
432 dst.put( m12 );
433 dst.put( m22 );
434 dst.put( m32 );
435 dst.put( m03 );
436 dst.put( m13 );
437 dst.put( m23 );
438 dst.put( m33 );
439 return dst;
440 }
441
442 //
443 // Basic matrix operations
444 //
445
446 /**
447 * Returns the determinant of this matrix
448 * @return the matrix determinant
449 */
450 public float determinant() {
451 float ret = 0;
452 ret += m00 * ( + m11*(m22*m33 - m23*m32) - m12*(m21*m33 - m23*m31) + m13*(m21*m32 - m22*m31));
453 ret -= m01 * ( + m10*(m22*m33 - m23*m32) - m12*(m20*m33 - m23*m30) + m13*(m20*m32 - m22*m30));
454 ret += m02 * ( + m10*(m21*m33 - m23*m31) - m11*(m20*m33 - m23*m30) + m13*(m20*m31 - m21*m30));
455 ret -= m03 * ( + m10*(m21*m32 - m22*m31) - m11*(m20*m32 - m22*m30) + m12*(m20*m31 - m21*m30));
456 return ret;
457 }
458
459 /**
460 * Transpose this matrix.
461 *
462 * @return this matrix for chaining
463 */
464 public final Matrix4f transpose() {
465 float tmp;
466
467 tmp = m10;
468 m10 = m01;
469 m01 = tmp;
470
471 tmp = m20;
472 m20 = m02;
473 m02 = tmp;
474
475 tmp = m30;
476 m30 = m03;
477 m03 = tmp;
478
479 tmp = m21;
480 m21 = m12;
481 m12 = tmp;
482
483 tmp = m31;
484 m31 = m13;
485 m13 = tmp;
486
487 tmp = m32;
488 m32 = m23;
489 m23 = tmp;
490
491 return this;
492 }
493
494 /**
495 * Transpose the given {@code src} matrix into this matrix.
496 *
497 * @param src source 4x4 matrix
498 * @return this matrix (result) for chaining
499 */
500 public final Matrix4f transpose(final Matrix4f src) {
501 if( src == this ) {
502 return transpose();
503 }
504 m00 = src.m00;
505 m10 = src.m01;
506 m20 = src.m02;
507 m30 = src.m03;
508
509 m01 = src.m10;
510 m11 = src.m11;
511 m21 = src.m12;
512 m31 = src.m13;
513
514 m02 = src.m20;
515 m12 = src.m21;
516 m22 = src.m22;
517 m32 = src.m23;
518
519 m03 = src.m30;
520 m13 = src.m31;
521 m23 = src.m32;
522 m33 = src.m33;
523 return this;
524 }
525
526 /**
527 * Invert this matrix.
528 * @return false if this matrix is singular and inversion not possible, otherwise true
529 */
530 public boolean invert() {
531 final float scale;
532 try {
533 scale = mulScale();
534 } catch(final ArithmeticException aex) {
535 return false; // max was 0
536 }
537 final float a00 = m00*scale;
538 final float a10 = m10*scale;
539 final float a20 = m20*scale;
540 final float a30 = m30*scale;
541
542 final float a01 = m01*scale;
543 final float a11 = m11*scale;
544 final float a21 = m21*scale;
545 final float a31 = m31*scale;
546
547 final float a02 = m02*scale;
548 final float a12 = m12*scale;
549 final float a22 = m22*scale;
550 final float a32 = m32*scale;
551
552 final float a03 = m03*scale;
553 final float a13 = m13*scale;
554 final float a23 = m23*scale;
555 final float a33 = m33*scale;
556
557 final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
558 final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30));
559 final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30);
560 final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30));
561
562 final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31));
563 final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30);
564 final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30));
565 final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30);
566
567 final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31);
568 final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30));
569 final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30);
570 final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30));
571
572 final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21));
573 final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20);
574 final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20));
575 final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20);
576
577 final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale;
578 if( 0 == det ) {
579 return false;
580 }
581 final float invdet = 1.0f / det;
582
583 m00 = b00 * invdet;
584 m10 = b01 * invdet;
585 m20 = b02 * invdet;
586 m30 = b03 * invdet;
587
588 m01 = b10 * invdet;
589 m11 = b11 * invdet;
590 m21 = b12 * invdet;
591 m31 = b13 * invdet;
592
593 m02 = b20 * invdet;
594 m12 = b21 * invdet;
595 m22 = b22 * invdet;
596 m32 = b23 * invdet;
597
598 m03 = b30 * invdet;
599 m13 = b31 * invdet;
600 m23 = b32 * invdet;
601 m33 = b33 * invdet;
602 return true;
603 }
604
605 /**
606 * Invert the {@code src} matrix values into this matrix
607 * @param src the source matrix, which values are to be inverted
608 * @return false if {@code src} matrix is singular and inversion not possible, otherwise true
609 */
610 public boolean invert(final Matrix4f src) {
611 final float scale;
612 try {
613 scale = src.mulScale();
614 } catch(final ArithmeticException aex) {
615 return false; // max was 0
616 }
617 final float a00 = src.m00*scale;
618 final float a10 = src.m10*scale;
619 final float a20 = src.m20*scale;
620 final float a30 = src.m30*scale;
621
622 final float a01 = src.m01*scale;
623 final float a11 = src.m11*scale;
624 final float a21 = src.m21*scale;
625 final float a31 = src.m31*scale;
626
627 final float a02 = src.m02*scale;
628 final float a12 = src.m12*scale;
629 final float a22 = src.m22*scale;
630 final float a32 = src.m32*scale;
631
632 final float a03 = src.m03*scale;
633 final float a13 = src.m13*scale;
634 final float a23 = src.m23*scale;
635 final float a33 = src.m33*scale;
636
637 final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
638 final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30));
639 final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30);
640 final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30));
641
642 final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31));
643 final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30);
644 final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30));
645 final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30);
646
647 final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31);
648 final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30));
649 final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30);
650 final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30));
651
652 final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21));
653 final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20);
654 final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20));
655 final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20);
656
657 final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale;
658
659 if( 0 == det ) {
660 return false;
661 }
662 final float invdet = 1.0f / det;
663
664 m00 = b00 * invdet;
665 m10 = b01 * invdet;
666 m20 = b02 * invdet;
667 m30 = b03 * invdet;
668
669 m01 = b10 * invdet;
670 m11 = b11 * invdet;
671 m21 = b12 * invdet;
672 m31 = b13 * invdet;
673
674 m02 = b20 * invdet;
675 m12 = b21 * invdet;
676 m22 = b22 * invdet;
677 m32 = b23 * invdet;
678
679 m03 = b30 * invdet;
680 m13 = b31 * invdet;
681 m23 = b32 * invdet;
682 m33 = b33 * invdet;
683 return true;
684 }
685
686 private final float mulScale() {
687 /**
688 // No Hotspot intrinsic Math.* optimization for at least Math.max(),
689 // hence this chunk is slower.
690 float max = Math.abs(m00);
691
692 max = Math.max(max, Math.abs(m01));
693 max = Math.max(max, Math.abs(m02));
694 ... etc
695 */
696 float a = Math.abs(m00);
697 float max = a;
698 a = Math.abs(m01); if( a > max ) max = a;
699 a = Math.abs(m02); if( a > max ) max = a;
700 a = Math.abs(m03); if( a > max ) max = a;
701
702 a = Math.abs(m10); if( a > max ) max = a;
703 a = Math.abs(m11); if( a > max ) max = a;
704 a = Math.abs(m12); if( a > max ) max = a;
705 a = Math.abs(m13); if( a > max ) max = a;
706
707 a = Math.abs(m20); if( a > max ) max = a;
708 a = Math.abs(m21); if( a > max ) max = a;
709 a = Math.abs(m22); if( a > max ) max = a;
710 a = Math.abs(m23); if( a > max ) max = a;
711
712 a = Math.abs(m30); if( a > max ) max = a;
713 a = Math.abs(m31); if( a > max ) max = a;
714 a = Math.abs(m32); if( a > max ) max = a;
715 a = Math.abs(m33); if( a > max ) max = a;
716
717 return 1.0f/max;
718 }
719
720 /**
721 * Multiply matrix: [this] = [this] x [b]
722 * @param b 4x4 matrix
723 * @return this matrix for chaining
724 * @see #mul(Matrix4f, Matrix4f)
725 */
726 public final Matrix4f mul(final Matrix4f b) {
727 // return mul(new Matrix4f(this), b); // <- roughly half speed
728 float ai0=m00; // row-0, m[0+0*4]
729 float ai1=m01;
730 float ai2=m02;
731 float ai3=m03;
732 m00 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
733 m01 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
734 m02 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
735 m03 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
736
737 ai0=m10; //row-1, m[1+0*4]
738 ai1=m11;
739 ai2=m12;
740 ai3=m13;
741 m10 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
742 m11 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
743 m12 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
744 m13 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
745
746 ai0=m20; // row-2, m[2+0*4]
747 ai1=m21;
748 ai2=m22;
749 ai3=m23;
750 m20 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
751 m21 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
752 m22 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
753 m23 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
754
755 ai0=m30; // row-3, m[3+0*4]
756 ai1=m31;
757 ai2=m32;
758 ai3=m33;
759 m30 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
760 m31 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
761 m32 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
762 m33 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
763 return this;
764 }
765
766 /**
767 * Multiply matrix: [this] = [a] x [b]
768 * @param a 4x4 matrix, can't be this matrix
769 * @param b 4x4 matrix, can't be this matrix
770 * @return this matrix for chaining
771 * @see #mul(Matrix4f)
772 */
773 public final Matrix4f mul(final Matrix4f a, final Matrix4f b) {
774 // row-0, m[0+0*4]
775 m00 = a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20 + a.m03 * b.m30 ;
776 m01 = a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21 + a.m03 * b.m31 ;
777 m02 = a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22 + a.m03 * b.m32 ;
778 m03 = a.m00 * b.m03 + a.m01 * b.m13 + a.m02 * b.m23 + a.m03 * b.m33 ;
779
780 //row-1, m[1+0*4]
781 m10 = a.m10 * b.m00 + a.m11 * b.m10 + a.m12 * b.m20 + a.m13 * b.m30 ;
782 m11 = a.m10 * b.m01 + a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31 ;
783 m12 = a.m10 * b.m02 + a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32 ;
784 m13 = a.m10 * b.m03 + a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33 ;
785
786 // row-2, m[2+0*4]
787 m20 = a.m20 * b.m00 + a.m21 * b.m10 + a.m22 * b.m20 + a.m23 * b.m30 ;
788 m21 = a.m20 * b.m01 + a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31 ;
789 m22 = a.m20 * b.m02 + a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32 ;
790 m23 = a.m20 * b.m03 + a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33 ;
791
792 // row-3, m[3+0*4]
793 m30 = a.m30 * b.m00 + a.m31 * b.m10 + a.m32 * b.m20 + a.m33 * b.m30 ;
794 m31 = a.m30 * b.m01 + a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31 ;
795 m32 = a.m30 * b.m02 + a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32 ;
796 m33 = a.m30 * b.m03 + a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33 ;
797
798 return this;
799 }
800
801 /**
802 * @param v_in 4-component column-vector, can be v_out for in-place transformation
803 * @param v_out this * v_in
804 * @returns v_out for chaining
805 */
806 public final Vec4f mulVec4f(final Vec4f v_in, final Vec4f v_out) {
807 // (one matrix row in column-major order) X (column vector)
808 final float x = v_in.x(), y = v_in.y(), z = v_in.z(), w = v_in.w();
809 v_out.set( x * m00 + y * m01 + z * m02 + w * m03,
810 x * m10 + y * m11 + z * m12 + w * m13,
811 x * m20 + y * m21 + z * m22 + w * m23,
812 x * m30 + y * m31 + z * m32 + w * m33 );
813 return v_out;
814 }
815
816 /**
817 * @param v_inout 4-component column-vector input and output, i.e. in-place transformation
818 * @returns v_inout for chaining
819 */
820 public final Vec4f mulVec4f(final Vec4f v_inout) {
821 // (one matrix row in column-major order) X (column vector)
822 final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z(), w = v_inout.w();
823 v_inout.set( x * m00 + y * m01 + z * m02 + w * m03,
824 x * m10 + y * m11 + z * m12 + w * m13,
825 x * m20 + y * m21 + z * m22 + w * m23,
826 x * m30 + y * m31 + z * m32 + w * m33 );
827 return v_inout;
828 }
829
830 /**
831 * Affine 3f-vector transformation by 4x4 matrix
832 *
833 * 4x4 matrix multiplication with 3-component vector,
834 * using {@code 1} for for {@code v_in.w()} and dropping {@code v_out.w()},
835 * which shall be {@code 1}.
836 *
837 * @param v_in 3-component column-vector {@link Vec3f}, can be v_out for in-place transformation
838 * @param v_out m_in * v_in, 3-component column-vector {@link Vec3f}
839 * @returns v_out for chaining
840 */
841 public final Vec3f mulVec3f(final Vec3f v_in, final Vec3f v_out) {
842 // (one matrix row in column-major order) X (column vector)
843 final float x = v_in.x(), y = v_in.y(), z = v_in.z();
844 v_out.set( x * m00 + y * m01 + z * m02 + 1f * m03,
845 x * m10 + y * m11 + z * m12 + 1f * m13,
846 x * m20 + y * m21 + z * m22 + 1f * m23 );
847 return v_out;
848 }
849
850 /**
851 * Affine 3f-vector transformation by 4x4 matrix
852 *
853 * 4x4 matrix multiplication with 3-component vector,
854 * using {@code 1} for for {@code v_inout.w()} and dropping {@code v_inout.w()},
855 * which shall be {@code 1}.
856 *
857 * @param v_inout 3-component column-vector {@link Vec3f} input and output, i.e. in-place transformation
858 * @returns v_inout for chaining
859 */
860 public final Vec3f mulVec3f(final Vec3f v_inout) {
861 // (one matrix row in column-major order) X (column vector)
862 final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z();
863 v_inout.set( x * m00 + y * m01 + z * m02 + 1f * m03,
864 x * m10 + y * m11 + z * m12 + 1f * m13,
865 x * m20 + y * m21 + z * m22 + 1f * m23 );
866 return v_inout;
867 }
868
869 //
870 // Matrix setTo...(), affine + basic
871 //
872
873 /**
874 * Set this matrix to translation.
875 * <pre>
876 Translation matrix (Column Order):
877 1 0 0 0
878 0 1 0 0
879 0 0 1 0
880 x y z 1
881 * </pre>
882 * @param x x-axis translate
883 * @param y y-axis translate
884 * @param z z-axis translate
885 * @return this matrix for chaining
886 */
887 public final Matrix4f setToTranslation(final float x, final float y, final float z) {
888 m00 = m11 = m22 = m33 = 1.0f;
889 m03 = x;
890 m13 = y;
891 m23 = z;
892 m01 = m02 =
893 m10 = m12 =
894 m20 = m21 =
895 m30 = m31 = m32 = 0.0f;
896 return this;
897 }
898
899 /**
900 * Set this matrix to translation.
901 * <pre>
902 Translation matrix (Column Order):
903 1 0 0 0
904 0 1 0 0
905 0 0 1 0
906 x y z 1
907 * </pre>
908 * @param t translate Vec3f
909 * @return this matrix for chaining
910 */
911 public final Matrix4f setToTranslation(final Vec3f t) {
912 return setToTranslation(t.x(), t.y(), t.z());
913 }
914
915 /**
916 * Set this matrix to scale.
917 * <pre>
918 Scale matrix (Any Order):
919 x 0 0 0
920 0 y 0 0
921 0 0 z 0
922 0 0 0 1
923 * </pre>
924 * @param x x-axis scale
925 * @param y y-axis scale
926 * @param z z-axis scale
927 * @return this matrix for chaining
928 */
929 public final Matrix4f setToScale(final float x, final float y, final float z) {
930 m33 = 1.0f;
931 m00 = x;
932 m11 = y;
933 m22 = z;
934 m01 = m02 = m03 =
935 m10 = m12 = m13 =
936 m20 = m21 = m23 =
937 m30 = m31 = m32 = 0.0f;
938 return this;
939 }
940
941 /**
942 * Set this matrix to scale.
943 * <pre>
944 Scale matrix (Any Order):
945 x 0 0 0
946 0 y 0 0
947 0 0 z 0
948 0 0 0 1
949 * </pre>
950 * @param s scale Vec3f
951 * @return this matrix for chaining
952 */
953 public final Matrix4f setToScale(final Vec3f s) {
954 return setToScale(s.x(), s.y(), s.z());
955 }
956
957 /**
958 * Set this matrix to rotation from the given axis and angle in radians.
959 * <pre>
960 Rotation matrix (Column Order):
961 xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
962 xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
963 xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
964 0 0 0 1
965 * </pre>
966 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
967 * @param ang_rad angle in radians
968 * @param x x of rotation axis
969 * @param y y of rotation axis
970 * @param z z of rotation axis
971 * @return this matrix for chaining
972 */
973 public final Matrix4f setToRotationAxis(final float ang_rad, float x, float y, float z) {
974 final float c = FloatUtil.cos(ang_rad);
975 final float ic= 1.0f - c;
976 final float s = FloatUtil.sin(ang_rad);
977
978 final Vec3f tmp = new Vec3f(x, y, z).normalize();
979 x = tmp.x(); y = tmp.y(); z = tmp.z();
980
981 final float xy = x*y;
982 final float xz = x*z;
983 final float xs = x*s;
984 final float ys = y*s;
985 final float yz = y*z;
986 final float zs = z*s;
987 m00 = x*x*ic+c;
988 m10 = xy*ic+zs;
989 m20 = xz*ic-ys;
990 m30 = 0;
991
992 m01 = xy*ic-zs;
993 m11 = y*y*ic+c;
994 m21 = yz*ic+xs;
995 m31 = 0;
996
997 m02 = xz*ic+ys;
998 m12 = yz*ic-xs;
999 m22 = z*z*ic+c;
1000 m32 = 0;
1001
1002 m03 = 0f;
1003 m13 = 0f;
1004 m23 = 0f;
1005 m33 = 1f;
1006
1007 return this;
1008 }
1009
1010 /**
1011 * Set this matrix to rotation from the given axis and angle in radians.
1012 * <pre>
1013 Rotation matrix (Column Order):
1014 xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
1015 xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
1016 xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
1017 0 0 0 1
1018 * </pre>
1019 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1020 * @param ang_rad angle in radians
1021 * @param axis rotation axis
1022 * @return this matrix for chaining
1023 */
1024 public final Matrix4f setToRotationAxis(final float ang_rad, final Vec3f axis) {
1025 return setToRotationAxis(ang_rad, axis.x(), axis.y(), axis.z());
1026 }
1027
1028 /**
1029 * Set this matrix to rotation from the given Euler rotation angles in radians.
1030 * <p>
1031 * The rotations are applied in the given order:
1032 * <ul>
1033 * <li>y - heading</li>
1034 * <li>z - attitude</li>
1035 * <li>x - bank</li>
1036 * </ul>
1037 * </p>
1038 * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
1039 * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
1040 * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
1041 * @return this matrix for chaining
1042 * <p>
1043 * Implementation does not use Quaternion and hence is exposed to
1044 * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
1045 * consider using {@link #setToRotation(Quaternion)}.
1046 * </p>
1047 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
1048 * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
1049 * @see #setToRotation(Quaternion)
1050 */
1051 public Matrix4f setToRotationEuler(final float bankX, final float headingY, final float attitudeZ) {
1052 // Assuming the angles are in radians.
1053 final float ch = FloatUtil.cos(headingY);
1054 final float sh = FloatUtil.sin(headingY);
1055 final float ca = FloatUtil.cos(attitudeZ);
1056 final float sa = FloatUtil.sin(attitudeZ);
1057 final float cb = FloatUtil.cos(bankX);
1058 final float sb = FloatUtil.sin(bankX);
1059
1060 m00 = ch*ca;
1061 m10 = sa;
1062 m20 = -sh*ca;
1063 m30 = 0;
1064
1065 m01 = sh*sb - ch*sa*cb;
1066 m11 = ca*cb;
1067 m21 = sh*sa*cb + ch*sb;
1068 m31 = 0;
1069
1070 m02 = ch*sa*sb + sh*cb;
1071 m12 = -ca*sb;
1072 m22 = -sh*sa*sb + ch*cb;
1073 m32 = 0;
1074
1075 m03 = 0;
1076 m13 = 0;
1077 m23 = 0;
1078 m33 = 1;
1079
1080 return this;
1081 }
1082
1083 /**
1084 * Set this matrix to rotation from the given Euler rotation angles in radians.
1085 * <p>
1086 * The rotations are applied in the given order:
1087 * <ul>
1088 * <li>y - heading</li>
1089 * <li>z - attitude</li>
1090 * <li>x - bank</li>
1091 * </ul>
1092 * </p>
1093 * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude
1094 * @return this quaternion for chaining.
1095 * <p>
1096 * Implementation does not use Quaternion and hence is exposed to
1097 * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
1098 * consider using {@link #setToRotation(Quaternion)}.
1099 * </p>
1100 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
1101 * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
1102 * @see #setToRotation(Quaternion)
1103 */
1104 public Matrix4f setToRotationEuler(final Vec3f angradXYZ) {
1105 return setToRotationEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z());
1106 }
1107
1108 /**
1109 * Set this matrix to rotation using the given Quaternion.
1110 * <p>
1111 * Implementation Details:
1112 * <ul>
1113 * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
1114 * <li> The fields [m00 .. m22] define the rotation</li>
1115 * </ul>
1116 * </p>
1117 *
1118 * @param q the Quaternion representing the rotation
1119 * @return this matrix for chaining
1120 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
1121 * @see Quaternion#toMatrix(float[])
1122 * @see #getRotation()
1123 */
1124 public final Matrix4f setToRotation(final Quaternion q) {
1125 // pre-multiply scaled-reciprocal-magnitude to reduce multiplications
1126 final float norm = q.magnitudeSquared();
1127 if ( FloatUtil.isZero(norm) ) {
1128 // identity matrix -> srecip = 0f
1129 loadIdentity();
1130 return this;
1131 }
1132 final float srecip;
1133 if ( FloatUtil.isEqual(1f, norm) ) {
1134 srecip = 2f;
1135 } else {
1136 srecip = 2.0f / norm;
1137 }
1138
1139 final float x = q.x();
1140 final float y = q.y();
1141 final float z = q.z();
1142 final float w = q.w();
1143
1144 final float xs = srecip * x;
1145 final float ys = srecip * y;
1146 final float zs = srecip * z;
1147
1148 final float xx = x * xs;
1149 final float xy = x * ys;
1150 final float xz = x * zs;
1151 final float xw = xs * w;
1152 final float yy = y * ys;
1153 final float yz = y * zs;
1154 final float yw = ys * w;
1155 final float zz = z * zs;
1156 final float zw = zs * w;
1157
1158 m00 = 1f - ( yy + zz );
1159 m01 = ( xy - zw );
1160 m02 = ( xz + yw );
1161 m03 = 0f;
1162
1163 m10 = ( xy + zw );
1164 m11 = 1f - ( xx + zz );
1165 m12 = ( yz - xw );
1166 m13 = 0f;
1167
1168 m20 = ( xz - yw );
1169 m21 = ( yz + xw );
1170 m22 = 1f - ( xx + yy );
1171 m23 = 0f;
1172
1173 m30 = m31 = m32 = 0f;
1174 m33 = 1f;
1175 return this;
1176 }
1177
1178 /**
1179 * Returns the rotation [m00 .. m22] fields converted to a Quaternion.
1180 * @param res resulting Quaternion
1181 * @return the resulting Quaternion for chaining.
1182 * @see Quaternion#setFromMat(float, float, float, float, float, float, float, float, float)
1183 * @see #setToRotation(Quaternion)
1184 */
1185 public final Quaternion getRotation(final Quaternion res) {
1186 return res.setFromMat(m00, m01, m02, m10, m11, m12, m20, m21, m22);
1187 }
1188
1189 /**
1190 * Set this matrix to orthogonal projection.
1191 * <pre>
1192 Ortho matrix (Column Order):
1193 2/dx 0 0 0
1194 0 2/dy 0 0
1195 0 0 2/dz 0
1196 tx ty tz 1
1197 * </pre>
1198 * @param left
1199 * @param right
1200 * @param bottom
1201 * @param top
1202 * @param zNear
1203 * @param zFar
1204 * @return this matrix for chaining
1205 */
1206 public Matrix4f setToOrtho(final float left, final float right,
1207 final float bottom, final float top,
1208 final float zNear, final float zFar) {
1209 {
1210 // m00 = m11 = m22 = m33 = 1f;
1211 m10 = m20 = m30 = 0f;
1212 m01 = m21 = m31 = 0f;
1213 m02 = m12 = m32 = 0f;
1214 // m03 = m13 = m23 = 0f;
1215 }
1216 final float dx=right-left;
1217 final float dy=top-bottom;
1218 final float dz=zFar-zNear;
1219 final float tx=-1.0f*(right+left)/dx;
1220 final float ty=-1.0f*(top+bottom)/dy;
1221 final float tz=-1.0f*(zFar+zNear)/dz;
1222
1223 m00 = 2.0f/dx;
1224 m11 = 2.0f/dy;
1225 m22 = -2.0f/dz;
1226
1227 m03 = tx;
1228 m13 = ty;
1229 m23 = tz;
1230 m33 = 1f;
1231
1232 return this;
1233 }
1234
1235 /**
1236 * Set this matrix to frustum.
1237 * <pre>
1238 Frustum matrix (Column Order):
1239 2*zNear/dx 0 0 0
1240 0 2*zNear/dy 0 0
1241 A B C -1
1242 0 0 D 0
1243 * </pre>
1244 * @param left
1245 * @param right
1246 * @param bottom
1247 * @param top
1248 * @param zNear
1249 * @param zFar
1250 * @return this matrix for chaining
1251 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1252 * or {@code left == right}, or {@code bottom == top}.
1253 */
1254 public Matrix4f setToFrustum(final float left, final float right,
1255 final float bottom, final float top,
1256 final float zNear, final float zFar) throws IllegalArgumentException {
1257 if( zNear <= 0.0f || zFar <= zNear ) {
1258 throw new IllegalArgumentException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar);
1259 }
1260 if( left == right || top == bottom) {
1261 throw new IllegalArgumentException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
1262 }
1263 {
1264 // m00 = m11 = m22 = m33 = 1f;
1265 m10 = m20 = m30 = 0f;
1266 m01 = m21 = m31 = 0f;
1267 m03 = m13 = 0f;
1268 }
1269 final float zNear2 = 2.0f*zNear;
1270 final float dx=right-left;
1271 final float dy=top-bottom;
1272 final float dz=zFar-zNear;
1273 final float A=(right+left)/dx;
1274 final float B=(top+bottom)/dy;
1275 final float C=-1.0f*(zFar+zNear)/dz;
1276 final float D=-2.0f*(zFar*zNear)/dz;
1277
1278 m00 = zNear2/dx;
1279 m11 = zNear2/dy;
1280
1281 m02 = A;
1282 m12 = B;
1283 m22 = C;
1284 m32 = -1.0f;
1285
1286 m23 = D;
1287 m33 = 0f;
1288
1289 return this;
1290 }
1291
1292 /**
1293 * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection.
1294 *
1295 * @param fovy_rad angle in radians
1296 * @param aspect aspect ratio width / height
1297 * @param zNear
1298 * @param zFar
1299 * @return this matrix for chaining
1300 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1301 * @see #setToFrustum(float, float, float, float, float, float)
1302 */
1303 public Matrix4f setToPerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) throws IllegalArgumentException {
1304 final float top = FloatUtil.tan(fovy_rad/2f) * zNear; // use tangent of half-fov !
1305 final float bottom = -1.0f * top; // -1f * fovhvTan.top * zNear
1306 final float left = aspect * bottom; // aspect * -1f * fovhvTan.top * zNear
1307 final float right = aspect * top; // aspect * fovhvTan.top * zNear
1308 return setToFrustum(left, right, bottom, top, zNear, zFar);
1309 }
1310
1311 /**
1312 * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection.
1313 *
1314 * @param fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent
1315 * @param zNear
1316 * @param zFar
1317 * @return this matrix for chaining
1318 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1319 * @see #setToFrustum(float, float, float, float, float, float)
1320 * @see Frustum#updateByFovDesc(Matrix4f, com.jogamp.math.geom.Frustum.FovDesc)
1321 */
1322 public Matrix4f setToPerspective(final FovHVHalves fovhv, final float zNear, final float zFar) throws IllegalArgumentException {
1323 final FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov !
1324 final float top = fovhvTan.top * zNear;
1325 final float bottom = -1.0f * fovhvTan.bottom * zNear;
1326 final float left = -1.0f * fovhvTan.left * zNear;
1327 final float right = fovhvTan.right * zNear;
1328 return setToFrustum(left, right, bottom, top, zNear, zFar);
1329 }
1330
1331 /**
1332 * Calculate the frustum planes in world coordinates
1333 * using this column major order matrix, usually a projection (P) or premultiplied P*MV matrix.
1334 * <p>
1335 * Frustum plane's normals will point to the inside of the viewing frustum,
1336 * as required by the {@link Frustum} class.
1337 * </p>
1338 * @see Frustum#setFromMat(Matrix4f)
1339 */
1340 public Frustum getFrustum(final Frustum frustum) {
1341 // Left: a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14 - [1..4] column-major
1342 // Left: a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03 - [0..3] column-major
1343 {
1344 final Frustum.Plane p = frustum.getPlanes()[Frustum.LEFT];
1345 p.n.set( m30 + m00,
1346 m31 + m01,
1347 m32 + m02 );
1348 p.d = m33 + m03;
1349 }
1350
1351 // Right: a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14 - [1..4] column-major
1352 // Right: a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03 - [0..3] column-major
1353 {
1354 final Frustum.Plane p = frustum.getPlanes()[Frustum.RIGHT];
1355 p.n.set( m30 - m00,
1356 m31 - m01,
1357 m32 - m02 );
1358 p.d = m33 - m03;
1359 }
1360
1361 // Bottom: a = m41m21, b = m42m22, c = m43m23, d = m44m24 - [1..4] column-major
1362 // Bottom: a = m30m10, b = m31m11, c = m32m12, d = m33m13 - [0..3] column-major
1363 {
1364 final Frustum.Plane p = frustum.getPlanes()[Frustum.BOTTOM];
1365 p.n.set( m30 + m10,
1366 m31 + m11,
1367 m32 + m12 );
1368 p.d = m33 + m13;
1369 }
1370
1371 // Top: a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24 - [1..4] column-major
1372 // Top: a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13 - [0..3] column-major
1373 {
1374 final Frustum.Plane p = frustum.getPlanes()[Frustum.TOP];
1375 p.n.set( m30 - m10,
1376 m31 - m11,
1377 m32 - m12 );
1378 p.d = m33 - m13;
1379 }
1380
1381 // Near: a = m41m31, b = m42m32, c = m43m33, d = m44m34 - [1..4] column-major
1382 // Near: a = m30m20, b = m31m21, c = m32m22, d = m33m23 - [0..3] column-major
1383 {
1384 final Frustum.Plane p = frustum.getPlanes()[Frustum.NEAR];
1385 p.n.set( m30 + m20,
1386 m31 + m21,
1387 m32 + m22 );
1388 p.d = m33 + m23;
1389 }
1390
1391 // Far: a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34 - [1..4] column-major
1392 // Far: a = m30 - m20, b = m31 - m21, c = m32m22, d = m33m23 - [0..3] column-major
1393 {
1394 final Frustum.Plane p = frustum.getPlanes()[Frustum.FAR];
1395 p.n.set( m30 - m20,
1396 m31 - m21,
1397 m32 - m22 );
1398 p.d = m33 - m23;
1399 }
1400
1401 // Normalize all planes
1402 for (int i = 0; i < 6; ++i) {
1403 final Plane p = frustum.getPlanes()[i];
1404 final Vec3f p_n = p.n;
1405 final float invLen = 1f / p_n.length();
1406 p_n.scale(invLen);
1407 p.d *= invLen;
1408 }
1409 return frustum;
1410 }
1411
1412 /**
1413 * Set this matrix to the <i>look-at</i> matrix based on given parameters.
1414 * <p>
1415 * Consist out of two matrix multiplications:
1416 * <pre>
1417 * <b>R</b> = <b>L</b> x <b>T</b>,
1418 * with <b>L</b> for <i>look-at</i> matrix and
1419 * <b>T</b> for eye translation.
1420 *
1421 * Result <b>R</b> can be utilized for <i>projection or modelview</i> multiplication, i.e.
1422 * <b>M</b> = <b>M</b> x <b>R</b>,
1423 * with <b>M</b> being the <i>projection or modelview</i> matrix.
1424 * </pre>
1425 * </p>
1426 * @param eye 3 component eye vector
1427 * @param center 3 component center vector
1428 * @param up 3 component up vector
1429 * @param tmp temporary Matrix4f used for multiplication
1430 * @return this matrix for chaining
1431 */
1432 public Matrix4f setToLookAt(final Vec3f eye, final Vec3f center, final Vec3f up, final Matrix4f tmp) {
1433 // normalized forward!
1434 final Vec3f fwd = new Vec3f( center.x() - eye.x(),
1435 center.y() - eye.y(),
1436 center.z() - eye.z() ).normalize();
1437
1438 /* Side = forward x up, normalized */
1439 final Vec3f side = fwd.cross(up).normalize();
1440
1441 /* Recompute up as: up = side x forward */
1442 final Vec3f up2 = side.cross(fwd);
1443
1444 m00 = side.x();
1445 m10 = up2.x();
1446 m20 = -fwd.x();
1447 m30 = 0;
1448
1449 m01 = side.y();
1450 m11 = up2.y();
1451 m21 = -fwd.y();
1452 m31 = 0;
1453
1454 m02 = side.z();
1455 m12 = up2.z();
1456 m22 = -fwd.z();
1457 m32 = 0;
1458
1459 m03 = 0;
1460 m13 = 0;
1461 m23 = 0;
1462 m33 = 1;
1463
1464 return mul( tmp.setToTranslation( -eye.x(), -eye.y(), -eye.z() ) );
1465 }
1466
1467 /**
1468 * Set this matrix to the <i>pick</i> matrix based on given parameters.
1469 * <p>
1470 * Traditional <code>gluPickMatrix</code> implementation.
1471 * </p>
1472 * <p>
1473 * Consist out of two matrix multiplications:
1474 * <pre>
1475 * <b>R</b> = <b>T</b> x <b>S</b>,
1476 * with <b>T</b> for viewport translation matrix and
1477 * <b>S</b> for viewport scale matrix.
1478 *
1479 * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e.
1480 * <b>P</b> = <b>P</b> x <b>R</b>,
1481 * with <b>P</b> being the <i>projection</i> matrix.
1482 * </pre>
1483 * </p>
1484 * <p>
1485 * To effectively use the generated pick matrix for picking,
1486 * call {@link #setToPick(float, float, float, float, Recti, Matrix4f) setToPick(..)}
1487 * and multiply a {@link #setToPerspective(float, float, float, float) custom perspective matrix}
1488 * by this pick matrix. Then you may load the result onto the perspective matrix stack.
1489 * </p>
1490 * @param x the center x-component of a picking region in window coordinates
1491 * @param y the center y-component of a picking region in window coordinates
1492 * @param deltaX the width of the picking region in window coordinates.
1493 * @param deltaY the height of the picking region in window coordinates.
1494 * @param viewport Rect4i viewport
1495 * @param mat4Tmp temp storage
1496 * @return this matrix for chaining or {@code null} if either delta value is <= zero.
1497 */
1498 public Matrix4f setToPick(final float x, final float y, final float deltaX, final float deltaY,
1499 final Recti viewport, final Matrix4f mat4Tmp) {
1500 if (deltaX <= 0 || deltaY <= 0) {
1501 return null;
1502 }
1503 /* Translate and scale the picked region to the entire window */
1504 setToTranslation( ( viewport.width() - 2 * ( x - viewport.x() ) ) / deltaX,
1505 ( viewport.height() - 2 * ( y - viewport.y() ) ) / deltaY,
1506 0);
1507 mat4Tmp.setToScale( viewport.width() / deltaX, viewport.height() / deltaY, 1.0f );
1508 return mul(mat4Tmp);
1509 }
1510
1511 //
1512 // Matrix affine operations using setTo..()
1513 //
1514
1515 /**
1516 * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, float, float, float) axis-rotation matrix}.
1517 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1518 * @param angrad angle in radians
1519 * @param x x of rotation axis
1520 * @param y y of rotation axis
1521 * @param z z of rotation axis
1522 * @param tmp temporary Matrix4f used for multiplication
1523 * @return this matrix for chaining
1524 */
1525 public final Matrix4f rotate(final float ang_rad, final float x, final float y, final float z, final Matrix4f tmp) {
1526 return mul( tmp.setToRotationAxis(ang_rad, x, y, z) );
1527 }
1528
1529 /**
1530 * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, Vec3f) axis-rotation matrix}.
1531 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1532 * @param angrad angle in radians
1533 * @param axis rotation axis
1534 * @param tmp temporary Matrix4f used for multiplication
1535 * @return this matrix for chaining
1536 */
1537 public final Matrix4f rotate(final float ang_rad, final Vec3f axis, final Matrix4f tmp) {
1538 return mul( tmp.setToRotationAxis(ang_rad, axis) );
1539 }
1540
1541 /**
1542 * Rotate this matrix with the given {@link Quaternion}, i.e. multiply by {@link #setToRotation(Quaternion) Quaternion's rotation matrix}.
1543 * @param tmp temporary Matrix4f used for multiplication
1544 * @return this matrix for chaining
1545 */
1546 public final Matrix4f rotate(final Quaternion quat, final Matrix4f tmp) {
1547 return mul( tmp.setToRotation(quat) );
1548 }
1549
1550 /**
1551 * Translate this matrix, i.e. multiply by {@link #setToTranslation(float, float, float) translation matrix}.
1552 * @param x x translation
1553 * @param y y translation
1554 * @param z z translation
1555 * @param tmp temporary Matrix4f used for multiplication
1556 * @return this matrix for chaining
1557 */
1558 public final Matrix4f translate(final float x, final float y, final float z, final Matrix4f tmp) {
1559 return mul( tmp.setToTranslation(x, y, z) );
1560 }
1561
1562 /**
1563 * Translate this matrix, i.e. multiply by {@link #setToTranslation(Vec3f) translation matrix}.
1564 * @param t translation Vec3f
1565 * @param tmp temporary Matrix4f used for multiplication
1566 * @return this matrix for chaining
1567 */
1568 public final Matrix4f translate(final Vec3f t, final Matrix4f tmp) {
1569 return mul( tmp.setToTranslation(t) );
1570 }
1571
1572 /**
1573 * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}.
1574 * @param x x scale
1575 * @param y y scale
1576 * @param z z scale
1577 * @param tmp temporary Matrix4f used for multiplication
1578 * @return this matrix for chaining
1579 */
1580 public final Matrix4f scale(final float x, final float y, final float z, final Matrix4f tmp) {
1581 return mul( tmp.setToScale(x, y, z) );
1582 }
1583
1584 /**
1585 * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}.
1586 * @param s scale for x-, y- and z-axis
1587 * @param tmp temporary Matrix4f used for multiplication
1588 * @return this matrix for chaining
1589 */
1590 public final Matrix4f scale(final float s, final Matrix4f tmp) {
1591 return mul( tmp.setToScale(s, s, s) );
1592 }
1593
1594 //
1595 // Matrix Stack
1596 //
1597
1598 /**
1599 * Push the matrix to it's stack, while preserving this matrix values.
1600 * @see #pop()
1601 */
1602 public final void push() {
1603 stack.push(this);
1604 }
1605
1606 /**
1607 * Pop the current matrix from it's stack, replacing this matrix values.
1608 * @see #push()
1609 */
1610 public final void pop() {
1611 stack.pop(this);
1612 }
1613
1614 //
1615 // equals
1616 //
1617
1618 /**
1619 * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}.
1620 * <p>
1621 * Implementation considers following corner cases:
1622 * <ul>
1623 * <li>NaN == NaN</li>
1624 * <li>+Inf == +Inf</li>
1625 * <li>-Inf == -Inf</li>
1626 * </ul>
1627 * @param o comparison value
1628 * @param epsilon consider using {@link FloatUtil#EPSILON}
1629 * @return true if all components differ less than {@code epsilon}, otherwise false.
1630 */
1631 public boolean isEqual(final Matrix4f o, final float epsilon) {
1632 if( this == o ) {
1633 return true;
1634 } else {
1635 return FloatUtil.isEqual(m00, o.m00, epsilon) &&
1636 FloatUtil.isEqual(m01, o.m01, epsilon) &&
1637 FloatUtil.isEqual(m02, o.m02, epsilon) &&
1638 FloatUtil.isEqual(m03, o.m03, epsilon) &&
1639 FloatUtil.isEqual(m10, o.m10, epsilon) &&
1640 FloatUtil.isEqual(m11, o.m11, epsilon) &&
1641 FloatUtil.isEqual(m12, o.m12, epsilon) &&
1642 FloatUtil.isEqual(m13, o.m13, epsilon) &&
1643 FloatUtil.isEqual(m20, o.m20, epsilon) &&
1644 FloatUtil.isEqual(m21, o.m21, epsilon) &&
1645 FloatUtil.isEqual(m22, o.m22, epsilon) &&
1646 FloatUtil.isEqual(m23, o.m23, epsilon) &&
1647 FloatUtil.isEqual(m30, o.m30, epsilon) &&
1648 FloatUtil.isEqual(m31, o.m31, epsilon) &&
1649 FloatUtil.isEqual(m32, o.m32, epsilon) &&
1650 FloatUtil.isEqual(m33, o.m33, epsilon);
1651 }
1652 }
1653
1654 /**
1655 * Equals check using {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}.
1656 * <p>
1657 * Implementation considers following corner cases:
1658 * <ul>
1659 * <li>NaN == NaN</li>
1660 * <li>+Inf == +Inf</li>
1661 * <li>-Inf == -Inf</li>
1662 * </ul>
1663 * @param o comparison value
1664 * @return true if all components differ less than {@link FloatUtil#EPSILON}, otherwise false.
1665 */
1666 public boolean isEqual(final Matrix4f o) {
1667 return isEqual(o, FloatUtil.EPSILON);
1668 }
1669
1670 @Override
1671 public boolean equals(final Object o) {
1672 if( o instanceof Matrix4f ) {
1673 return isEqual((Matrix4f)o, FloatUtil.EPSILON);
1674 } else {
1675 return false;
1676 }
1677 }
1678
1679 //
1680 // Static multi Matrix ops
1681 //
1682
1683 /**
1684 * Map object coordinates to window coordinates.
1685 * <p>
1686 * Traditional <code>gluProject</code> implementation.
1687 * </p>
1688 *
1689 * @param obj object position, 3 component vector
1690 * @param mMv modelview matrix
1691 * @param mP projection matrix
1692 * @param viewport Rect4i viewport
1693 * @param winPos 3 component window coordinate, the result
1694 * @return true if successful, otherwise false (z is 1)
1695 */
1696 public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mMv, final Matrix4f mP,
1697 final Recti viewport, final Vec3f winPos)
1698 {
1699 final Vec4f vec4Tmp1 = new Vec4f(obj, 1f);
1700
1701 // vec4Tmp2 = Mv * o
1702 // rawWinPos = P * vec4Tmp2
1703 // rawWinPos = P * ( Mv * o )
1704 // rawWinPos = P * Mv * o
1705 final Vec4f vec4Tmp2 = mMv.mulVec4f(vec4Tmp1, new Vec4f());
1706 final Vec4f rawWinPos = mP.mulVec4f(vec4Tmp2, vec4Tmp1);
1707
1708 if (rawWinPos.w() == 0.0f) {
1709 return false;
1710 }
1711
1712 final float s = ( 1.0f / rawWinPos.w() ) * 0.5f;
1713
1714 // Map x, y and z to range 0-1 (w is ignored)
1715 rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
1716
1717 // Map x,y to viewport
1718 winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
1719 rawWinPos.y() * viewport.height() + viewport.y(),
1720 rawWinPos.z() );
1721
1722 return true;
1723 }
1724
1725 /**
1726 * Map object coordinates to window coordinates.
1727 * <p>
1728 * Traditional <code>gluProject</code> implementation.
1729 * </p>
1730 *
1731 * @param obj object position, 3 component vector
1732 * @param mPMv [projection] x [modelview] matrix, i.e. P x Mv
1733 * @param viewport Rect4i viewport
1734 * @param winPos 3 component window coordinate, the result
1735 * @return true if successful, otherwise false (z is 1)
1736 */
1737 public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mPMv,
1738 final Recti viewport, final Vec3f winPos)
1739 {
1740 final Vec4f vec4Tmp2 = new Vec4f(obj, 1f);
1741
1742 // rawWinPos = P * Mv * o
1743 final Vec4f rawWinPos = mPMv.mulVec4f(vec4Tmp2, new Vec4f());
1744
1745 if (rawWinPos.w() == 0.0f) {
1746 return false;
1747 }
1748
1749 final float s = ( 1.0f / rawWinPos.w() ) * 0.5f;
1750
1751 // Map x, y and z to range 0-1 (w is ignored)
1752 rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
1753
1754 // Map x,y to viewport
1755 winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
1756 rawWinPos.y() * viewport.height() + viewport.y(),
1757 rawWinPos.z() );
1758
1759 return true;
1760 }
1761
1762 /**
1763 * Map window coordinates to object coordinates.
1764 * <p>
1765 * Traditional <code>gluUnProject</code> implementation.
1766 * </p>
1767 *
1768 * @param winx
1769 * @param winy
1770 * @param winz
1771 * @param mMv 4x4 modelview matrix
1772 * @param mP 4x4 projection matrix
1773 * @param viewport Rect4i viewport
1774 * @param objPos 3 component object coordinate, the result
1775 * @param mat4Tmp 16 component matrix for temp storage
1776 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
1777 */
1778 public static boolean mapWinToObj(final float winx, final float winy, final float winz,
1779 final Matrix4f mMv, final Matrix4f mP,
1780 final Recti viewport,
1781 final Vec3f objPos,
1782 final Matrix4f mat4Tmp)
1783 {
1784 // invPMv = Inv(P x Mv)
1785 final Matrix4f invPMv = mat4Tmp.mul(mP, mMv);
1786 if( !invPMv.invert() ) {
1787 return false;
1788 }
1789
1790 final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
1791
1792 // Map x and y from window coordinates
1793 winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).mul(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
1794
1795 // Map to range -1 to 1
1796 winPos.mul(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
1797
1798 // rawObjPos = Inv(P x Mv) * winPos
1799 final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
1800
1801 if ( rawObjPos.w() == 0.0f ) {
1802 return false;
1803 }
1804 objPos.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
1805
1806 return true;
1807 }
1808
1809 /**
1810 * Map window coordinates to object coordinates.
1811 * <p>
1812 * Traditional <code>gluUnProject</code> implementation.
1813 * </p>
1814 *
1815 * @param winx
1816 * @param winy
1817 * @param winz
1818 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
1819 * @param viewport Rect4i viewport
1820 * @param objPos 3 component object coordinate, the result
1821 * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
1822 */
1823 public static boolean mapWinToObj(final float winx, final float winy, final float winz,
1824 final Matrix4f invPMv,
1825 final Recti viewport,
1826 final Vec3f objPos)
1827 {
1828 if( null == invPMv ) {
1829 return false;
1830 }
1831 final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
1832
1833 // Map x and y from window coordinates
1834 winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).mul(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
1835
1836 // Map to range -1 to 1
1837 winPos.mul(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
1838
1839 // rawObjPos = Inv(P x Mv) * winPos
1840 final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
1841
1842 if ( rawObjPos.w() == 0.0f ) {
1843 return false;
1844 }
1845 objPos.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
1846
1847 return true;
1848 }
1849
1850 /**
1851 * Map two window coordinates to two object coordinates,
1852 * distinguished by their z component.
1853 * <p>
1854 * Traditional <code>gluUnProject</code> implementation.
1855 * </p>
1856 *
1857 * @param winx
1858 * @param winy
1859 * @param winz1
1860 * @param winz2
1861 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
1862 * @param viewport Rect4i viewport vector
1863 * @param objPos1 3 component object coordinate, the result
1864 * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
1865 */
1866 public static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2,
1867 final Matrix4f invPMv,
1868 final Recti viewport,
1869 final Vec3f objPos1, final Vec3f objPos2)
1870 {
1871 if( null == invPMv ) {
1872 return false;
1873 }
1874 final Vec4f winPos = new Vec4f(winx, winy, winz1, 1f);
1875
1876 // Map x and y from window coordinates
1877 winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).mul(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
1878
1879 // Map to range -1 to 1
1880 winPos.mul(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
1881
1882 // rawObjPos = Inv(P x Mv) * winPos1
1883 final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
1884
1885 if ( rawObjPos.w() == 0.0f ) {
1886 return false;
1887 }
1888 objPos1.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
1889
1890 //
1891 // winz2
1892 //
1893 // Map Z to range -1 to 1
1894 winPos.setZ( winz2 * 2f - 1f );
1895
1896 // rawObjPos = Inv(P x Mv) * winPos2
1897 invPMv.mulVec4f(winPos, rawObjPos);
1898
1899 if ( rawObjPos.w() == 0.0f ) {
1900 return false;
1901 }
1902 objPos2.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
1903
1904 return true;
1905 }
1906
1907 /**
1908 * Map window coordinates to object coordinates.
1909 * <p>
1910 * Traditional <code>gluUnProject4</code> implementation.
1911 * </p>
1912 *
1913 * @param winx
1914 * @param winy
1915 * @param winz
1916 * @param clipw
1917 * @param mMv 4x4 modelview matrix
1918 * @param mP 4x4 projection matrix
1919 * @param viewport Rect4i viewport vector
1920 * @param near
1921 * @param far
1922 * @param obj_pos 4 component object coordinate, the result
1923 * @param mat4Tmp 16 component matrix for temp storage
1924 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
1925 */
1926 public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
1927 final Matrix4f mMv, final Matrix4f mP,
1928 final Recti viewport,
1929 final float near, final float far,
1930 final Vec4f objPos,
1931 final Matrix4f mat4Tmp)
1932 {
1933 // invPMv = Inv(P x Mv)
1934 final Matrix4f invPMv = mat4Tmp.mul(mP, mMv);
1935 if( !invPMv.invert() ) {
1936 return false;
1937 }
1938
1939 final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
1940
1941 // Map x and y from window coordinates
1942 winPos.add(-viewport.x(), -viewport.y(), -near, 0f).mul(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f);
1943
1944 // Map to range -1 to 1
1945 winPos.mul(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
1946
1947 // objPos = Inv(P x Mv) * winPos
1948 invPMv.mulVec4f(winPos, objPos);
1949
1950 if ( objPos.w() == 0.0f ) {
1951 return false;
1952 }
1953 return true;
1954 }
1955
1956 /**
1957 * Map window coordinates to object coordinates.
1958 * <p>
1959 * Traditional <code>gluUnProject4</code> implementation.
1960 * </p>
1961 *
1962 * @param winx
1963 * @param winy
1964 * @param winz
1965 * @param clipw
1966 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
1967 * @param viewport Rect4i viewport vector
1968 * @param near
1969 * @param far
1970 * @param obj_pos 4 component object coordinate, the result
1971 * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
1972 */
1973 public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
1974 final Matrix4f invPMv,
1975 final Recti viewport,
1976 final float near, final float far,
1977 final Vec4f objPos)
1978 {
1979 if( null == invPMv ) {
1980 return false;
1981 }
1982 final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
1983
1984 // Map x and y from window coordinates
1985 winPos.add(-viewport.x(), -viewport.y(), -near, 0f).mul(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f);
1986
1987 // Map to range -1 to 1
1988 winPos.mul(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
1989
1990 // objPos = Inv(P x Mv) * winPos
1991 invPMv.mulVec4f(winPos, objPos);
1992
1993 if ( objPos.w() == 0.0f ) {
1994 return false;
1995 }
1996 return true;
1997 }
1998
1999 /**
2000 * Map two window coordinates w/ shared X/Y and distinctive Z
2001 * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
2002 * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
2003 * <p>
2004 * Notes for picking <i>winz0</i> and <i>winz1</i>:
2005 * <ul>
2006 * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
2007 * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
2008 * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
2009 * </ul>
2010 * </p>
2011 * @param winx
2012 * @param winy
2013 * @param winz0
2014 * @param winz1
2015 * @param mMv 4x4 modelview matrix
2016 * @param mP 4x4 projection matrix
2017 * @param viewport Rect4i viewport
2018 * @param ray storage for the resulting {@link Ray}
2019 * @param mat4Tmp1 16 component matrix for temp storage
2020 * @param mat4Tmp2 16 component matrix for temp storage
2021 * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
2022 */
2023 public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
2024 final Matrix4f mMv, final Matrix4f mP,
2025 final Recti viewport,
2026 final Ray ray,
2027 final Matrix4f mat4Tmp1) {
2028 // invPMv = Inv(P x Mv)
2029 final Matrix4f invPMv = mat4Tmp1.mul(mP, mMv);
2030 if( !invPMv.invert() ) {
2031 return false;
2032 }
2033
2034 if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
2035 ray.dir.sub(ray.orig).normalize();
2036 return true;
2037 } else {
2038 return false;
2039 }
2040 }
2041
2042 /**
2043 * Map two window coordinates w/ shared X/Y and distinctive Z
2044 * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
2045 * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
2046 * <p>
2047 * Notes for picking <i>winz0</i> and <i>winz1</i>:
2048 * <ul>
2049 * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
2050 * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
2051 * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
2052 * </ul>
2053 * </p>
2054 * @param winx
2055 * @param winy
2056 * @param winz0
2057 * @param winz1
2058 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
2059 * @param viewport Rect4i viewport
2060 * @param ray storage for the resulting {@link Ray}
2061 * @return true if successful, otherwise false (null invert matrix, or becomes z is infinity)
2062 */
2063 public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
2064 final Matrix4f invPMv,
2065 final Recti viewport,
2066 final Ray ray) {
2067 if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
2068 ray.dir.sub(ray.orig).normalize();
2069 return true;
2070 } else {
2071 return false;
2072 }
2073 }
2074
2075 //
2076 // String and internals
2077 //
2078
2079 /**
2080 * @param sb optional passed StringBuilder instance to be used
2081 * @param rowPrefix optional prefix for each row
2082 * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
2083 * @return matrix string representation
2084 */
2085 public StringBuilder toString(final StringBuilder sb, final String rowPrefix, final String f) {
2086 final float[] tmp = new float[16];
2087 this.get(tmp);
2088 return FloatUtil.matrixToString(sb, rowPrefix, f,tmp, 0, 4, 4, false /* rowMajorOrder */);
2089 }
2090
2091 @Override
2092 public String toString() {
2093 return toString(null, null, "%10.5f").toString();
2094 }
2095
2096 private float m00, m10, m20, m30;
2097 private float m01, m11, m21, m31;
2098 private float m02, m12, m22, m32;
2099 private float m03, m13, m23, m33;
2100
2101 final Stack stack = new Stack(0, 16*16); // start w/ zero size, growSize is half GL-min size (32)
2102
2103 private static class Stack {
2104 private int position;
2105 private float[] buffer;
2106 private final int growSize;
2107
2108 /**
2109 * @param initialSize initial size
2110 * @param growSize grow size if {@link #position()} is reached, maybe <code>0</code>
2111 * in which case an {@link IndexOutOfBoundsException} is thrown.
2112 */
2113 public Stack(final int initialSize, final int growSize) {
2114 this.position = 0;
2115 this.growSize = growSize;
2116 this.buffer = new float[initialSize];
2117 }
2118
2119 private final void growIfNecessary(final int length) throws IndexOutOfBoundsException {
2120 if( position + length > buffer.length ) {
2121 if( 0 >= growSize ) {
2122 throw new IndexOutOfBoundsException("Out of fixed stack size: "+this);
2123 }
2124 final float[] newBuffer = new float[buffer.length + Math.max(length, growSize)];
2125 System.arraycopy(buffer, 0, newBuffer, 0, position);
2126 buffer = newBuffer;
2127 }
2128 }
2129
2130 public final Matrix4f push(final Matrix4f src) throws IndexOutOfBoundsException {
2131 growIfNecessary(16);
2132 src.get(buffer, position);
2133 position += 16;
2134 return src;
2135 }
2136
2137 public final Matrix4f pop(final Matrix4f dest) throws IndexOutOfBoundsException {
2138 position -= 16;
2139 dest.load(buffer, position);
2140 return dest;
2141 }
2142 }
2143}
Basic Float math utility functions.
Definition: FloatUtil.java:83
static float sin(final float a)
static final float EPSILON
Epsilon for floating point {@value}, as once computed via getMachineEpsilon() on an AMD-64 CPU.
static float cos(final float a)
static float tan(final float a)
static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, final FloatBuffer a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder)
static boolean isZero(final float a, final float epsilon)
Returns true if value is zero, i.e.
static boolean isEqual(final float a, final float b, final float epsilon)
Returns true if both values are equal, i.e.
Horizontal and vertical field of view (FOV) halves, allowing a non-centered projection.
final FovHVHalves toTangents()
Returns this instance in tangent values.
Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
Definition: Matrix4f.java:89
boolean isEqual(final Matrix4f o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
Definition: Matrix4f.java:1631
final Matrix4f mul(final Matrix4f b)
Multiply matrix: [this] = [this] x [b].
Definition: Matrix4f.java:726
boolean invert(final Matrix4f src)
Invert the src matrix values into this matrix.
Definition: Matrix4f.java:610
static boolean mapObjToWin(final Vec3f obj, final Matrix4f mMv, final Matrix4f mP, final Recti viewport, final Vec3f winPos)
Map object coordinates to window coordinates.
Definition: Matrix4f.java:1696
final Matrix4f rotate(final Quaternion quat, final Matrix4f tmp)
Rotate this matrix with the given Quaternion, i.e.
Definition: Matrix4f.java:1546
Matrix4f load(final Matrix4f src)
Load the values of the given matrix src to this matrix.
Definition: Matrix4f.java:186
final Matrix4f loadIdentity()
Set this matrix to identity.
Definition: Matrix4f.java:172
Vec3f getRow(final int row, final Vec3f v_out)
Get the named row of the given column-major matrix to v_out.
Definition: Matrix4f.java:352
Matrix4f setToPerspective(final FovHVHalves fovhv, final float zNear, final float zFar)
Set this matrix to perspective frustum projection.
Definition: Matrix4f.java:1322
Matrix4f()
Creates a new identity matrix.
Definition: Matrix4f.java:94
static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw, final Matrix4f mMv, final Matrix4f mP, final Recti viewport, final float near, final float far, final Vec4f objPos, final Matrix4f mat4Tmp)
Map window coordinates to object coordinates.
Definition: Matrix4f.java:1926
final Vec3f mulVec3f(final Vec3f v_in, final Vec3f v_out)
Affine 3f-vector transformation by 4x4 matrix.
Definition: Matrix4f.java:841
final Matrix4f mul(final Matrix4f a, final Matrix4f b)
Multiply matrix: [this] = [a] x [b].
Definition: Matrix4f.java:773
final Matrix4f rotate(final float ang_rad, final float x, final float y, final float z, final Matrix4f tmp)
Rotate this matrix about give axis and angle in radians, i.e.
Definition: Matrix4f.java:1525
static boolean mapWinToObj(final float winx, final float winy, final float winz, final Matrix4f invPMv, final Recti viewport, final Vec3f objPos)
Map window coordinates to object coordinates.
Definition: Matrix4f.java:1823
final Matrix4f scale(final float s, final Matrix4f tmp)
Scale this matrix, i.e.
Definition: Matrix4f.java:1590
Frustum getFrustum(final Frustum frustum)
Calculate the frustum planes in world coordinates using this column major order matrix,...
Definition: Matrix4f.java:1340
final Matrix4f scale(final float x, final float y, final float z, final Matrix4f tmp)
Scale this matrix, i.e.
Definition: Matrix4f.java:1580
static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1, final Matrix4f invPMv, final Recti viewport, final Ray ray)
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray.
Definition: Matrix4f.java:2063
Vec4f getRow(final int row, final Vec4f v_out)
Get the named row of the given column-major matrix to v_out.
Definition: Matrix4f.java:338
Matrix4f(final FloatBuffer m)
Creates a new matrix based on given FloatBuffer 4x4 column major order.
Definition: Matrix4f.java:127
final Matrix4f translate(final float x, final float y, final float z, final Matrix4f tmp)
Translate this matrix, i.e.
Definition: Matrix4f.java:1558
static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2, final Matrix4f invPMv, final Recti viewport, final Vec3f objPos1, final Vec3f objPos2)
Map two window coordinates to two object coordinates, distinguished by their z component.
Definition: Matrix4f.java:1866
static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw, final Matrix4f invPMv, final Recti viewport, final float near, final float far, final Vec4f objPos)
Map window coordinates to object coordinates.
Definition: Matrix4f.java:1973
final Matrix4f transpose()
Transpose this matrix.
Definition: Matrix4f.java:464
Matrix4f setToRotationEuler(final float bankX, final float headingY, final float attitudeZ)
Set this matrix to rotation from the given Euler rotation angles in radians.
Definition: Matrix4f.java:1051
Matrix4f setToPerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar)
Set this matrix to perspective frustum projection.
Definition: Matrix4f.java:1303
Matrix4f load(final FloatBuffer src)
Load the values of the given matrix src to this matrix.
Definition: Matrix4f.java:254
boolean invert()
Invert this matrix.
Definition: Matrix4f.java:530
Matrix4f load(final float[] src)
Load the values of the given matrix src to this matrix.
Definition: Matrix4f.java:199
final Matrix4f setToRotationAxis(final float ang_rad, final Vec3f axis)
Set this matrix to rotation from the given axis and angle in radians.
Definition: Matrix4f.java:1024
final Matrix4f setToRotation(final Quaternion q)
Set this matrix to rotation using the given Quaternion.
Definition: Matrix4f.java:1124
final Matrix4f setToTranslation(final Vec3f t)
Set this matrix to translation.
Definition: Matrix4f.java:911
float determinant()
Returns the determinant of this matrix.
Definition: Matrix4f.java:450
final Matrix4f translate(final Vec3f t, final Matrix4f tmp)
Translate this matrix, i.e.
Definition: Matrix4f.java:1568
Vec3f getColumn(final int column, final Vec3f v_out)
Get the named column of the given column-major matrix to v_out.
Definition: Matrix4f.java:325
final Matrix4f transpose(final Matrix4f src)
Transpose the given src matrix into this matrix.
Definition: Matrix4f.java:500
final void pop()
Pop the current matrix from it's stack, replacing this matrix values.
Definition: Matrix4f.java:1610
StringBuilder toString(final StringBuilder sb, final String rowPrefix, final String f)
Definition: Matrix4f.java:2085
final Matrix4f setToRotationAxis(final float ang_rad, float x, float y, float z)
Set this matrix to rotation from the given axis and angle in radians.
Definition: Matrix4f.java:973
final Quaternion getRotation(final Quaternion res)
Returns the rotation [m00 .
Definition: Matrix4f.java:1185
Matrix4f setToOrtho(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar)
Set this matrix to orthogonal projection.
Definition: Matrix4f.java:1206
Matrix4f load(final float[] src, final int src_off)
Load the values of the given matrix src to this matrix.
Definition: Matrix4f.java:225
Matrix4f setToLookAt(final Vec3f eye, final Vec3f center, final Vec3f up, final Matrix4f tmp)
Set this matrix to the look-at matrix based on given parameters.
Definition: Matrix4f.java:1432
static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1, final Matrix4f mMv, final Matrix4f mP, final Recti viewport, final Ray ray, final Matrix4f mat4Tmp1)
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray.
Definition: Matrix4f.java:2023
final void push()
Push the matrix to it's stack, while preserving this matrix values.
Definition: Matrix4f.java:1602
Matrix4f(final float[] m, final int m_off)
Creates a new matrix based on given float[4*4] column major order.
Definition: Matrix4f.java:119
final Vec4f mulVec4f(final Vec4f v_in, final Vec4f v_out)
Definition: Matrix4f.java:806
Matrix4f setToPick(final float x, final float y, final float deltaX, final float deltaY, final Recti viewport, final Matrix4f mat4Tmp)
Set this matrix to the pick matrix based on given parameters.
Definition: Matrix4f.java:1498
Matrix4f setToRotationEuler(final Vec3f angradXYZ)
Set this matrix to rotation from the given Euler rotation angles in radians.
Definition: Matrix4f.java:1104
final Matrix4f rotate(final float ang_rad, final Vec3f axis, final Matrix4f tmp)
Rotate this matrix about give axis and angle in radians, i.e.
Definition: Matrix4f.java:1537
final Matrix4f setToScale(final float x, final float y, final float z)
Set this matrix to scale.
Definition: Matrix4f.java:929
static boolean mapObjToWin(final Vec3f obj, final Matrix4f mPMv, final Recti viewport, final Vec3f winPos)
Map object coordinates to window coordinates.
Definition: Matrix4f.java:1737
Matrix4f(final Matrix4f src)
Creates a new matrix copying the values of the given src matrix.
Definition: Matrix4f.java:102
final Vec4f mulVec4f(final Vec4f v_inout)
Definition: Matrix4f.java:820
Matrix4f setToFrustum(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar)
Set this matrix to frustum.
Definition: Matrix4f.java:1254
Matrix4f(final float[] m)
Creates a new matrix based on given float[4*4] column major order.
Definition: Matrix4f.java:110
boolean isEqual(final Matrix4f o)
Equals check using FloatUtil#EPSILON value and FloatUtil#isEqual(float, float, float).
Definition: Matrix4f.java:1666
static boolean mapWinToObj(final float winx, final float winy, final float winz, final Matrix4f mMv, final Matrix4f mP, final Recti viewport, final Vec3f objPos, final Matrix4f mat4Tmp)
Map window coordinates to object coordinates.
Definition: Matrix4f.java:1778
final Matrix4f setToScale(final Vec3f s)
Set this matrix to scale.
Definition: Matrix4f.java:953
Vec4f getColumn(final int column, final Vec4f v_out)
Get the named column of the given column-major matrix to v_out.
Definition: Matrix4f.java:311
boolean equals(final Object o)
Definition: Matrix4f.java:1671
final Vec3f mulVec3f(final Vec3f v_inout)
Affine 3f-vector transformation by 4x4 matrix.
Definition: Matrix4f.java:860
final Matrix4f setToTranslation(final float x, final float y, final float z)
Set this matrix to translation.
Definition: Matrix4f.java:887
Quaternion implementation supporting Gimbal-Lock free rotations.
Definition: Quaternion.java:45
final float magnitudeSquared()
See magnitude() for special handling of epsilon, which is not applied here.
Definition: Quaternion.java:75
Quaternion setFromMat(final float m00, final float m01, final float m02, final float m10, final float m11, final float m12, final float m20, final float m21, final float m22)
Compute the quaternion from a 3x3 column rotation matrix.
Simple compound denoting a ray.
Definition: Ray.java:49
final Vec3f dir
Normalized direction vector of ray.
Definition: Ray.java:54
final Vec3f orig
Origin of Ray.
Definition: Ray.java:51
Rectangle with x, y, width and height integer components.
Definition: Recti.java:34
3D Vector based upon three float components.
Definition: Vec3f.java:37
Vec3f scale(final float s)
this = this * s, returns this.
Definition: Vec3f.java:218
Vec3f sub(final Vec3f b)
this = this - b, returns this.
Definition: Vec3f.java:268
Vec3f normalize()
Normalize this vector in place.
Definition: Vec3f.java:297
float length()
Return the length of this vector, a.k.a the norm or magnitude
Definition: Vec3f.java:283
Vec3f cross(final Vec3f arg)
Returns this cross arg; creates new vector.
Definition: Vec3f.java:343
Vec3f set(final Vec3f o)
this = o, returns this.
Definition: Vec3f.java:79
4D Vector based upon four float components.
Definition: Vec4f.java:37
Vec4f set(final Vec4f o)
this = o, returns this.
Definition: Vec4f.java:67
Vec4f scale(final float s)
this = this * s, returns this.
Definition: Vec4f.java:214
Vec4f mul(final float val)
Returns this * val; creates new vector.
Definition: Vec4f.java:170
Vec4f add(final float dx, final float dy, final float dz, final float dw)
this = this + { dx, dy, dz, dw }, returns this.
Definition: Vec4f.java:237
void setZ(final float z)
Definition: Vec4f.java:149
Plane equation := dot(n, x - p) = 0 -> Ax + By + Cz + d == 0.
Definition: Frustum.java:158
final Vec3f n
Normal of the plane.
Definition: Frustum.java:160
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition: Frustum.java:81
static final int NEAR
Index for near plane: {@value}.
Definition: Frustum.java:268
static final int BOTTOM
Index for bottom plane: {@value}.
Definition: Frustum.java:264
final Plane[] getPlanes()
Planes are ordered in the returned array as follows:
Definition: Frustum.java:289
static final int RIGHT
Index for right plane: {@value}.
Definition: Frustum.java:262
static final int TOP
Index for top plane: {@value}.
Definition: Frustum.java:266
static final int LEFT
Index for left plane: {@value}.
Definition: Frustum.java:260
static final int FAR
Index for far plane: {@value}.
Definition: Frustum.java:270