/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.tests;
import com.badlogic.gdx.math.Affine2;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.tests.utils.GdxTest;
import com.badlogic.gdx.utils.GdxRuntimeException;
public class Affine2Test extends GdxTest {
static public final float TOLERANCE = 0.005f;
@Override
public void create () {
Vector2 trn = new Vector2(30, 50);
float rot = 35;
float cos = (float)Math.cos(MathUtils.degreesToRadians * rot);
float sin = (float)Math.sin(MathUtils.degreesToRadians * rot);
Vector2 scl = new Vector2(0.42f, 1.19f);
Vector2 shear = new Vector2(0.35f, 0.71f);
Matrix3 mat1 = new Matrix3();
Matrix3 mat2 = new Matrix3();
Affine2 afn1 = new Affine2();
Affine2 afn2 = new Affine2();
// check setter - identity
checkEqual(mat1, new float[] {1, 0, 0, 0, 1, 0, 0, 0, 1});
checkEqual(mat1, mat2.idt());
checkEqual(mat1, afn1);
checkEqual(mat1, afn1.idt());
// check setter - translation
mat1.setToTranslation(trn);
checkEqual(mat1, new float[] {1, 0, 0, 0, 1, 0, trn.x, trn.y, 1});
afn1.setToTranslation(trn);
checkEqual(mat1, afn1);
// check setter - scale
mat1.setToScaling(scl);
checkEqual(mat1, new float[] {scl.x, 0, 0, 0, scl.y, 0, 0, 0, 1});
afn1.setToScaling(scl);
checkEqual(mat1, afn1);
// check setter - rotation
mat1.setToRotation(rot);
checkEqual(mat1, new float[] {cos, sin, 0, -sin, cos, 0, 0, 0, 1});
afn1.setToRotation(rot);
checkEqual(mat1, afn1);
mat1.setToRotationRad(MathUtils.degreesToRadians * rot);
checkEqual(mat1, afn1);
afn1.setToRotationRad(MathUtils.degreesToRadians * rot);
checkEqual(mat1, afn1);
// check setter - shearing
afn1.setToShearing(shear);
checkEqual(mat1.set(afn1), new float[] {1, shear.y, 0, shear.x, 1, 0, 0, 0, 1});
// check setter - translation x rotation x scale
afn1.setToTrnRotScl(trn, rot, scl);
afn2.setToTrnRotRadScl(trn, MathUtils.degreesToRadians * rot, scl);
checkEqual(afn1, afn2);
afn2.setToTranslation(trn).rotate(rot).scale(scl);
checkEqual(afn1, afn2);
// check setter - translation x scale
afn1.setToTrnRotScl(trn, 0, scl);
afn2.setToTrnScl(trn, scl);
checkEqual(afn1, afn2);
// check post-multiplication
mat1.idt().scale(scl).rotate(rot).translate(trn).mul(mat2.set(afn2.setToShearing(shear)));
afn1.idt().scale(scl).rotate(rot).translate(trn).shear(shear);
checkEqual(mat1, afn1);
afn1.idt().mul(afn2.setToScaling(scl)).mul(afn2.setToRotation(rot)).mul(afn2.setToTranslation(trn))
.mul(afn2.setToShearing(shear));
checkEqual(mat1, afn1);
// check pre-multiplication
afn1.idt().preShear(shear).preTranslate(trn).preRotate(rot).preScale(scl);
checkEqual(mat1, afn1);
afn1.idt().preMul(afn2.setToShearing(shear)).preMul(afn2.setToTranslation(trn)).preMul(afn2.setToRotation(rot))
.preMul(afn2.setToScaling(scl));
checkEqual(mat1, afn1);
mat1.set(afn2.setToShearing(shear)).trn(trn).mulLeft(mat2.setToRotation(rot)).mulLeft(mat2.setToScaling(scl));
checkEqual(mat1, afn1);
// check determinant and inverse
checkEqual(mat1.det(), afn1.det());
check(afn1.det() == (afn1.m00 * afn1.m11 - afn1.m01 * afn1.m10));
mat1.inv();
afn2.set(afn1).inv();
checkEqual(mat1, afn2);
checkEqual(afn1.det(), 1 / afn2.det());
// check for exception when trying to invert singular matrices
boolean didThrow = false;
afn1.setToShearing(1, 1);
try {
afn1.inv();
} catch (GdxRuntimeException e) {
didThrow = true;
}
check(didThrow);
System.out.println("All tests passed.");
}
private static void check (boolean condition) {
if (!condition) throw new GdxRuntimeException("");
}
private static void check (boolean condition, String msg) {
if (!condition) throw new GdxRuntimeException(msg);
}
private static void checkEqual (Matrix3 matrix, Affine2 affine) {
checkEqual(matrix, new Matrix3().set(affine));
}
private static void checkEqual (Affine2 a, Affine2 b) {
checkEqual(new Matrix3().set(a), new Matrix3().set(b));
}
private static void checkEqual (Matrix3 a, Matrix3 b) {
for (int i = 0; i < 9; i++)
check(MathUtils.isEqual(a.val[i], b.val[i], TOLERANCE), "matrices are not equal");
}
private static void checkEqual (Matrix3 matrix, float[] vals) {
for (int i = 0; i < 9; i++)
check(MathUtils.isEqual(matrix.val[i], vals[i], TOLERANCE), "matrices are not equal");
}
private static void checkEqual (float a, float b) {
check(MathUtils.isEqual(a, b, TOLERANCE));
}
}