1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.tests; 18 19 import com.badlogic.gdx.math.Affine2; 20 import com.badlogic.gdx.math.MathUtils; 21 import com.badlogic.gdx.math.Matrix3; 22 import com.badlogic.gdx.math.Vector2; 23 import com.badlogic.gdx.tests.utils.GdxTest; 24 import com.badlogic.gdx.utils.GdxRuntimeException; 25 26 public class Affine2Test extends GdxTest { 27 28 static public final float TOLERANCE = 0.005f; 29 30 @Override create()31 public void create () { 32 Vector2 trn = new Vector2(30, 50); 33 float rot = 35; 34 float cos = (float)Math.cos(MathUtils.degreesToRadians * rot); 35 float sin = (float)Math.sin(MathUtils.degreesToRadians * rot); 36 Vector2 scl = new Vector2(0.42f, 1.19f); 37 Vector2 shear = new Vector2(0.35f, 0.71f); 38 39 Matrix3 mat1 = new Matrix3(); 40 Matrix3 mat2 = new Matrix3(); 41 Affine2 afn1 = new Affine2(); 42 Affine2 afn2 = new Affine2(); 43 44 // check setter - identity 45 checkEqual(mat1, new float[] {1, 0, 0, 0, 1, 0, 0, 0, 1}); 46 checkEqual(mat1, mat2.idt()); 47 checkEqual(mat1, afn1); 48 checkEqual(mat1, afn1.idt()); 49 50 // check setter - translation 51 mat1.setToTranslation(trn); 52 checkEqual(mat1, new float[] {1, 0, 0, 0, 1, 0, trn.x, trn.y, 1}); 53 afn1.setToTranslation(trn); 54 checkEqual(mat1, afn1); 55 56 // check setter - scale 57 mat1.setToScaling(scl); 58 checkEqual(mat1, new float[] {scl.x, 0, 0, 0, scl.y, 0, 0, 0, 1}); 59 afn1.setToScaling(scl); 60 checkEqual(mat1, afn1); 61 62 // check setter - rotation 63 mat1.setToRotation(rot); 64 checkEqual(mat1, new float[] {cos, sin, 0, -sin, cos, 0, 0, 0, 1}); 65 afn1.setToRotation(rot); 66 checkEqual(mat1, afn1); 67 mat1.setToRotationRad(MathUtils.degreesToRadians * rot); 68 checkEqual(mat1, afn1); 69 afn1.setToRotationRad(MathUtils.degreesToRadians * rot); 70 checkEqual(mat1, afn1); 71 72 // check setter - shearing 73 afn1.setToShearing(shear); 74 checkEqual(mat1.set(afn1), new float[] {1, shear.y, 0, shear.x, 1, 0, 0, 0, 1}); 75 76 // check setter - translation x rotation x scale 77 afn1.setToTrnRotScl(trn, rot, scl); 78 afn2.setToTrnRotRadScl(trn, MathUtils.degreesToRadians * rot, scl); 79 checkEqual(afn1, afn2); 80 afn2.setToTranslation(trn).rotate(rot).scale(scl); 81 checkEqual(afn1, afn2); 82 83 // check setter - translation x scale 84 afn1.setToTrnRotScl(trn, 0, scl); 85 afn2.setToTrnScl(trn, scl); 86 checkEqual(afn1, afn2); 87 88 // check post-multiplication 89 mat1.idt().scale(scl).rotate(rot).translate(trn).mul(mat2.set(afn2.setToShearing(shear))); 90 afn1.idt().scale(scl).rotate(rot).translate(trn).shear(shear); 91 checkEqual(mat1, afn1); 92 afn1.idt().mul(afn2.setToScaling(scl)).mul(afn2.setToRotation(rot)).mul(afn2.setToTranslation(trn)) 93 .mul(afn2.setToShearing(shear)); 94 checkEqual(mat1, afn1); 95 96 // check pre-multiplication 97 afn1.idt().preShear(shear).preTranslate(trn).preRotate(rot).preScale(scl); 98 checkEqual(mat1, afn1); 99 afn1.idt().preMul(afn2.setToShearing(shear)).preMul(afn2.setToTranslation(trn)).preMul(afn2.setToRotation(rot)) 100 .preMul(afn2.setToScaling(scl)); 101 checkEqual(mat1, afn1); 102 mat1.set(afn2.setToShearing(shear)).trn(trn).mulLeft(mat2.setToRotation(rot)).mulLeft(mat2.setToScaling(scl)); 103 checkEqual(mat1, afn1); 104 105 // check determinant and inverse 106 checkEqual(mat1.det(), afn1.det()); 107 check(afn1.det() == (afn1.m00 * afn1.m11 - afn1.m01 * afn1.m10)); 108 mat1.inv(); 109 afn2.set(afn1).inv(); 110 checkEqual(mat1, afn2); 111 checkEqual(afn1.det(), 1 / afn2.det()); 112 113 // check for exception when trying to invert singular matrices 114 boolean didThrow = false; 115 afn1.setToShearing(1, 1); 116 try { 117 afn1.inv(); 118 } catch (GdxRuntimeException e) { 119 didThrow = true; 120 } 121 check(didThrow); 122 123 System.out.println("All tests passed."); 124 } 125 check(boolean condition)126 private static void check (boolean condition) { 127 if (!condition) throw new GdxRuntimeException(""); 128 } 129 check(boolean condition, String msg)130 private static void check (boolean condition, String msg) { 131 if (!condition) throw new GdxRuntimeException(msg); 132 } 133 checkEqual(Matrix3 matrix, Affine2 affine)134 private static void checkEqual (Matrix3 matrix, Affine2 affine) { 135 checkEqual(matrix, new Matrix3().set(affine)); 136 } 137 checkEqual(Affine2 a, Affine2 b)138 private static void checkEqual (Affine2 a, Affine2 b) { 139 checkEqual(new Matrix3().set(a), new Matrix3().set(b)); 140 } 141 checkEqual(Matrix3 a, Matrix3 b)142 private static void checkEqual (Matrix3 a, Matrix3 b) { 143 for (int i = 0; i < 9; i++) 144 check(MathUtils.isEqual(a.val[i], b.val[i], TOLERANCE), "matrices are not equal"); 145 } 146 checkEqual(Matrix3 matrix, float[] vals)147 private static void checkEqual (Matrix3 matrix, float[] vals) { 148 for (int i = 0; i < 9; i++) 149 check(MathUtils.isEqual(matrix.val[i], vals[i], TOLERANCE), "matrices are not equal"); 150 } 151 checkEqual(float a, float b)152 private static void checkEqual (float a, float b) { 153 check(MathUtils.isEqual(a, b, TOLERANCE)); 154 } 155 } 156