JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestQuaternion01NOUI.java
Go to the documentation of this file.
1/**
2 * Copyright 2014 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.opengl.test.junit.math;
30
31import org.junit.Assert;
32import org.junit.Test;
33import org.junit.FixMethodOrder;
34import org.junit.runners.MethodSorters;
35
36import com.jogamp.junit.util.JunitTracer;
37import com.jogamp.math.FloatUtil;
38import com.jogamp.math.Matrix4f;
39import com.jogamp.math.Quaternion;
40import com.jogamp.math.Vec3f;
41import com.jogamp.math.Vec4f;
42import com.jogamp.math.VectorUtil;
43
44@FixMethodOrder(MethodSorters.NAME_ASCENDING)
45public class TestQuaternion01NOUI extends JunitTracer {
46 static final boolean DEBUG = false;
47
48 static final Quaternion QUAT_IDENT = new Quaternion(0f, 0f, 0f, 1f);
49
50 static final Vec3f ZERO = new Vec3f ( 0f, 0f, 0f );
51 static final Vec3f ONE = new Vec3f ( 1f, 1f, 1f );
52 static final Vec3f NEG_ONE = new Vec3f ( -1f, -1f, -1f );
53 static final Vec3f UNIT_X = new Vec3f ( 1f, 0f, 0f );
54 static final Vec3f UNIT_Y = new Vec3f ( 0f, 1f, 0f );
55 static final Vec3f UNIT_Z = new Vec3f ( 0f, 0f, 1f );
56 static final Vec3f NEG_UNIT_X = new Vec3f ( -1f, 0f, 0f );
57 static final Vec3f NEG_UNIT_Y = new Vec3f ( 0f, -1f, 0f );
58 static final Vec3f NEG_UNIT_Z = new Vec3f ( 0f, 0f, -1f );
59
60 static final Vec4f NEG_ONE_v4 = new Vec4f ( -1f, -1f, -1f, 0f );
61 static final Vec4f ONE_v4 = new Vec4f ( 1f, 1f, 1f, 0f );
62
63 static final float MACH_EPSILON = FloatUtil.EPSILON;
64
65 //
66 // Basic
67 //
68
69 @Test
70 public void test01Normalize() {
71 final Quaternion quat = new Quaternion(0, 1, 2, 3);
72 final Quaternion quat2 = new Quaternion(quat).normalize();
73 // Assert.assertTrue(Math.abs(1 - quat2.magnitude()) <= MACH_EPSILON);
74 Assert.assertEquals(0f, Math.abs(1 - quat2.magnitude()), MACH_EPSILON);
75 }
76
77 @Test
78 public void test02RotateZeroVector() {
79 final Quaternion quat = new Quaternion();
80 final Vec3f ZERO = new Vec3f(0, 0, 0);
81 final Vec3f rotVec0 = quat.rotateVector(ZERO, new Vec3f());
82 Assert.assertEquals(ZERO, rotVec0);
83 }
84
85 @Test
86 public void test03InvertAndConj() {
87 // inversion check
88 {
89 final Quaternion quat0 = new Quaternion(0, 1, 2, 3);
90 final Quaternion quat0Inv = new Quaternion(quat0).invert();
91 Assert.assertEquals(quat0, quat0Inv.invert());
92 }
93 // conjugate check
94 {
95 final Quaternion quat0 = new Quaternion(-1f, -2f, -3f, 4f);
96 final Quaternion quat0Conj = new Quaternion( 1f, 2f, 3f, 4f).conjugate();
97 Assert.assertEquals(quat0, quat0Conj);
98 }
99 }
100
101 @Test
102 public void test04Dot() {
103 final Quaternion quat = new Quaternion(7f, 2f, 5f, -1f);
104 Assert.assertTrue(35.0f == quat.dot(3f, 1f, 2f, -2f));
105 Assert.assertTrue(-11.0f == quat.dot(new Quaternion(-1f, 1f, -1f, 1f)));
106 }
107
108
109 //
110 // Conversion
111 //
112
113 @Test
114 public void test10AngleAxis() {
115 final Vec3f tmpV3f = new Vec3f();
116 final Quaternion quat1 = new Quaternion().setFromAngleAxis(FloatUtil.HALF_PI, new Vec3f ( 2, 0, 0 ), tmpV3f );
117 final Quaternion quat2 = new Quaternion().setFromAngleNormalAxis(FloatUtil.HALF_PI, new Vec3f ( 1, 0, 0 ) );
118
119 Assert.assertEquals(quat2, quat1);
120 // System.err.println("M "+quat2.magnitude()+", 1-M "+(1f-quat2.magnitude())+", Eps "+FloatUtil.EPSILON);
121 Assert.assertEquals(0f, 1 - quat2.magnitude(), FloatUtil.EPSILON);
122 Assert.assertTrue(1 - quat1.magnitude() <= FloatUtil.EPSILON);
123
124 final Vec3f vecOut1 = new Vec3f();
125 final Vec3f vecOut2 = new Vec3f();
126 quat1.rotateVector(Vec3f.ONE, vecOut1);
127 quat2.rotateVector(Vec3f.ONE, vecOut2);
128 Assert.assertEquals(vecOut1, vecOut2);
129 Assert.assertEquals(0f, Math.abs( vecOut1.dist(vecOut2) ), FloatUtil.EPSILON );
130
131 quat1.rotateVector(Vec3f.UNIT_Z, vecOut1);
132 Assert.assertEquals(0f, Math.abs( Vec3f.UNIT_Y_NEG.dist(vecOut1) ), FloatUtil.EPSILON );
133
134 quat2.setFromAngleAxis(FloatUtil.HALF_PI, ZERO, tmpV3f);
135 Assert.assertEquals(QUAT_IDENT, quat2);
136
137 float angle = quat1.toAngleAxis(vecOut1);
138 quat2.setFromAngleAxis(angle, vecOut1, tmpV3f);
139 Assert.assertEquals(quat1, quat2);
140
141 quat1.set(0, 0, 0, 0);
142 angle = quat1.toAngleAxis(vecOut1);
143 Assert.assertTrue(0.0f == angle);
144 Assert.assertEquals(UNIT_X, vecOut1);
145 }
146
147 @Test
149 final Vec3f tmp0V3f = new Vec3f();
150 final Vec3f tmp1V3f = new Vec3f();
151 final Vec3f vecOut = new Vec3f();
152 final Quaternion quat = new Quaternion();
153 quat.setFromVectors(UNIT_Z, UNIT_X, tmp0V3f, tmp1V3f);
154
155 final Quaternion quat2 = new Quaternion();
156 quat2.setFromNormalVectors(UNIT_Z, UNIT_X, tmp0V3f);
157 Assert.assertEquals(quat, quat2);
158
159 quat2.setFromAngleAxis(FloatUtil.HALF_PI, UNIT_Y, tmp0V3f);
160 Assert.assertEquals(quat2, quat);
161
162 quat.setFromVectors(UNIT_Z, NEG_UNIT_Z, tmp0V3f, tmp1V3f);
163 quat.rotateVector(UNIT_Z, vecOut);
164 // System.err.println("vecOut: "+Arrays.toString(vecOut));
165 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_Z.dist(vecOut) ), Quaternion.ALLOWED_DEVIANCE );
166
167 quat.setFromVectors(UNIT_X, NEG_UNIT_X, tmp0V3f, tmp1V3f);
168 quat.rotateVector(UNIT_X, vecOut);
169 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecOut) ), Quaternion.ALLOWED_DEVIANCE );
170
171 quat.setFromVectors(UNIT_Y, NEG_UNIT_Y, tmp0V3f, tmp1V3f);
172 quat.rotateVector(UNIT_Y, vecOut);
173 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_Y.dist(vecOut) ), Quaternion.ALLOWED_DEVIANCE );
174
175 quat.setFromVectors(ONE, NEG_ONE, tmp0V3f, tmp1V3f);
176 quat.rotateVector(ONE, vecOut);
177 Assert.assertEquals( 0f, Math.abs( NEG_ONE.dist(vecOut) ), Quaternion.ALLOWED_DEVIANCE );
178
179 quat.setFromVectors(ZERO, ZERO, tmp0V3f, tmp1V3f);
180 Assert.assertEquals(QUAT_IDENT, quat);
181 }
182
183 @Test
185 // Y.Z.X -> X.Y.Z
186 final Quaternion quat = new Quaternion();
187 final Vec3f angles0Exp = new Vec3f( 0f, FloatUtil.HALF_PI, 0f );
188 quat.setFromEuler(angles0Exp);
189 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
190
191 final Vec3f angles0Has = quat.toEuler(new Vec3f());
192 // System.err.println("exp0 "+Arrays.toString(angles0Exp));
193 // System.err.println("has0 "+Arrays.toString(angles0Has));
194 Assert.assertEquals(angles0Exp, angles0Has);
195
196 final Quaternion quat2 = new Quaternion();
197 quat2.setFromEuler(angles0Has);
198 Assert.assertEquals(quat, quat2);
199
200 ///
201
202 final Vec3f angles1Exp = new Vec3f(0f, 0f, -FloatUtil.HALF_PI);
203 quat.setFromEuler(angles1Exp);
204 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
205
206 final Vec3f angles1Has = quat.toEuler(new Vec3f());
207 // System.err.println("exp1 "+Arrays.toString(angles1Exp));
208 // System.err.println("has1 "+Arrays.toString(angles1Has));
209 Assert.assertEquals(angles1Exp, angles1Has);
210
211 quat2.setFromEuler(angles1Has);
212 Assert.assertEquals(quat, quat2);
213
214 ///
215
216 final Vec3f angles2Exp = new Vec3f(FloatUtil.HALF_PI, 0f, 0f);
217 quat.setFromEuler(angles2Exp);
218 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
219
220 final Vec3f angles2Has = quat.toEuler(new Vec3f());
221 // System.err.println("exp2 "+Arrays.toString(angles2Exp));
222 // System.err.println("has2 "+Arrays.toString(angles2Has));
223 Assert.assertEquals(angles2Exp, angles2Has);
224
225 quat2.setFromEuler(angles2Has);
226 Assert.assertEquals(quat, quat2);
227 }
228
229 @Test
231 final Quaternion quat = new Quaternion();
232 quat.setFromEuler(0, FloatUtil.HALF_PI, 0); // 90 degrees y-axis
233 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
234
235 final Vec3f v2 = quat.rotateVector(UNIT_X, new Vec3f());
236 Assert.assertEquals(0f, Math.abs( NEG_UNIT_Z.dist(v2)), FloatUtil.EPSILON);
237
238 quat.setFromEuler(0, 0, -FloatUtil.HALF_PI);
239 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
240 quat.rotateVector(UNIT_X, v2);
241 Assert.assertEquals(0f, Math.abs( NEG_UNIT_Y.dist(v2)), FloatUtil.EPSILON);
242
243 quat.setFromEuler(FloatUtil.HALF_PI, 0, 0);
244 Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
245 quat.rotateVector(UNIT_Y, v2);
246 Assert.assertEquals(0f, Math.abs( UNIT_Z.dist(v2)), FloatUtil.EPSILON);
247 }
248
249 @Test
250 public void test14Matrix() {
251 final Vec3f vecHas = new Vec3f();
252 final Vec3f vecOut3 = new Vec3f();
253 final Vec4f vecOut4 = new Vec4f();
254 final Matrix4f mat1 = new Matrix4f();;
255 final Matrix4f mat2 = new Matrix4f();
256 final Quaternion quat = new Quaternion();
257
258 //
259 // IDENTITY CHECK
260 //
261 mat1.loadIdentity();
262 quat.set(0, 0, 0, 0);
263 quat.toMatrix(mat2);
264 Assert.assertEquals(mat1, mat2);
265
266 //
267 // 90 degrees rotation on X
268 //
269
270 float a = FloatUtil.HALF_PI;
271 final float[] mat1_0 = new float[] { // Column Order
272 1, 0, 0, 0, //
273 0, FloatUtil.cos(a), FloatUtil.sin(a), 0, //
274 0, -FloatUtil.sin(a), FloatUtil.cos(a), 0,
275 0, 0, 0, 1 };
276 mat1.load( mat1_0 );
277 {
278 // Matrix4f load() <-> toFloats()
279 final float[] mat2_0 = new float[16];
280 mat1.get(mat2_0);
281 Assert.assertArrayEquals(mat1_0, mat2_0, FloatUtil.EPSILON);
282 }
283 {
284 // Validate Matrix via Euler rotation on Quaternion!
285 quat.setFromEuler(a, 0f, 0f);
286 {
287 // quat.toMatrix(float[])
288 final float[] mat2_0 = new float[16];
289 quat.toMatrix(mat2_0);
290 Assert.assertArrayEquals(mat1_0, mat2_0, FloatUtil.EPSILON);
291 }
292 {
293 // quat.toMatrix(float[]) and Matrix4f.load()
294 final float[] mat2_0 = new float[16];
295 quat.toMatrix(mat2_0);
296 Assert.assertArrayEquals(mat1_0, mat2_0, FloatUtil.EPSILON);
297 mat2.load(mat2_0);
298 Assert.assertEquals(mat1, mat2);
299 }
300 {
301 // Quaternion.toMatrix(Matrix4f)
302 quat.toMatrix(mat2);
303 // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
304 Assert.assertEquals(mat1, mat2);
305 }
306 quat.rotateVector(UNIT_Y, vecHas);
307 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
308 // System.err.println("has0 "+Arrays.toString(vecHas));
309 Assert.assertEquals( 0f, Math.abs( UNIT_Z.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
310 }
311 mat1.getRotation(quat);
312 quat.setFromMat(mat1);
313 quat.rotateVector(UNIT_Y, vecHas);
314 // System.err.println("exp0 "+Arrays.toString(UNIT_Z));
315 // System.err.println("has0 "+Arrays.toString(vecHas));
316 Assert.assertEquals( 0f, Math.abs( UNIT_Z.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
317
318 quat.toMatrix(mat2);
319 // System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
320 Assert.assertEquals(mat1, mat2);
321
322 quat.rotateVector(NEG_ONE, vecHas);
323 {
324 // 1st use float[] math
325 final float[] vecHas_0 = new float[3];
326 vecHas.get(vecHas_0);
327 final float[] mat2_0 = new float[16];
328 quat.toMatrix(mat2_0);
329 final float[] NEG_ONE_0 = new float[3];
330 NEG_ONE.get(NEG_ONE_0);
331 final float[] vecOut3_0 = new float[3];
332 FloatUtil.multMatrixVec3(mat2_0, NEG_ONE_0, vecOut3_0);
333 Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas_0, vecOut3_0) ), Quaternion.ALLOWED_DEVIANCE );
334 Assert.assertArrayEquals(vecHas_0, vecOut3_0, FloatUtil.EPSILON);
335
336 // 2nd use Vec3f math
337 mat2.mulVec3f(NEG_ONE, vecOut3);
338 Assert.assertEquals( 0f, Math.abs( vecHas.dist(vecOut3) ), Quaternion.ALLOWED_DEVIANCE );
339 Assert.assertEquals(vecHas, vecOut3);
340
341 // 3rd compare both
342 final float[] vecOut3_1 = new float[3];
343 vecOut3.get(vecOut3_1);
344 Assert.assertArrayEquals(vecOut3_0, vecOut3_1, FloatUtil.EPSILON);
345 }
346 {
347 // 1st use float[] math
348 final float[] vecHas_0 = new float[4];
349 vecHas.get(vecHas_0); // w is 0
350 final float[] mat2_0 = new float[16];
351 quat.toMatrix(mat2_0);
352 final float[] NEG_ONE_v4_0 = new float[4];
353 NEG_ONE_v4.get(NEG_ONE_v4_0);
354 final float[] vecOut4_0 = new float[4];
355 FloatUtil.multMatrixVec(mat2_0, NEG_ONE_v4_0, vecOut4_0);
356 Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas_0, vecOut4_0) ), Quaternion.ALLOWED_DEVIANCE );
357 Assert.assertArrayEquals(vecHas_0, vecOut4_0, FloatUtil.EPSILON);
358
359 // 2nd use Vec4f math
360 mat2.mulVec4f(NEG_ONE_v4, vecOut4);
361 vecOut3.set(vecOut4);
362 Assert.assertEquals( 0f, Math.abs( vecHas.dist(vecOut3) ), Quaternion.ALLOWED_DEVIANCE );
363 Assert.assertEquals(vecHas, vecOut3);
364
365 // 3rd compare both
366 final float[] vecOut4_1 = new float[4];
367 vecOut4.get(vecOut4_1);
368 Assert.assertArrayEquals(vecOut4_0, vecOut4_1, FloatUtil.EPSILON);
369 }
370
371 //
372 // 180 degrees rotation on X
373 //
374 a = FloatUtil.PI;
375 mat1.load( new float[] { // Column Order
376 1, 0, 0, 0, //
377 0, FloatUtil.cos(a), FloatUtil.sin(a), 0, //
378 0, -FloatUtil.sin(a), FloatUtil.cos(a), 0,
379 0, 0, 0, 1 } );
380 {
381 // Validate Matrix via Euler rotation on Quaternion!
382 quat.setFromEuler(a, 0f, 0f);
383 quat.toMatrix(mat2);
384 // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
385 Assert.assertEquals(mat1, mat2);
386 quat.rotateVector(UNIT_Y, vecHas);
387 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
388 // System.err.println("has0 "+Arrays.toString(vecHas));
389 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_Y.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
390 }
391 quat.setFromMat(mat1);
392 quat.rotateVector(UNIT_Y, vecHas);
393 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_Y));
394 // System.err.println("has0 "+Arrays.toString(vecHas));
395 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_Y.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
396
397 quat.toMatrix(mat2);
398 // System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
399 Assert.assertEquals(mat1, mat2);
400
401 quat.rotateVector(ONE, vecHas);
402 mat2.mulVec4f(ONE_v4, vecOut4);
403 vecOut3.set(vecOut4);
404 Assert.assertEquals( 0f, Math.abs( vecHas.dist(vecOut3) ), Quaternion.ALLOWED_DEVIANCE );
405
406 //
407 // 180 degrees rotation on Y
408 //
409 a = FloatUtil.PI;
410 mat1.load( new float[] { // Column Order
411 FloatUtil.cos(a), 0, -FloatUtil.sin(a), 0, //
412 0, 1, 0, 0, //
413 FloatUtil.sin(a), 0, FloatUtil.cos(a), 0,
414 0, 0, 0, 1 } );
415 {
416 // Validate Matrix via Euler rotation on Quaternion!
417 quat.setFromEuler(0f, a, 0f);
418 quat.toMatrix(mat2);
419 // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
420 Assert.assertEquals(mat1, mat2);
421 quat.rotateVector(UNIT_X, vecHas);
422 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
423 // System.err.println("has0 "+Arrays.toString(vecHas));
424 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
425 }
426 quat.setFromMat(mat1);
427 quat.rotateVector(UNIT_X, vecHas);
428 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
429 // System.err.println("has0 "+Arrays.toString(vecHas));
430 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
431
432 quat.toMatrix(mat2);
433 // System.err.println(FloatUtil.matrixToString(null, "matr-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
434 Assert.assertEquals(mat1, mat2);
435
436 quat.rotateVector(NEG_ONE, vecHas);
437 mat2.mulVec4f(NEG_ONE_v4, vecOut4);
438 vecOut3.set(vecOut4);
439 Assert.assertEquals( 0f, Math.abs( vecHas.dist(vecOut3) ), Quaternion.ALLOWED_DEVIANCE );
440
441 //
442 // 180 degrees rotation on Z
443 //
444 a = FloatUtil.PI;
445 mat1.load( new float[] { // Column Order
446 FloatUtil.cos(a), FloatUtil.sin(a), 0, 0, //
447 -FloatUtil.sin(a), FloatUtil.cos(a), 0, 0,
448 0, 0, 1, 0,
449 0, 0, 0, 1 } );
450 {
451 // Validate Matrix via Euler rotation on Quaternion!
452 quat.setFromEuler(0f, 0f, a);
453 quat.toMatrix(mat2);
454 // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
455 Assert.assertEquals(mat1, mat2);
456 quat.rotateVector(UNIT_X, vecHas);
457 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
458 // System.err.println("has0 "+Arrays.toString(vecHas));
459 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
460 }
461 quat.setFromMat(mat1);
462 quat.rotateVector(UNIT_X, vecHas);
463 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
464 // System.err.println("has0 "+Arrays.toString(vecHas));
465 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE );
466
467 quat.toMatrix(mat2);
468 // System.err.println(FloatUtil.matrixToString(null, "matr-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
469 Assert.assertEquals(mat1, mat2);
470
471 quat.rotateVector(ONE, vecHas);
472 mat2.mulVec4f(ONE_v4, vecOut4);
473 vecOut3.set(vecOut4);
474 Assert.assertEquals( 0f, Math.abs( vecHas.dist(vecOut3) ), Quaternion.ALLOWED_DEVIANCE );
475
476 //
477 // Test Matrix-Columns
478 //
479
481 final Vec3f vecExp0 = new Vec3f( FloatUtil.cos(a), FloatUtil.sin(a), 0);
482 final Vec3f vecExp1 = new Vec3f(-FloatUtil.sin(a), FloatUtil.cos(a), 0);
483 final Vec3f vecExp2 = new Vec3f( 0, 0, 1);
484 final Vec3f vecCol = new Vec3f();
485 mat1.load( new float[] { // Column Order
486 FloatUtil.cos(a), FloatUtil.sin(a), 0, 0, //
487 -FloatUtil.sin(a), FloatUtil.cos(a), 0, 0,
488 0, 0, 1, 0,
489 0, 0, 0, 1 } );
490 mat1.getColumn(0, vecCol);
491 // System.err.println("exp0 "+Arrays.toString(vecExp));
492 // System.err.println("has0 "+Arrays.toString(vecCol))
493 Assert.assertEquals(vecExp0, vecCol);
494 Assert.assertEquals(0f, Math.abs( vecExp0.dist(vecCol)), FloatUtil.EPSILON);
495
496 mat1.getColumn(1, vecCol);
497 Assert.assertEquals(vecExp1, vecCol);
498 Assert.assertEquals(0f, Math.abs( vecExp1.dist(vecCol)), FloatUtil.EPSILON);
499
500 mat1.getColumn(2, vecCol);
501 Assert.assertEquals(vecExp2, vecCol);
502 Assert.assertEquals(0f, Math.abs( vecExp2.dist(vecCol)), FloatUtil.EPSILON);
503 }
504
505 @Test
506 public void test15aAxesAndMatrix() {
507 final Vec3f eulerExp = new Vec3f ( 0f, FloatUtil.HALF_PI, 0f ); // 45 degr on X, 90 degr on Y
508 final Matrix4f matExp1 = new Matrix4f();
509 matExp1.setToRotationEuler(eulerExp.x(), eulerExp.y(), eulerExp.z());
510
511 final Matrix4f matHas = new Matrix4f();;
512 final Quaternion quat1 = new Quaternion();
513 quat1.setFromEuler(eulerExp);
514 quat1.toMatrix(matHas);
515 // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
516 Assert.assertEquals(matExp1, matHas);
517
518 final Vec3f eulerHas = new Vec3f();
519 final Quaternion quat2 = new Quaternion();
520 quat2.setFromMat(matExp1);
521 quat2.toEuler(eulerHas);
522 // System.err.println("exp-euler "+Arrays.toString(eulerExp));
523 // System.err.println("has-euler "+Arrays.toString(eulerHas));
524 Assert.assertEquals(eulerExp, eulerHas);
525
526 Assert.assertEquals(quat2, quat1);
527
528 final Vec3f angles = new Vec3f();
529 quat2.toEuler(angles);
530 quat1.setFromEuler(angles);
531 Assert.assertEquals(quat2, quat1);
532 }
533
534 @Test
535 public void test15bAxesAndMatrix() {
536 final Vec3f eulerExp = new Vec3f(FloatUtil.HALF_PI, 0f, 0f);
537 final Matrix4f matExp = new Matrix4f();
538 matExp.setToRotationEuler(eulerExp.x(), eulerExp.y(), eulerExp.z()); // 45 degr on X, 90 degr on Y (?)
539
540 final Matrix4f matHas = new Matrix4f();
541 final Quaternion quat1 = new Quaternion();
542 quat1.setFromEuler(eulerExp);
543 quat1.toMatrix(matHas);
544 // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
545 Assert.assertEquals(matExp, matHas);
546
547 final Vec3f eulerHas = new Vec3f();
548 final Quaternion quat2 = new Quaternion();
549 quat2.setFromMat(matExp);
550 quat2.toEuler(eulerHas);
551 // System.err.println("exp-euler "+Arrays.toString(eulerExp));
552 // System.err.println("has-euler "+Arrays.toString(eulerHas));
553 Assert.assertEquals(eulerExp, eulerHas);
554
555 Assert.assertEquals(quat2, quat1);
556
557 final Vec3f angles = new Vec3f();
558 quat2.toEuler(angles);
559 quat1.setFromEuler(angles);
560 Assert.assertEquals(quat2, quat1);
561 }
562
563 @Test
564 public void test15cAxesAndMatrix() {
565 final Vec3f eulerExp1 = new Vec3f(FloatUtil.QUARTER_PI, FloatUtil.HALF_PI, 0f); // 45 degr on X, 90 degr on Y
566 final float[] eulerExp0 = new float[3];
567 eulerExp1.get(eulerExp0);
568
569 final Matrix4f matExp = new Matrix4f();
570 matExp.setToRotationEuler(eulerExp1.x(), eulerExp1.y(), eulerExp1.z());
571
572 final Matrix4f matHas = new Matrix4f();
573 final Quaternion quat1 = new Quaternion();
574 quat1.setFromEuler(eulerExp1);
575 quat1.toMatrix(matHas);
576 // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
577 Assert.assertEquals(matExp, matHas);
578
579 final Vec3f eulerHas1 = new Vec3f();
580 final Quaternion quat2 = new Quaternion();
581 quat2.setFromMat(matExp);
582 quat2.toEuler(eulerHas1); // Vec3f
583 if( DEBUG ) {
584 System.err.println("PI");
585 System.err.printf(" double %20.20f%n", Math.PI);
586 System.err.printf(" float %20.20f%n", FloatUtil.PI);
587 System.err.printf(" diff %20.20f%n", (Math.PI - FloatUtil.PI));
588 System.err.println("PI/2");
589 System.err.printf(" double %20.20f%n", Math.PI/2f);
590 System.err.printf(" float %20.20f%n", FloatUtil.HALF_PI);
591 System.err.printf(" diff %20.20f%n", (Math.PI/2f - FloatUtil.HALF_PI));
592
593 System.err.println("exp-euler "+eulerExp1);
594 System.err.println("has-euler1 "+eulerHas1);
595 System.err.println("dif-euler1 "+eulerExp1.minus(eulerHas1));
596 }
597 {
598 final float[] eulerHas0 = new float[3];
599 eulerHas1.get(eulerHas0);
600 Assert.assertArrayEquals(eulerExp0, eulerHas0, FloatUtil.EPSILON);
601 }
602 Assert.assertTrue(eulerExp1+" != "+eulerHas1, eulerExp1.isEqual(eulerHas1, Quaternion.ALLOWED_DEVIANCE));
603 // Assert.assertEquals(eulerExp1, eulerHas1); // `diff < EPSILON` criteria hits, while `Assert.assertArrayEquals(..)` uses `diff <= EPSILON`
604
605 Assert.assertEquals(quat2, quat1);
606
607 final Vec3f angles = new Vec3f();
608 quat2.toEuler(angles);
609 quat1.setFromEuler(angles);
610 Assert.assertEquals(quat2, quat1);
611 }
612
613 //
614 // Functions
615 //
616
617 @Test
618 public void test20AddSubtract() {
619 final Quaternion quatExp1 = new Quaternion(1, 2, 3, 4);
620 final Quaternion quat1 = new Quaternion(0, 1, 2, 3);
621 final Quaternion quat2 = new Quaternion(1, 1, 1, 1);
622
623 final Quaternion quatHas = new Quaternion();
624 quatHas.set(quat1);
625 quatHas.add(quat2); // q3 = q1 + q2
626 Assert.assertEquals(quatExp1, quatHas);
627
628 quat1.set(0, 1, 2, 3);
629 quat2.set(1, 1, 1, 1);
630 quatHas.set(quat1);
631 quatHas.subtract(quat2); // q3 = q1 - q2
632 Assert.assertEquals(new Quaternion(-1, 0, 1, 2), quatHas);
633 }
634
635 @Test
636 public void test21Multiply() {
637 final Quaternion quat1 = new Quaternion(0.5f, 1f, 2f, 3f);
638 final Quaternion quat2 = new Quaternion();
639
640 quat2.set(quat1);
641 quat2.scale(2f); // q2 = q1 * 2f
642 Assert.assertEquals(new Quaternion(1, 2, 4, 6), quat2);
643
644 quat2.set(quat1);
645 quat2.scale(4f); // q2 = q1 * 4f
646 Assert.assertEquals(new Quaternion(2, 4, 8, 12), quat2);
647
648 //
649 // mul and cmp rotated vector
650 //
651 quat1.setFromAngleNormalAxis(FloatUtil.QUARTER_PI, UNIT_Y); // 45 degr on Y
652 quat2.set(quat1);
653 quat2.mult(quat1); // q2 = q1 * q1 -> 2 * 45 degr -> 90 degr on Y
654
655 final Vec3f vecOut = new Vec3f();
656 quat2.rotateVector(UNIT_Z, vecOut);
657 Assert.assertTrue( Math.abs( UNIT_X.dist(vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
658
659 quat2.setFromAngleNormalAxis(FloatUtil.HALF_PI, UNIT_Y); // 90 degr on Y
660 quat1.mult(quat1); // q1 = q1 * q1 -> 2 * 45 degr -> 90 degr on Y
661 quat1.mult(quat2); // q1 = q1 * q2 -> 2 * 90 degr -> 180 degr on Y
662 quat1.rotateVector(UNIT_Z, vecOut);
663 Assert.assertTrue( Math.abs( NEG_UNIT_Z.dist(vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
664
665 quat2.setFromEuler(0f, FloatUtil.HALF_PI, 0f);
666 quat1.mult(quat2); // q1 = q1 * q2 = q1 * rotMat(0, 90degr, 0)
667 quat1.rotateVector(UNIT_Z, vecOut);
668 Assert.assertTrue( Math.abs( NEG_UNIT_X.dist(vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
669 }
670
671 @Test
673 final Quaternion quat0 = new Quaternion(0, 1, 2, 3);
674 final Quaternion quat1 = new Quaternion(quat0);
675 final Quaternion quat2 = new Quaternion(quat0);
676 quat1.invert(); // q1 = invert(q0)
677 quat2.mult(quat1); // q2 = q0 * q1 = q0 * invert(q0)
678 Assert.assertEquals(QUAT_IDENT, quat2);
679 quat1.invert();
680 Assert.assertEquals(quat0, quat1);
681
682 // normalized version
684 quat1.set(quat0);
685 quat1.invert(); // q1 = invert(q0)
686 quat2.set(quat0);
687 quat2.mult(quat1); // q2 = q0 * q1 = q0 * invert(q0)
688 Assert.assertEquals(QUAT_IDENT, quat2);
689 quat1.invert();
690 Assert.assertEquals(quat0, quat1);
691
692 // conjugate check
693 quat0.set(-1f, -2f, -3f, 4f);
694 quat1.set( 1f, 2f, 3f, 4f);
695 quat2.set(quat1);
696 quat2.conjugate();
697 Assert.assertEquals(quat0, quat2);
698 }
699
700 @Test
701 public void test23RotationOrder() {
702 {
703 final Quaternion quat1 = new Quaternion().setFromEuler( -2f*FloatUtil.HALF_PI, 0f, 0f); // -180 degr X
704 final Quaternion quat2 = new Quaternion().rotateByAngleX( -2f * FloatUtil.HALF_PI); // angle: -180 degrees, axis X
705 Assert.assertEquals(quat1, quat2);
706 }
707 {
708 final Quaternion quat1 = new Quaternion().setFromEuler( FloatUtil.HALF_PI, 0f, 0f); // 90 degr X
709 final Quaternion quat2 = new Quaternion().rotateByAngleX( FloatUtil.HALF_PI); // angle: 90 degrees, axis X
710 Assert.assertEquals(quat1, quat2);
711 }
712 {
715 Assert.assertEquals(quat1, quat2);
716 }
717 {
720 Assert.assertEquals(quat1, quat2);
721 }
722
723
724 final Vec3f vecExp = new Vec3f();
725 final Vec3f vecRot = new Vec3f();
726 final Quaternion quat = new Quaternion();
727
728 // Try a new way with new angles...
730 vecRot.set(1f, 1f, 1f);
731 quat.rotateVector(vecRot, vecRot);
732
733 // expected
734 vecExp.set(1f, 1f, 1f);
735 final Quaternion worker = new Quaternion();
736 // put together matrix, then apply to vector, so YZX
738 quat.rotateVector(vecExp, vecExp);
739 Assert.assertEquals(0f, vecExp.dist(vecRot), FloatUtil.EPSILON);
740 Assert.assertEquals(vecExp, vecRot);
741
742 // test axis rotation methods against general purpose
743 // X AXIS
744 vecExp.set(1f, 1f, 1f);
745 vecRot.set(1f, 1f, 1f);
747 worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 1f, 0f, 0f).rotateVector(vecRot, vecRot);
748 // System.err.println("exp0 "+Arrays.toString(vecExp)+", len "+VectorUtil.length(vecExp));
749 // System.err.println("has0 "+Arrays.toString(vecRot)+", len "+VectorUtil.length(vecRot));
750 Assert.assertEquals(0f, vecExp.dist(vecRot), FloatUtil.EPSILON);
751 Assert.assertEquals(vecExp, vecRot);
752
753 // Y AXIS
754 vecExp.set(1f, 1f, 1f);
755 vecRot.set(1f, 1f, 1f);
757 worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 0f, 1f, 0f).rotateVector(vecRot, vecRot);
758 // System.err.println("exp0 "+Arrays.toString(vecExp));
759 // System.err.println("has0 "+Arrays.toString(vecRot));
760 Assert.assertEquals(0f, vecExp.dist(vecRot), FloatUtil.EPSILON);
761 Assert.assertEquals(vecExp, vecRot);
762
763 // Z AXIS
764 vecExp.set(1f, 1f, 1f);
765 vecRot.set(1f, 1f, 1f);
767 worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 0f, 0f, 1f).rotateVector(vecRot, vecRot);
768 // System.err.println("exp0 "+Arrays.toString(vecExp));
769 // System.err.println("has0 "+Arrays.toString(vecRot));
770 Assert.assertEquals(0f, vecExp.dist(vecRot), FloatUtil.EPSILON);
771 Assert.assertEquals(vecExp, vecRot);
772
773 quat.set(worker);
774 worker.rotateByAngleNormalAxis(0f, 0f, 0f, 0f);
775 Assert.assertEquals(quat, worker);
776 }
777
778 @Test
779 public void test24Axes() {
781 final Matrix4f rotMat = new Matrix4f();
782 quat0.toMatrix(rotMat);
783 final Vec3f xAxis = new Vec3f();
784 final Vec3f yAxis = new Vec3f();
785 final Vec3f zAxis = new Vec3f();
786 rotMat.getColumn(0, xAxis);
787 rotMat.getColumn(1, yAxis);
788 rotMat.getColumn(2, zAxis);
789
790 final Quaternion quat1 = new Quaternion().setFromAxes(xAxis, yAxis, zAxis);
791 Assert.assertEquals(quat0, quat1);
792 final Quaternion quat2 = new Quaternion().setFromMat(rotMat);
793 Assert.assertEquals(quat2, quat1);
794
795 quat1.toAxes(xAxis, yAxis, zAxis, rotMat);
796 quat2.setFromAxes(xAxis, yAxis, zAxis);
797 Assert.assertEquals(quat0, quat2);
798 Assert.assertEquals(quat1, quat2);
799 }
800
801 @Test
802 public void test25Slerp() {
803 final Quaternion quat1 = new Quaternion(); // angle: 0 degrees
804 final Quaternion quat2 = new Quaternion().rotateByAngleY(FloatUtil.HALF_PI); // angle: 90 degrees, axis Y
805
807 final Vec3f vecHas = new Vec3f();
808 final Quaternion quatS = new Quaternion();
809 // System.err.println("Slerp #01: 1/2 * 90 degrees Y");
810 quatS.setSlerp(quat1, quat2, 0.5f);
811 quatS.rotateVector(UNIT_Z, vecHas);
812 // System.err.println("exp0 "+Arrays.toString(vecExp));
813 // System.err.println("has0 "+Arrays.toString(vecHas));
814 Assert.assertEquals( 0f, Math.abs( vecExp.dist(vecHas)), Quaternion.ALLOWED_DEVIANCE);
815 if( !vecExp.equals(vecHas) ) {
816 System.err.println("Deviance: "+vecExp+", "+vecHas+": "+vecExp.minus(vecHas)+", dist "+vecExp.dist(vecHas));
817 }
818 // Assert.assertEquals(vecExp, vecHas);
819
820 // delta == 100%
821 quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
822 // System.err.println("Slerp #02: 1 * 180 degrees Z");
823 quatS.setSlerp(quat1, quat2, 1.0f);
824 quatS.rotateVector(UNIT_X, vecHas);
825 // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
826 // System.err.println("has0 "+Arrays.toString(vecHas));
827 Assert.assertEquals( 0f, Math.abs( NEG_UNIT_X.dist(vecHas)), Quaternion.ALLOWED_DEVIANCE);
828 Assert.assertEquals(NEG_UNIT_X, vecHas);
829
830 quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
831 // System.err.println("Slerp #03: 1/2 * 180 degrees Z");
832 quatS.setSlerp(quat1, quat2, 0.5f);
833 quatS.rotateVector(UNIT_X, vecHas);
834 // System.err.println("exp0 "+Arrays.toString(UNIT_Y));
835 // System.err.println("has0 "+Arrays.toString(vecHas));
836 Assert.assertEquals( 0f, Math.abs( UNIT_Y.dist(vecHas)), Quaternion.ALLOWED_DEVIANCE);
837 if( !UNIT_Y.equals(vecHas) ) {
838 System.err.println("Deviance: "+UNIT_Y+", "+vecHas+": "+UNIT_Y.minus(vecHas)+", dist "+UNIT_Y.dist(vecHas));
839 }
840 // Assert.assertEquals(UNIT_Y, vecHas);
841
842 // delta == 0%
843 quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
844 // System.err.println("Slerp #04: 0 * 180 degrees Z");
845 quatS.setSlerp(quat1, quat2, 0.0f);
846 quatS.rotateVector(UNIT_X, vecHas);
847 // System.err.println("exp0 "+Arrays.toString(UNIT_X));
848 // System.err.println("has0 "+Arrays.toString(vecHas));
849 Assert.assertEquals( 0f, Math.abs( UNIT_X.dist(vecHas)), Quaternion.ALLOWED_DEVIANCE);
850 Assert.assertEquals(UNIT_X, vecHas);
851
852 // a==b
853 quat2.setIdentity();
854 // System.err.println("Slerp #05: 1/4 * 0 degrees");
855 quatS.setSlerp(quat1, quat2, 0.25f); // 1/4 of identity .. NOP
856 quatS.rotateVector(UNIT_X, vecHas);
857 // System.err.println("exp0 "+Arrays.toString(UNIT_X));
858 // System.err.println("has0 "+Arrays.toString(vecHas));
859 Assert.assertEquals( 0f, Math.abs( UNIT_X.dist(vecHas)), Quaternion.ALLOWED_DEVIANCE);
860 Assert.assertEquals(UNIT_X, vecHas);
861
862 // negative dot product
864 quat1.setIdentity().rotateByAngleX( -2f * FloatUtil.HALF_PI); // angle: -180 degrees, axis X
865 quat2.setIdentity().rotateByAngleX( FloatUtil.HALF_PI); // angle: 90 degrees, axis X
866 // System.err.println("Slerp #06: 1/2 * 270 degrees");
867 quatS.setSlerp(quat1, quat2, 0.5f);
868 quatS.rotateVector(UNIT_Y, vecHas);
869 // System.err.println("exp0 "+Arrays.toString(vecExp));
870 // System.err.println("has0 "+Arrays.toString(vecHas));
871 Assert.assertEquals( 0f, Math.abs( vecExp.dist(vecHas) ), Quaternion.ALLOWED_DEVIANCE);
872 if( !vecExp.equals(vecHas) ) {
873 System.err.println("Deviance: "+vecExp+", "+vecHas+": "+vecExp.minus(vecHas)+", dist "+vecExp.dist(vecHas));
874 }
875 // Assert.assertEquals(vecExp, vecHas);
876 }
877
878 @Test
879 public void test26LookAt() {
880 final Vec3f direction = new Vec3f();
881 final Vec3f xAxis = new Vec3f();
882 final Vec3f yAxis = new Vec3f();
883 final Vec3f zAxis = new Vec3f();
884 final Vec3f vecHas = new Vec3f();
885
886 if( DEBUG ) System.err.println("LookAt #01");
887 direction.set(NEG_UNIT_X);
888 final Quaternion quat = new Quaternion().setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
889 Assert.assertEquals(0f, direction.dist( quat.rotateVector(UNIT_Z, vecHas) ), Quaternion.ALLOWED_DEVIANCE);
890 Assert.assertEquals(direction, vecHas);
891
892 if( DEBUG ) {
893 System.err.println("quat0.0 "+quat);
894 System.err.println("exp0 "+direction+", len "+direction.length());
895 System.err.println("has0 "+vecHas+", len "+vecHas.length());
896 System.err.println();
897 System.err.println("LookAt #02");
898 }
899 direction.set(ONE).normalize();
900 quat.setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
901 if( DEBUG ) {
902 System.err.println("direction "+direction);
903 System.err.println("quat0.0 "+quat);
904 }
905 quat.rotateVector(UNIT_Z, vecHas);
906 if( DEBUG ) {
907 System.err.println("quat0.1 "+quat);
908 System.err.println("xAxis "+xAxis+", len "+xAxis.length());
909 System.err.println("yAxis "+yAxis+", len "+yAxis.length());
910 System.err.println("zAxis "+zAxis+", len "+zAxis.length());
911 System.err.println("exp0 "+direction+", len "+direction.length());
912 System.err.println("has0 "+vecHas+", len "+vecHas.length());
913 }
914 // Assert.assertEquals(0f, VectorUtil.distance(direction, quat.rotateVector(vecHas, 0, UNIT_Z, 0)), Quaternion.ALLOWED_DEVIANCE);
915 Assert.assertEquals(0f, direction.dist(vecHas), Quaternion.ALLOWED_DEVIANCE);
916 Assert.assertEquals(direction, vecHas);
917
918 if( DEBUG )System.err.println("LookAt #03");
919 direction.set(-1f, 2f, -1f).normalize();
920 quat.setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
921 if( DEBUG )System.err.println("quat0 "+quat);
922 quat.rotateVector(UNIT_Z, vecHas);
923 if( DEBUG ) {
924 System.err.println("xAxis "+xAxis+", len "+xAxis.length());
925 System.err.println("yAxis "+yAxis+", len "+yAxis.length());
926 System.err.println("zAxis "+zAxis+", len "+zAxis.length());
927 System.err.println("exp0 "+direction+", len "+direction.length());
928 System.err.println("has0 "+vecHas+", len "+vecHas.length());
929 }
930 // Assert.assertEquals(0f, VectorUtil.distance(direction, quat.rotateVector(vecHas, 0, UNIT_Z, 0)), Quaternion.ALLOWED_DEVIANCE);
931 Assert.assertEquals(0f, direction.dist(vecHas), Quaternion.ALLOWED_DEVIANCE);
932 if( !direction.equals(vecHas) ) {
933 System.err.println("Deviance: "+direction+", "+vecHas+": "+direction.minus(vecHas)+", dist "+direction.dist(vecHas));
934 }
935 // Assert.assertEquals(direction, vecHas);
936 }
937
938 public static void main(final String args[]) {
939 org.junit.runner.JUnitCore.main(TestQuaternion01NOUI.class.getName());
940 }
941}
Basic Float math utility functions.
Definition: FloatUtil.java:83
static float sin(final float a)
static final float QUARTER_PI
The value PI/4, i.e.
static final float PI
The value PI, i.e.
static final float EPSILON
Epsilon for floating point {@value}, as once computed via getMachineEpsilon() on an AMD-64 CPU.
static void multMatrixVec(final float[] m_in, final int m_in_off, final float[] v_in, final int v_in_off, final float[] v_out, final int v_out_off)
static float cos(final float a)
static float[] multMatrixVec3(final float[] m_in, final float[] v_in, final float[] v_out)
Affine 3f-vector transformation by 4x4 matrix.
static final float HALF_PI
The value PI/2, i.e.
Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
Definition: Matrix4f.java:89
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
final Vec3f mulVec3f(final Vec3f v_in, final Vec3f v_out)
Affine 3f-vector transformation by 4x4 matrix.
Definition: Matrix4f.java:841
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
float get(final int i)
Gets the ith component, 0 <= i < 16.
Definition: Matrix4f.java:279
final Quaternion getRotation(final Quaternion res)
Returns the rotation [m00 .
Definition: Matrix4f.java:1185
final Vec4f mulVec4f(final Vec4f v_in, final Vec4f v_out)
Definition: Matrix4f.java:806
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
Quaternion implementation supporting Gimbal-Lock free rotations.
Definition: Quaternion.java:45
final float dot(final float x, final float y, final float z, final float w)
Returns the dot product of this quaternion with the given x,y,z and w components.
final Vec3f rotateVector(final Vec3f vecIn, final Vec3f vecOut)
Quaternion conjugate()
Conjugates this quaternion [-x, -y, -z, w].
final Quaternion invert()
Invert the quaternion If rotational, will produce a the inverse rotation.
final Quaternion setFromNormalVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec)
Initialize this quaternion from two normalized vectors.
final Quaternion scale(final float n)
Scale this quaternion by a constant.
Vec3f toEuler(final Vec3f result)
Transform this quaternion to Euler rotation angles in radians (pitchX, yawY and rollZ).
final Quaternion set(final Quaternion src)
Set all values of this quaternion using the given src.
final Quaternion setFromEuler(final Vec3f angradXYZ)
Initializes this quaternion from the given Euler rotation array angradXYZ in radians.
final Quaternion setSlerp(final Quaternion a, final Quaternion b, final float changeAmnt)
Set this quaternion to a spherical linear interpolation between the given start and end quaternions b...
Quaternion rotateByAngleNormalAxis(final float angle, final float axisX, final float axisY, final float axisZ)
Rotate this quaternion by the given angle and axis.
final Quaternion setFromAngleNormalAxis(final float angle, final Vec3f vector)
final Quaternion setFromAngleAxis(final float angle, final Vec3f vector, final Vec3f tmpV3f)
static final float ALLOWED_DEVIANCE
Quaternion Epsilon, used with equals method to determine if two Quaternions are close enough to be co...
Definition: Quaternion.java:54
Quaternion rotateByAngleY(final float angle)
Rotate this quaternion around Y axis with the given angle in radians.
Quaternion rotateByAngleZ(final float angle)
Rotate this quaternion around Z axis with the given angle in radians.
final Quaternion setFromAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis)
Initializes this quaternion to represent a rotation formed by the given three orthogonal axes.
final float toAngleAxis(final Vec3f axis)
Transform the rotational quaternion to axis based rotation angles.
final Quaternion subtract(final Quaternion q)
Subtract a quaternion.
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.
final Quaternion setFromVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec, final Vec3f tmpNormalVec)
Initialize this quaternion from two vectors.
final float[] toMatrix(final float[] matrix)
Transform this quaternion to a normalized 4x4 column matrix representing the rotation.
void toAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis, final Matrix4f tmpMat4)
Extracts this quaternion's orthogonal rotation axes.
Quaternion setLookAt(final Vec3f directionIn, final Vec3f upIn, final Vec3f xAxisOut, final Vec3f yAxisOut, final Vec3f zAxisOut)
Set this quaternion to equal the rotation required to point the z-axis at direction and the y-axis to...
final float magnitude()
Return the magnitude of this quaternion, i.e.
Definition: Quaternion.java:93
final Quaternion mult(final Quaternion q)
Multiply this quaternion by the param quaternion.
final Quaternion setIdentity()
final Quaternion normalize()
Normalize a quaternion required if to be used as a rotational quaternion.
final Quaternion add(final Quaternion q)
Add a quaternion.
Quaternion rotateByAngleX(final float angle)
Rotate this quaternion around X axis with the given angle in radians.
3D Vector based upon three float components.
Definition: Vec3f.java:37
static final Vec3f ONE
Definition: Vec3f.java:38
static final Vec3f UNIT_Y_NEG
Definition: Vec3f.java:42
boolean equals(final Object o)
Definition: Vec3f.java:416
Vec3f normalize()
Normalize this vector in place.
Definition: Vec3f.java:297
boolean isEqual(final Vec3f o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
Definition: Vec3f.java:383
float dist(final Vec3f o)
Return the distance between this vector and the given one.
Definition: Vec3f.java:329
float length()
Return the length of this vector, a.k.a the norm or magnitude
Definition: Vec3f.java:283
float[] get(final float[] xyz)
xyz = this, returns xyz.
Definition: Vec3f.java:137
Vec3f minus(final Vec3f arg)
Returns this - arg; creates new vector.
Definition: Vec3f.java:255
static final Vec3f UNIT_Z
Definition: Vec3f.java:43
Vec3f set(final Vec3f o)
this = o, returns this.
Definition: Vec3f.java:79
4D Vector based upon four float components.
Definition: Vec4f.java:37
float[] get(final float[] xyzw)
xyzw = this, returns xyzw.
Definition: Vec4f.java:123
static float distVec3(final float[] v1, final float[] v2)
Return the distance between the given two points described vector v1 and v2.
Definition: VectorUtil.java:84