001/** 002 * Copyright (c) 2008-2014 Ardor Labs, Inc. 003 * 004 * This file is part of Ardor3D. 005 * 006 * Ardor3D is free software: you can redistribute it and/or modify it 007 * under the terms of its license which may be found in the accompanying 008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>. 009 */ 010 011package com.ardor3d.math; 012 013import static org.junit.Assert.*; 014 015import java.nio.DoubleBuffer; 016import java.nio.FloatBuffer; 017 018import org.junit.Test; 019 020public class TestMatrix4 { 021 022 @Test 023 public void testGetSet() { 024 final Matrix4 mat4A = new Matrix4(); 025 assertEquals(Matrix4.IDENTITY, mat4A); 026 027 mat4A.setM00(0.0); 028 mat4A.setM01(0.1); 029 mat4A.setM02(0.2); 030 mat4A.setM03(0.3); 031 mat4A.setM10(1.0); 032 mat4A.setM11(1.1); 033 mat4A.setM12(1.2); 034 mat4A.setM13(1.3); 035 mat4A.setM20(2.0); 036 mat4A.setM21(2.1); 037 mat4A.setM22(2.2); 038 mat4A.setM23(2.3); 039 mat4A.setM30(3.0); 040 mat4A.setM31(3.1); 041 mat4A.setM32(3.2); 042 mat4A.setM33(3.3); 043 044 assertTrue(0.0 == mat4A.getM00()); 045 assertTrue(0.1 == mat4A.getM01()); 046 assertTrue(0.2 == mat4A.getM02()); 047 assertTrue(0.3 == mat4A.getM03()); 048 assertTrue(1.0 == mat4A.getM10()); 049 assertTrue(1.1 == mat4A.getM11()); 050 assertTrue(1.2 == mat4A.getM12()); 051 assertTrue(1.3 == mat4A.getM13()); 052 assertTrue(2.0 == mat4A.getM20()); 053 assertTrue(2.1 == mat4A.getM21()); 054 assertTrue(2.2 == mat4A.getM22()); 055 assertTrue(2.3 == mat4A.getM23()); 056 assertTrue(3.0 == mat4A.getM30()); 057 assertTrue(3.1 == mat4A.getM31()); 058 assertTrue(3.2 == mat4A.getM32()); 059 assertTrue(3.3 == mat4A.getM33()); 060 061 final Matrix4 mat4B = new Matrix4(mat4A); 062 assertTrue(0.0 == mat4B.getM00()); 063 assertTrue(0.1 == mat4B.getM01()); 064 assertTrue(0.2 == mat4B.getM02()); 065 assertTrue(0.3 == mat4B.getM03()); 066 assertTrue(1.0 == mat4B.getM10()); 067 assertTrue(1.1 == mat4B.getM11()); 068 assertTrue(1.2 == mat4B.getM12()); 069 assertTrue(1.3 == mat4B.getM13()); 070 assertTrue(2.0 == mat4B.getM20()); 071 assertTrue(2.1 == mat4B.getM21()); 072 assertTrue(2.2 == mat4B.getM22()); 073 assertTrue(2.3 == mat4B.getM23()); 074 assertTrue(3.0 == mat4B.getM30()); 075 assertTrue(3.1 == mat4B.getM31()); 076 assertTrue(3.2 == mat4B.getM32()); 077 assertTrue(3.3 == mat4B.getM33()); 078 079 final Matrix4 mat4C = new Matrix4(0.0, 0.1, 0.2, 0.3, 1.0, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2, 2.3, 3.0, 3.1, 3.2, 080 3.3); 081 assertTrue(0.0 == mat4C.getM00()); 082 assertTrue(0.1 == mat4C.getM01()); 083 assertTrue(0.2 == mat4C.getM02()); 084 assertTrue(0.3 == mat4C.getM03()); 085 assertTrue(1.0 == mat4C.getM10()); 086 assertTrue(1.1 == mat4C.getM11()); 087 assertTrue(1.2 == mat4C.getM12()); 088 assertTrue(1.3 == mat4C.getM13()); 089 assertTrue(2.0 == mat4C.getM20()); 090 assertTrue(2.1 == mat4C.getM21()); 091 assertTrue(2.2 == mat4C.getM22()); 092 assertTrue(2.3 == mat4C.getM23()); 093 assertTrue(3.0 == mat4C.getM30()); 094 assertTrue(3.1 == mat4C.getM31()); 095 assertTrue(3.2 == mat4C.getM32()); 096 assertTrue(3.3 == mat4C.getM33()); 097 098 mat4C.setIdentity(); 099 assertTrue(mat4C.isIdentity()); 100 101 for (int x = 0; x < 4; x++) { 102 for (int y = 0; y < 4; y++) { 103 final double value = (10 * x + y) / 10.; 104 mat4C.setValue(x, y, value); 105 assertTrue(value == mat4C.getValue(x, y)); 106 } 107 } 108 109 mat4C.setIdentity(); 110 mat4C.set(0.0, 0.1, 0.2, 0.3, 2.0, 2.1, 2.2, 2.3, 4.0, 4.1, 4.2, 4.3, 6.0, 6.1, 6.2, 6.3); 111 for (int x = 0; x < 4; x++) { 112 for (int y = 0; y < 4; y++) { 113 assertTrue((20 * x + y) / 10.f == mat4C.getValuef(x, y)); 114 } 115 } 116 117 final Matrix4 store = new Matrix4(mat4C); 118 // catch a few expected exceptions 119 try { 120 mat4C.getValue(-1, 0); 121 fail("getValue(-1, 0) should have thrown IllegalArgumentException."); 122 } catch (final IllegalArgumentException e) { 123 } 124 try { 125 mat4C.getValue(0, 4); 126 fail("getValue(0, 4) should have thrown IllegalArgumentException."); 127 } catch (final IllegalArgumentException e) { 128 } 129 try { 130 mat4C.getValue(1, -1); 131 fail("getValue(1, -1) should have thrown IllegalArgumentException."); 132 } catch (final IllegalArgumentException e) { 133 } 134 try { 135 mat4C.getValue(2, 4); 136 fail("getValue(2, 4) should have thrown IllegalArgumentException."); 137 } catch (final IllegalArgumentException e) { 138 } 139 try { 140 mat4C.getValue(3, -1); 141 fail("getValue(3, -1) should have thrown IllegalArgumentException."); 142 } catch (final IllegalArgumentException e) { 143 } 144 try { 145 mat4C.getValue(4, 0); 146 fail("getValue(4, 0) should have thrown IllegalArgumentException."); 147 } catch (final IllegalArgumentException e) { 148 } 149 150 try { 151 mat4C.setValue(-1, 0, 0); 152 fail("setValue(-1, 0, 0) should have thrown IllegalArgumentException."); 153 } catch (final IllegalArgumentException e) { 154 } 155 try { 156 mat4C.setValue(0, -1, 0); 157 fail("setValue(0, -1, 0) should have thrown IllegalArgumentException."); 158 } catch (final IllegalArgumentException e) { 159 } 160 try { 161 mat4C.setValue(1, 4, 0); 162 fail("setValue(1, 4, 0) should have thrown IllegalArgumentException."); 163 } catch (final IllegalArgumentException e) { 164 } 165 try { 166 mat4C.setValue(2, -1, 0); 167 fail("setValue(2, -1, 0) should have thrown IllegalArgumentException."); 168 } catch (final IllegalArgumentException e) { 169 } 170 try { 171 mat4C.setValue(3, 4, 0); 172 fail("setValue(3, 4, 0) should have thrown IllegalArgumentException."); 173 } catch (final IllegalArgumentException e) { 174 } 175 try { 176 mat4C.setValue(4, 0, 0); 177 fail("setValue(4, 0, 0) should have thrown IllegalArgumentException."); 178 } catch (final IllegalArgumentException e) { 179 } 180 // above exceptions shouldn't have altered mat4C 181 assertEquals(store, mat4C); 182 } 183 184 @Test 185 public void testColumns() { 186 final Matrix4 mat4A = new Matrix4(); 187 mat4A.setColumn(0, new Vector4(0, 4, 8, 12)); 188 mat4A.setColumn(1, new Vector4(1, 5, 9, 13)); 189 mat4A.setColumn(2, new Vector4(2, 6, 10, 14)); 190 mat4A.setColumn(3, new Vector4(3, 7, 11, 15)); 191 assertEquals(new Vector4(0, 4, 8, 12), mat4A.getColumn(0, new Vector4())); 192 assertEquals(new Vector4(1, 5, 9, 13), mat4A.getColumn(1, null)); 193 assertEquals(new Vector4(2, 6, 10, 14), mat4A.getColumn(2, null)); 194 assertEquals(new Vector4(3, 7, 11, 15), mat4A.getColumn(3, null)); 195 try { 196 mat4A.getColumn(-1, null); 197 fail("getColumn(-1, null) should have thrown IllegalArgumentException."); 198 } catch (final IllegalArgumentException e) { 199 } 200 try { 201 mat4A.getColumn(4, null); 202 fail("getColumn(4, null) should have thrown IllegalArgumentException."); 203 } catch (final IllegalArgumentException e) { 204 } 205 try { 206 mat4A.setColumn(-1, new Vector4()); 207 fail("setColumn(-1, double[]) should have thrown IllegalArgumentException."); 208 } catch (final IllegalArgumentException e) { 209 } 210 try { 211 mat4A.setColumn(4, new Vector4()); 212 fail("setColumn(4, double[]) should have thrown IllegalArgumentException."); 213 } catch (final IllegalArgumentException e) { 214 } 215 } 216 217 @Test 218 public void testRows() { 219 final Matrix4 mat4A = new Matrix4(); 220 mat4A.setRow(0, new Vector4(0, 1, 2, 3)); 221 mat4A.setRow(1, new Vector4(4, 5, 6, 7)); 222 mat4A.setRow(2, new Vector4(8, 9, 10, 11)); 223 mat4A.setRow(3, new Vector4(12, 13, 14, 15)); 224 assertEquals(new Vector4(0, 1, 2, 3), mat4A.getRow(0, new Vector4())); 225 assertEquals(new Vector4(4, 5, 6, 7), mat4A.getRow(1, null)); 226 assertEquals(new Vector4(8, 9, 10, 11), mat4A.getRow(2, null)); 227 assertEquals(new Vector4(12, 13, 14, 15), mat4A.getRow(3, null)); 228 try { 229 mat4A.getRow(-1, null); 230 fail("getRow(-1, null) should have thrown IllegalArgumentException."); 231 } catch (final IllegalArgumentException e) { 232 } 233 try { 234 mat4A.getRow(4, null); 235 fail("getRow(4, null) should have thrown IllegalArgumentException."); 236 } catch (final IllegalArgumentException e) { 237 } 238 try { 239 mat4A.setRow(-1, new Vector4()); 240 fail("setRow(-1, double[]) should have thrown IllegalArgumentException."); 241 } catch (final IllegalArgumentException e) { 242 } 243 try { 244 mat4A.setRow(4, new Vector4()); 245 fail("setRow(4, double[]) should have thrown IllegalArgumentException."); 246 } catch (final IllegalArgumentException e) { 247 } 248 } 249 250 @Test 251 public void testSetRotation() { 252 final Matrix4 mat4A = new Matrix4(0.0, 0.1, 0.2, 0.3, 1.0, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2, 2.3, 3.0, 3.1, 3.2, 253 3.3); 254 mat4A.set(Matrix3.IDENTITY); 255 assertTrue(1.0 == mat4A.getM00()); 256 assertTrue(0.0 == mat4A.getM01()); 257 assertTrue(0.0 == mat4A.getM02()); 258 assertTrue(0.3 == mat4A.getM03()); 259 assertTrue(0.0 == mat4A.getM10()); 260 assertTrue(1.0 == mat4A.getM11()); 261 assertTrue(0.0 == mat4A.getM12()); 262 assertTrue(1.3 == mat4A.getM13()); 263 assertTrue(0.0 == mat4A.getM20()); 264 assertTrue(0.0 == mat4A.getM21()); 265 assertTrue(1.0 == mat4A.getM22()); 266 assertTrue(2.3 == mat4A.getM23()); 267 assertTrue(3.0 == mat4A.getM30()); 268 assertTrue(3.1 == mat4A.getM31()); 269 assertTrue(3.2 == mat4A.getM32()); 270 assertTrue(3.3 == mat4A.getM33()); 271 272 mat4A.setIdentity(); 273 // rotate identity 90 degrees around Y 274 final double a = MathUtils.HALF_PI; 275 final Quaternion quaternion = new Quaternion(); 276 quaternion.fromAngleAxis(a, Vector3.UNIT_Y); 277 mat4A.set(quaternion); 278 279 assertEquals(new Matrix4( // 280 Math.cos(a), 0, Math.sin(a), 0, // 281 0, 1, 0, 0, // 282 -Math.sin(a), 0, Math.cos(a), 0, // 283 0, 0, 0, 1), mat4A); 284 } 285 286 @Test 287 public void testFromBuffer() { 288 final FloatBuffer fb = FloatBuffer.allocate(16); 289 fb.put(new float[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }); 290 fb.flip(); 291 // row major 292 final Matrix4 mat4A = new Matrix4().fromFloatBuffer(fb); 293 assertTrue(0 == mat4A.getM00()); 294 assertTrue(1 == mat4A.getM01()); 295 assertTrue(2 == mat4A.getM02()); 296 assertTrue(3 == mat4A.getM03()); 297 assertTrue(4 == mat4A.getM10()); 298 assertTrue(5 == mat4A.getM11()); 299 assertTrue(6 == mat4A.getM12()); 300 assertTrue(7 == mat4A.getM13()); 301 assertTrue(8 == mat4A.getM20()); 302 assertTrue(9 == mat4A.getM21()); 303 assertTrue(10 == mat4A.getM22()); 304 assertTrue(11 == mat4A.getM23()); 305 assertTrue(12 == mat4A.getM30()); 306 assertTrue(13 == mat4A.getM31()); 307 assertTrue(14 == mat4A.getM32()); 308 assertTrue(15 == mat4A.getM33()); 309 310 // column major 311 fb.rewind(); 312 mat4A.setIdentity(); 313 mat4A.fromFloatBuffer(fb, false); 314 assertTrue(0 == mat4A.getM00()); 315 assertTrue(4 == mat4A.getM01()); 316 assertTrue(8 == mat4A.getM02()); 317 assertTrue(12 == mat4A.getM03()); 318 assertTrue(1 == mat4A.getM10()); 319 assertTrue(5 == mat4A.getM11()); 320 assertTrue(9 == mat4A.getM12()); 321 assertTrue(13 == mat4A.getM13()); 322 assertTrue(2 == mat4A.getM20()); 323 assertTrue(6 == mat4A.getM21()); 324 assertTrue(10 == mat4A.getM22()); 325 assertTrue(14 == mat4A.getM23()); 326 assertTrue(3 == mat4A.getM30()); 327 assertTrue(7 == mat4A.getM31()); 328 assertTrue(11 == mat4A.getM32()); 329 assertTrue(15 == mat4A.getM33()); 330 331 final DoubleBuffer db = DoubleBuffer.allocate(16); 332 db.put(new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }); 333 db.flip(); 334 // row major 335 mat4A.setIdentity(); 336 mat4A.fromDoubleBuffer(db); 337 assertTrue(0 == mat4A.getM00()); 338 assertTrue(1 == mat4A.getM01()); 339 assertTrue(2 == mat4A.getM02()); 340 assertTrue(3 == mat4A.getM03()); 341 assertTrue(4 == mat4A.getM10()); 342 assertTrue(5 == mat4A.getM11()); 343 assertTrue(6 == mat4A.getM12()); 344 assertTrue(7 == mat4A.getM13()); 345 assertTrue(8 == mat4A.getM20()); 346 assertTrue(9 == mat4A.getM21()); 347 assertTrue(10 == mat4A.getM22()); 348 assertTrue(11 == mat4A.getM23()); 349 assertTrue(12 == mat4A.getM30()); 350 assertTrue(13 == mat4A.getM31()); 351 assertTrue(14 == mat4A.getM32()); 352 assertTrue(15 == mat4A.getM33()); 353 354 // column major 355 db.rewind(); 356 mat4A.setIdentity(); 357 mat4A.fromDoubleBuffer(db, false); 358 assertTrue(0 == mat4A.getM00()); 359 assertTrue(4 == mat4A.getM01()); 360 assertTrue(8 == mat4A.getM02()); 361 assertTrue(12 == mat4A.getM03()); 362 assertTrue(1 == mat4A.getM10()); 363 assertTrue(5 == mat4A.getM11()); 364 assertTrue(9 == mat4A.getM12()); 365 assertTrue(13 == mat4A.getM13()); 366 assertTrue(2 == mat4A.getM20()); 367 assertTrue(6 == mat4A.getM21()); 368 assertTrue(10 == mat4A.getM22()); 369 assertTrue(14 == mat4A.getM23()); 370 assertTrue(3 == mat4A.getM30()); 371 assertTrue(7 == mat4A.getM31()); 372 assertTrue(11 == mat4A.getM32()); 373 assertTrue(15 == mat4A.getM33()); 374 } 375 376 @Test 377 public void testToBuffer() { 378 final double[] values = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 379 final double[] colmajor = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; 380 381 final Matrix4 mat4A = new Matrix4().fromArray(values); 382 383 // row major 384 final FloatBuffer fb = mat4A.toFloatBuffer(FloatBuffer.allocate(16)); 385 fb.flip(); 386 for (int i = 0; i < 16; i++) { 387 assertTrue(values[i] == fb.get()); 388 } 389 390 // column major 391 fb.rewind(); 392 mat4A.toFloatBuffer(fb, false); 393 fb.flip(); 394 for (int i = 0; i < 16; i++) { 395 assertTrue(colmajor[i] == fb.get()); 396 } 397 398 // row major 399 final DoubleBuffer db = mat4A.toDoubleBuffer(DoubleBuffer.allocate(16)); 400 db.flip(); 401 for (int i = 0; i < 16; i++) { 402 assertTrue(values[i] == db.get()); 403 } 404 405 // column major 406 db.rewind(); 407 mat4A.toDoubleBuffer(db, false); 408 db.flip(); 409 for (int i = 0; i < 16; i++) { 410 assertTrue(colmajor[i] == db.get()); 411 } 412 } 413 414 @Test 415 public void testFromArray() { 416 final double[] values = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 417 final Matrix4 mat4A = new Matrix4(); 418 419 // row major 420 mat4A.setIdentity(); 421 mat4A.fromArray(values); 422 assertTrue(0 == mat4A.getM00()); 423 assertTrue(1 == mat4A.getM01()); 424 assertTrue(2 == mat4A.getM02()); 425 assertTrue(3 == mat4A.getM03()); 426 assertTrue(4 == mat4A.getM10()); 427 assertTrue(5 == mat4A.getM11()); 428 assertTrue(6 == mat4A.getM12()); 429 assertTrue(7 == mat4A.getM13()); 430 assertTrue(8 == mat4A.getM20()); 431 assertTrue(9 == mat4A.getM21()); 432 assertTrue(10 == mat4A.getM22()); 433 assertTrue(11 == mat4A.getM23()); 434 assertTrue(12 == mat4A.getM30()); 435 assertTrue(13 == mat4A.getM31()); 436 assertTrue(14 == mat4A.getM32()); 437 assertTrue(15 == mat4A.getM33()); 438 439 // column major 440 mat4A.setIdentity(); 441 mat4A.fromArray(values, false); 442 assertTrue(0 == mat4A.getM00()); 443 assertTrue(4 == mat4A.getM01()); 444 assertTrue(8 == mat4A.getM02()); 445 assertTrue(12 == mat4A.getM03()); 446 assertTrue(1 == mat4A.getM10()); 447 assertTrue(5 == mat4A.getM11()); 448 assertTrue(9 == mat4A.getM12()); 449 assertTrue(13 == mat4A.getM13()); 450 assertTrue(2 == mat4A.getM20()); 451 assertTrue(6 == mat4A.getM21()); 452 assertTrue(10 == mat4A.getM22()); 453 assertTrue(14 == mat4A.getM23()); 454 assertTrue(3 == mat4A.getM30()); 455 assertTrue(7 == mat4A.getM31()); 456 assertTrue(11 == mat4A.getM32()); 457 assertTrue(15 == mat4A.getM33()); 458 } 459 460 @Test 461 public void testToArray() { 462 final double[] values = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 463 final Matrix4 mat4A = new Matrix4().fromArray(values); 464 465 // row major 466 final double[] dbls1 = mat4A.toArray(null); 467 for (int i = 0; i < 16; i++) { 468 assertTrue(values[i] == dbls1[i]); 469 } 470 471 // column major 472 final double[] colmajor = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; 473 mat4A.toArray(dbls1, false); 474 for (int i = 0; i < 16; i++) { 475 assertTrue(colmajor[i] == dbls1[i]); 476 } 477 } 478 479 @Test(expected = IllegalArgumentException.class) 480 public void testBadArray() { 481 final Matrix4 mat4A = new Matrix4(); 482 mat4A.toArray(new double[9]); 483 } 484 485 @Test 486 public void testAngleAxis() { 487 final Matrix4 mat4A = new Matrix4(); 488 // rotate identity 90 degrees around X 489 final double angle = MathUtils.HALF_PI; 490 mat4A.fromAngleAxis(MathUtils.HALF_PI, Vector3.UNIT_X); 491 assertEquals(new Matrix4( // 492 1, 0, 0, 0, // 493 0, Math.cos(angle), -Math.sin(angle), 0, // 494 0, Math.sin(angle), Math.cos(angle), 0, // 495 0, 0, 0, 1), mat4A); 496 } 497 498 @Test 499 public void testRotations() { 500 final Vector4 rotated = new Vector4(); 501 final Vector4 expected = new Vector4(); 502 final Matrix4 worker = new Matrix4(); 503 504 // test axis rotation methods against general purpose 505 // X AXIS 506 expected.set(1, 1, 1, 1); 507 rotated.set(1, 1, 1, 1); 508 worker.setIdentity().applyRotationX(MathUtils.QUARTER_PI).applyPost(expected, expected); 509 worker.setIdentity().applyRotation(MathUtils.QUARTER_PI, 1, 0, 0).applyPost(rotated, rotated); 510 assertTrue(rotated.distance(expected) <= MathUtils.EPSILON); 511 512 // Y AXIS 513 expected.set(1, 1, 1, 1); 514 rotated.set(1, 1, 1, 1); 515 worker.setIdentity().applyRotationY(MathUtils.QUARTER_PI).applyPost(expected, expected); 516 worker.setIdentity().applyRotation(MathUtils.QUARTER_PI, 0, 1, 0).applyPost(rotated, rotated); 517 assertTrue(rotated.distance(expected) <= MathUtils.EPSILON); 518 519 // Z AXIS 520 expected.set(1, 1, 1, 1); 521 rotated.set(1, 1, 1, 1); 522 worker.setIdentity().applyRotationZ(MathUtils.QUARTER_PI).applyPost(expected, expected); 523 worker.setIdentity().applyRotation(MathUtils.QUARTER_PI, 0, 0, 1).applyPost(rotated, rotated); 524 assertTrue(rotated.distance(expected) <= MathUtils.EPSILON); 525 } 526 527 @Test 528 public void testTranslation() { 529 final Matrix4 src = new Matrix4(); 530 src.applyRotation(MathUtils.QUARTER_PI, 1, 0, 0); 531 532 final Matrix4 trans = new Matrix4(); 533 trans.setColumn(3, new Vector4(1, 2, 3, 1)); 534 final Matrix4 transThenRotate = trans.multiply(src, null); 535 final Matrix4 rotateThenTrans = src.multiply(trans, null); 536 537 final Matrix4 pre1 = new Matrix4(src).applyTranslationPre(1, 2, 3); 538 final Matrix4 post1 = new Matrix4(src).applyTranslationPost(1, 2, 3); 539 540 assertEquals(transThenRotate, pre1); 541 assertEquals(rotateThenTrans, post1); 542 } 543 544 @Test 545 public void testMultiplyDiagonal() { 546 final Matrix4 mat4A = new Matrix4(); 547 Matrix4 result = mat4A.multiplyDiagonalPost(new Vector4(2, 4, 6, 8), null); 548 assertEquals(new Matrix4( // 549 2, 0, 0, 0, // 550 0, 4, 0, 0, // 551 0, 0, 6, 0, // 552 0, 0, 0, 8), result); 553 mat4A.multiplyDiagonalPre(new Vector4(-2, -4, -6, -8), result); 554 assertEquals(new Matrix4( // 555 -2, 0, 0, 0, // 556 0, -4, 0, 0, // 557 0, 0, -6, 0, // 558 0, 0, 0, -8), result); 559 560 final double a = MathUtils.HALF_PI; 561 mat4A.applyRotationY(a); 562 mat4A.multiplyDiagonalPost(new Vector4(2, 4, 6, 8), result); 563 assertEquals(new Matrix4( // 564 2 * Math.cos(a), 4 * 0, 6 * Math.sin(a), 8 * 0, // 565 2 * 0, 4 * 1, 6 * 0, 8 * 0, // 566 2 * -Math.sin(a), 4 * 0, 6 * Math.cos(a), 8 * 0, // 567 2 * 0, 4 * 0, 6 * 0, 8 * 1), result); 568 result = mat4A.multiplyDiagonalPre(new Vector4(-2, -4, -6, -8), null); 569 assertEquals(new Matrix4( // 570 -2 * Math.cos(a), -2 * 0, -2 * Math.sin(a), -2 * 0, // 571 -4 * 0, -4 * 1, -4 * 0, -4 * 0, // 572 -6 * -Math.sin(a), -6 * 0, -6 * Math.cos(a), -6 * 0, // 573 -8 * 0, -8 * 0, -8 * 0, -8 * 1), result); 574 } 575 576 @Test 577 public void testMultiply() { 578 final Matrix4 mat4A = new Matrix4( // 579 0.01, 0.1, 0.2, 0.3, // 580 1.0, 1.1, 1.2, 1.3, // 581 2.0, 2.1, 2.2, 2.3, // 582 3.0, 3.1, 3.2, 3.3); 583 mat4A.multiplyLocal(2); 584 assertEquals(new Matrix4( // 585 0.02, 0.2, 0.4, 0.6, // 586 2.0, 2.2, 2.4, 2.6, // 587 4.0, 4.2, 4.4, 4.6, // 588 6.0, 6.2, 6.4, 6.6), mat4A); 589 590 final Matrix4 mat4B = new Matrix4( // 591 0.5, 1, 2, 3, // 592 4, 5, 6, 7, // 593 8, 9, 10, 11, // 594 12, 13, 14, 15); 595 final Matrix4 result = mat4A.multiply(mat4B, null); 596 assertTrue(0.02 * 0.5 + 0.2 * 4 + 0.4 * 8 + 0.6 * 12 == result.getM00()); 597 assertTrue(0.02 * 1 + 0.2 * 5 + 0.4 * 9 + 0.6 * 13 == result.getM01()); 598 assertTrue(0.02 * 2 + 0.2 * 6 + 0.4 * 10 + 0.6 * 14 == result.getM02()); 599 assertTrue(0.02 * 3 + 0.2 * 7 + 0.4 * 11 + 0.6 * 15 == result.getM03()); 600 assertTrue(2.0 * 0.5 + 2.2 * 4 + 2.4 * 8 + 2.6 * 12 == result.getM10()); 601 assertTrue(2.0 * 1 + 2.2 * 5 + 2.4 * 9 + 2.6 * 13 == result.getM11()); 602 assertTrue(2.0 * 2 + 2.2 * 6 + 2.4 * 10 + 2.6 * 14 == result.getM12()); 603 assertTrue(2.0 * 3 + 2.2 * 7 + 2.4 * 11 + 2.6 * 15 == result.getM13()); 604 assertTrue(4.0 * 0.5 + 4.2 * 4 + 4.4 * 8 + 4.6 * 12 == result.getM20()); 605 assertTrue(4.0 * 1 + 4.2 * 5 + 4.4 * 9 + 4.6 * 13 == result.getM21()); 606 assertTrue(4.0 * 2 + 4.2 * 6 + 4.4 * 10 + 4.6 * 14 == result.getM22()); 607 assertTrue(4.0 * 3 + 4.2 * 7 + 4.4 * 11 + 4.6 * 15 == result.getM23()); 608 assertTrue(6.0 * 0.5 + 6.2 * 4 + 6.4 * 8 + 6.6 * 12 == result.getM30()); 609 assertTrue(6.0 * 1 + 6.2 * 5 + 6.4 * 9 + 6.6 * 13 == result.getM31()); 610 assertTrue(6.0 * 2 + 6.2 * 6 + 6.4 * 10 + 6.6 * 14 == result.getM32()); 611 assertTrue(6.0 * 3 + 6.2 * 7 + 6.4 * 11 + 6.6 * 15 == result.getM33()); 612 mat4A.multiplyLocal(mat4B); 613 assertTrue(0.02 * 0.5 + 0.2 * 4 + 0.4 * 8 + 0.6 * 12 == mat4A.getM00()); 614 assertTrue(0.02 * 1 + 0.2 * 5 + 0.4 * 9 + 0.6 * 13 == mat4A.getM01()); 615 assertTrue(0.02 * 2 + 0.2 * 6 + 0.4 * 10 + 0.6 * 14 == mat4A.getM02()); 616 assertTrue(0.02 * 3 + 0.2 * 7 + 0.4 * 11 + 0.6 * 15 == mat4A.getM03()); 617 assertTrue(2.0 * 0.5 + 2.2 * 4 + 2.4 * 8 + 2.6 * 12 == mat4A.getM10()); 618 assertTrue(2.0 * 1 + 2.2 * 5 + 2.4 * 9 + 2.6 * 13 == mat4A.getM11()); 619 assertTrue(2.0 * 2 + 2.2 * 6 + 2.4 * 10 + 2.6 * 14 == mat4A.getM12()); 620 assertTrue(2.0 * 3 + 2.2 * 7 + 2.4 * 11 + 2.6 * 15 == mat4A.getM13()); 621 assertTrue(4.0 * 0.5 + 4.2 * 4 + 4.4 * 8 + 4.6 * 12 == mat4A.getM20()); 622 assertTrue(4.0 * 1 + 4.2 * 5 + 4.4 * 9 + 4.6 * 13 == mat4A.getM21()); 623 assertTrue(4.0 * 2 + 4.2 * 6 + 4.4 * 10 + 4.6 * 14 == mat4A.getM22()); 624 assertTrue(4.0 * 3 + 4.2 * 7 + 4.4 * 11 + 4.6 * 15 == mat4A.getM23()); 625 assertTrue(6.0 * 0.5 + 6.2 * 4 + 6.4 * 8 + 6.6 * 12 == mat4A.getM30()); 626 assertTrue(6.0 * 1 + 6.2 * 5 + 6.4 * 9 + 6.6 * 13 == mat4A.getM31()); 627 assertTrue(6.0 * 2 + 6.2 * 6 + 6.4 * 10 + 6.6 * 14 == mat4A.getM32()); 628 assertTrue(6.0 * 3 + 6.2 * 7 + 6.4 * 11 + 6.6 * 15 == mat4A.getM33()); 629 } 630 631 @Test 632 public void testAddSubtract() { 633 final Matrix4 mat4A = new Matrix4( // 634 0.0, 0.1, 0.2, 0.3, // 635 1.0, 1.1, 1.2, 1.3, // 636 2.0, 2.1, 2.2, 2.3, // 637 3.0, 3.1, 3.2, 3.3); 638 639 final Matrix4 result1 = mat4A.add(new Matrix4(// 640 1, 2, 3, 4,// 641 5, 6, 7, 8,// 642 9, 10, 11, 12,// 643 13, 14, 15, 16), null); 644 assertEquals(new Matrix4( // 645 1.0, 2.1, 3.2, 4.3, // 646 6.0, 7.1, 8.2, 9.3, // 647 11.0, 12.1, 13.2, 14.3, // 648 16.0, 17.1, 18.2, 19.3), result1); 649 650 final Matrix4 result2 = result1.subtract(new Matrix4(// 651 1, 2, 3, 4,// 652 5, 6, 7, 8,// 653 9, 10, 11, 12,// 654 13, 14, 15, 16), null); 655 assertEquals(mat4A, result2); 656 result2.addLocal(Matrix4.IDENTITY); 657 assertEquals(new Matrix4( // 658 1.0, 0.1, 0.2, 0.3, // 659 1.0, 2.1, 1.2, 1.3, // 660 2.0, 2.1, 3.2, 2.3, // 661 3.0, 3.1, 3.2, 4.3), result2); 662 663 result1.subtractLocal(Matrix4.IDENTITY); 664 assertEquals(new Matrix4( // 665 0.0, 2.1, 3.2, 4.3, // 666 6.0, 6.1, 8.2, 9.3, // 667 11.0, 12.1, 12.2, 14.3, // 668 16.0, 17.1, 18.2, 18.3), result1); 669 } 670 671 @Test 672 public void testScale() { 673 final Matrix4 mat4A = new Matrix4( // 674 0.01, 0.1, 0.2, 0.3, // 675 1.0, 1.1, 1.2, 1.3, // 676 2.0, 2.1, 2.2, 2.3, // 677 3.0, 3.1, 3.2, 3.3); 678 final Matrix4 result = mat4A.scale(new Vector4(-1, 2, 3, 4), null); 679 assertEquals(new Matrix4( // 680 0.01 * -1, 0.1 * 2, 0.2 * 3, 0.3 * 4, // 681 1.0 * -1, 1.1 * 2, 1.2 * 3, 1.3 * 4, // 682 2.0 * -1, 2.1 * 2, 2.2 * 3, 2.3 * 4, // 683 3.0 * -1, 3.1 * 2, 3.2 * 3, 3.3 * 4), result); 684 685 result.scaleLocal(new Vector4(-1, 0.5, 1 / 3., .25)); 686 assertEquals(mat4A, result); 687 } 688 689 @Test 690 public void testTranspose() { 691 final Matrix4 mat4A = new Matrix4( // 692 0.01, 0.1, 0.2, 0.3, // 693 1.0, 1.1, 1.2, 1.3, // 694 2.0, 2.1, 2.2, 2.3, // 695 3.0, 3.1, 3.2, 3.3); 696 final Matrix4 result = mat4A.transpose(null); 697 assertEquals(new Matrix4( // 698 0.01, 1.0, 2.0, 3.0, // 699 0.1, 1.1, 2.1, 3.1, // 700 0.2, 1.2, 2.2, 3.2, // 701 0.3, 1.3, 2.3, 3.3), result); 702 assertEquals(new Matrix4( // 703 0.01, 0.1, 0.2, 0.3, // 704 1.0, 1.1, 1.2, 1.3, // 705 2.0, 2.1, 2.2, 2.3, // 706 3.0, 3.1, 3.2, 3.3), result.transposeLocal()); 707 // coverage 708 final Matrix4 result2 = result.transposeLocal().transpose(new Matrix4()); 709 assertEquals(mat4A, result2); 710 } 711 712 @Test 713 public void testInvert() { 714 final Matrix4 mat4A = new Matrix4().applyRotationX(MathUtils.QUARTER_PI).applyTranslationPost(1, 2, 3); 715 final Matrix4 inverted = mat4A.invert(null); 716 assertEquals(Matrix4.IDENTITY, mat4A.multiply(inverted, null)); 717 assertEquals(mat4A, inverted.invertLocal()); 718 } 719 720 @Test(expected = ArithmeticException.class) 721 public void testBadInvert() { 722 final Matrix4 mat4A = new Matrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 723 mat4A.invertLocal(); 724 } 725 726 @Test 727 public void testAdjugate() { 728 final double // 729 a = -3, b = 2, c = -5, d = 2, // 730 e = -1, f = 0, g = -2, h = 3, // 731 i = 1, j = -3, k = -4, l = 0, // 732 m = 4, n = 2, o = 3, p = 1; 733 734 final Matrix4 mat4A = new Matrix4( // 735 a, b, c, d,// 736 e, f, g, h, // 737 i, j, k, l, // 738 m, n, o, p); 739 740 // prepare sections 741 final Matrix3 m00 = new Matrix3(f, g, h, j, k, l, n, o, p); 742 final Matrix3 m01 = new Matrix3(b, c, d, j, k, l, n, o, p); 743 final Matrix3 m02 = new Matrix3(b, c, d, f, g, h, n, o, p); 744 final Matrix3 m03 = new Matrix3(b, c, d, f, g, h, j, k, l); 745 final Matrix3 m10 = new Matrix3(e, g, h, i, k, l, m, o, p); 746 final Matrix3 m11 = new Matrix3(a, c, d, i, k, l, m, o, p); 747 final Matrix3 m12 = new Matrix3(a, c, d, e, g, h, m, o, p); 748 final Matrix3 m13 = new Matrix3(a, c, d, e, g, h, i, k, l); 749 final Matrix3 m20 = new Matrix3(e, f, h, i, j, l, m, n, p); 750 final Matrix3 m21 = new Matrix3(a, b, d, i, j, l, m, n, p); 751 final Matrix3 m22 = new Matrix3(a, b, d, e, f, h, m, n, p); 752 final Matrix3 m23 = new Matrix3(a, b, d, e, f, h, i, j, l); 753 final Matrix3 m30 = new Matrix3(e, f, g, i, j, k, m, n, o); 754 final Matrix3 m31 = new Matrix3(a, b, c, i, j, k, m, n, o); 755 final Matrix3 m32 = new Matrix3(a, b, c, e, f, g, m, n, o); 756 final Matrix3 m33 = new Matrix3(a, b, c, e, f, g, i, j, k); 757 758 // generate adjugate 759 final Matrix4 testValue = new Matrix4( // 760 m00.determinant(), -m01.determinant(), m02.determinant(), -m03.determinant(), // 761 -m10.determinant(), m11.determinant(), -m12.determinant(), m13.determinant(), // 762 m20.determinant(), -m21.determinant(), m22.determinant(), -m23.determinant(), // 763 -m30.determinant(), m31.determinant(), -m32.determinant(), m33.determinant()); 764 765 assertEquals(testValue, mat4A.adjugate(null)); 766 assertEquals(testValue, mat4A.adjugateLocal()); 767 } 768 769 @Test 770 public void testDeterminant() { 771 { 772 final double // 773 a = -3, b = 2, c = -5, d = 2, // 774 e = -1, f = 0, g = -2, h = 3, // 775 i = 1, j = -3, k = -4, l = 0, // 776 m = 4, n = 2, o = 3, p = 1; 777 778 final Matrix4 mat4A = new Matrix4( // 779 a, b, c, d,// 780 e, f, g, h, // 781 i, j, k, l, // 782 m, n, o, p); 783 784 // prepare sections 785 final double m00 = new Matrix3(f, g, h, j, k, l, n, o, p).determinant(); 786 final double m01 = new Matrix3(e, g, h, i, k, l, m, o, p).determinant(); 787 final double m02 = new Matrix3(e, f, h, i, j, l, m, n, p).determinant(); 788 final double m03 = new Matrix3(e, f, g, i, j, k, m, n, o).determinant(); 789 final double determinant = a * m00 - b * m01 + c * m02 - d * m03; 790 791 assertTrue(Math.abs(determinant - mat4A.determinant()) <= MathUtils.EPSILON); 792 } 793 794 { 795 final double // 796 a = -1.2, b = 4, c = -2.5, d = 1.7, // 797 e = 2, f = -3, g = -2, h = 3.2, // 798 i = 3.1, j = -1, k = 2, l = 1.15, // 799 m = 1, n = 2, o = 3.14, p = 1.4; 800 801 final Matrix4 mat4A = new Matrix4( // 802 a, b, c, d,// 803 e, f, g, h, // 804 i, j, k, l, // 805 m, n, o, p); 806 807 // prepare sections 808 final double m00 = new Matrix3(f, g, h, j, k, l, n, o, p).determinant(); 809 final double m01 = new Matrix3(e, g, h, i, k, l, m, o, p).determinant(); 810 final double m02 = new Matrix3(e, f, h, i, j, l, m, n, p).determinant(); 811 final double m03 = new Matrix3(e, f, g, i, j, k, m, n, o).determinant(); 812 final double determinant = a * m00 - b * m01 + c * m02 - d * m03; 813 814 assertTrue(Math.abs(determinant - mat4A.determinant()) <= MathUtils.EPSILON); 815 } 816 } 817 818 @Test 819 public void testClone() { 820 final Matrix4 mat1 = new Matrix4(); 821 final Matrix4 mat2 = mat1.clone(); 822 assertEquals(mat1, mat2); 823 assertNotSame(mat1, mat2); 824 } 825 826 @Test 827 public void testValid() { 828 final Matrix4 mat4 = new Matrix4(); 829 assertTrue(Matrix4.isValid(mat4)); 830 for (int i = 0; i < 16; i++) { 831 mat4.setIdentity(); 832 mat4.setValue(i / 4, i % 4, Double.NaN); 833 assertFalse(Matrix4.isValid(mat4)); 834 mat4.setIdentity(); 835 mat4.setValue(i / 4, i % 4, Double.POSITIVE_INFINITY); 836 assertFalse(Matrix4.isValid(mat4)); 837 } 838 839 mat4.setIdentity(); 840 assertTrue(Matrix4.isValid(mat4)); 841 842 assertFalse(Matrix4.isValid(null)); 843 844 // couple of equals validity tests 845 assertEquals(mat4, mat4); 846 assertTrue(mat4.strictEquals(mat4)); 847 assertFalse(mat4.equals(null)); 848 assertFalse(mat4.strictEquals(null)); 849 assertFalse(mat4.equals(new Vector2())); 850 assertFalse(mat4.strictEquals(new Vector2())); 851 852 // throw in a couple pool accesses for coverage 853 final Matrix4 matTemp = Matrix4.fetchTempInstance(); 854 matTemp.set(mat4); 855 assertEquals(mat4, matTemp); 856 assertNotSame(mat4, matTemp); 857 Matrix4.releaseTempInstance(matTemp); 858 859 // cover more of equals 860 mat4.set(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 861 final Matrix4 comp = new Matrix4(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); 862 assertFalse(mat4.equals(comp)); 863 assertFalse(mat4.strictEquals(comp)); 864 for (int i = 0; i < 15; i++) { 865 comp.setValue(i / 4, i % 4, i); 866 assertFalse(mat4.equals(comp)); 867 assertFalse(mat4.strictEquals(comp)); 868 } 869 } 870 871 @Test 872 public void testSimpleHash() { 873 // Just a simple sanity check. 874 final Matrix4 mat1 = new Matrix4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); 875 final Matrix4 mat2 = new Matrix4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); 876 final Matrix4 mat3 = new Matrix4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0); 877 878 assertTrue(mat1.hashCode() == mat2.hashCode()); 879 assertTrue(mat1.hashCode() != mat3.hashCode()); 880 } 881 882 @Test 883 public void testOrthonormal() { 884 final Matrix4 mat4 = new Matrix4(); 885 assertTrue(mat4.isOrthonormal()); 886 // just rotation 887 mat4.set(new Matrix3().applyRotationX(MathUtils.QUARTER_PI)); 888 assertTrue(mat4.isOrthonormal()); 889 // non-uniform scale 890 mat4.set(new Matrix3().scaleLocal(new Vector3(1, 2, 3)).applyRotationX(MathUtils.QUARTER_PI)); 891 assertFalse(mat4.isOrthonormal()); 892 // uniform scale 893 mat4.set(new Matrix3().scaleLocal(new Vector3(2, 2, 2)).applyRotationX(MathUtils.QUARTER_PI)); 894 assertFalse(mat4.isOrthonormal()); 895 // uniform scale 1 896 mat4.set(new Matrix3().scaleLocal(new Vector3(1, 1, 1)).applyRotationX(MathUtils.QUARTER_PI)); 897 assertTrue(mat4.isOrthonormal()); 898 } 899 900 @Test 901 public void testApplyVector4() { 902 final Matrix4 mat4 = new Matrix4().applyRotationX(MathUtils.HALF_PI); 903 final Vector4 vec4 = new Vector4(0, 1, 0, 1); 904 final Vector4 result = mat4.applyPost(vec4, null); 905 assertTrue(Math.abs(new Vector4(0, 0, 1, 1).distance(result)) <= MathUtils.EPSILON); 906 vec4.set(0, 1, 1, 1); 907 mat4.applyPost(vec4, result); 908 assertTrue(Math.abs(new Vector4(0, -1, 1, 1).distance(result)) <= MathUtils.EPSILON); 909 910 vec4.set(0, 1, 1, 1); 911 mat4.applyPre(vec4, result); 912 assertTrue(Math.abs(new Vector4(0, 1, -1, 1).distance(result)) <= MathUtils.EPSILON); 913 914 vec4.set(1, 1, 1, 1); 915 assertTrue(Math.abs(new Vector4(1, 1, -1, 1).distance(mat4.applyPre(vec4, null))) <= MathUtils.EPSILON); 916 } 917 918 @Test 919 public void testApplyVector3() { 920 final Matrix4 mat4 = new Matrix4().applyRotationX(MathUtils.HALF_PI).applyTranslationPre(1, 2, 3); 921 final Vector3 vec3 = new Vector3(0, 1, 0); 922 final Vector3 result = mat4.applyPostPoint(vec3, null); 923 assertTrue(Math.abs(new Vector3(1, 2, 4).distance(result)) <= MathUtils.EPSILON); 924 vec3.set(0, 1, 1); 925 mat4.applyPostPoint(vec3, result); 926 assertTrue(Math.abs(new Vector3(1, 1, 4).distance(result)) <= MathUtils.EPSILON); 927 928 vec3.set(0, 1, 1); 929 mat4.applyPostVector(vec3, result); 930 assertTrue(Math.abs(new Vector3(0, -1, 1).distance(result)) <= MathUtils.EPSILON); 931 932 vec3.set(1, 1, 1); 933 assertTrue(Math.abs(new Vector3(1, -1, 1).distance(mat4.applyPostVector(vec3, null))) <= MathUtils.EPSILON); 934 } 935}