package org.andengine.util.adt.transformation;
import org.andengine.util.math.MathConstants;
import android.util.FloatMath;
/**
* <p>This class is basically a java-space replacement for the native {@link android.graphics.Matrix} class.</p>
*
* <p>Math taken from <a href="http://www.senocular.com/flash/tutorials/transformmatrix/">senocular.com</a>.</p>
*
* This class represents an affine transformation with the following matrix:
* <pre> [ a , b , 0 ]
* [ c , d , 0 ]
* [ tx, ty, 1 ]</pre>
* where:
* <ul>
* <li><b>a</b> is the <b>x scale</b></li>
* <li><b>b</b> is the <b>y skew</b></li>
* <li><b>c</b> is the <b>x skew</b></li>
* <li><b>d</b> is the <b>y scale</b></li>
* <li><b>tx</b> is the <b>x translation</b></li>
* <li><b>ty</b> is the <b>y translation</b></li>
* </ul>
*
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 15:47:18 - 23.12.2010
*/
public class Transformation {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private float a = 1.0f; /* x scale */
private float b = 0.0f; /* y skew */
private float c = 0.0f; /* x skew */
private float d = 1.0f; /* y scale */
private float tx = 0.0f; /* x translation */
private float ty = 0.0f; /* y translation */
// ===========================================================
// Constructors
// ===========================================================
public Transformation() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public String toString() {
return "Transformation{[" + this.a + ", " + this.c + ", " + this.tx + "][" + this.b + ", " + this.d + ", " + this.ty + "][0.0, 0.0, 1.0]}";
}
// ===========================================================
// Methods
// ===========================================================
public final void reset() {
this.setToIdentity();
}
public final void setToIdentity() {
this.a = 1.0f;
this.d = 1.0f;
this.b = 0.0f;
this.c = 0.0f;
this.tx = 0.0f;
this.ty = 0.0f;
}
public final void setTo(final Transformation pTransformation) {
this.a = pTransformation.a;
this.d = pTransformation.d;
this.b = pTransformation.b;
this.c = pTransformation.c;
this.tx = pTransformation.tx;
this.ty = pTransformation.ty;
}
public final void preTranslate(final float pX, final float pY) {
this.tx += pX * this.a + pY * this.c;
this.ty += pX * this.b + pY * this.d;
}
public final void postTranslate(final float pX, final float pY) {
this.tx += pX;
this.ty += pY;
}
public final Transformation setToTranslate(final float pX, final float pY) {
this.a = 1.0f;
this.b = 0.0f;
this.c = 0.0f;
this.d = 1.0f;
this.tx = pX;
this.ty = pY;
return this;
}
public final void preRotate(final float pAngle) {
final float angleRad = MathConstants.DEG_TO_RAD * pAngle;
final float sin = FloatMath.sin(angleRad);
final float cos = FloatMath.cos(angleRad);
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
this.a = cos * a + sin * c;
this.b = cos * b + sin * d;
this.c = cos * c - sin * a;
this.d = cos * d - sin * b;
}
public final void postRotate(final float pAngle) {
final float angleRad = MathConstants.DEG_TO_RAD * pAngle;
final float sin = FloatMath.sin(angleRad);
final float cos = FloatMath.cos(angleRad);
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
final float tx = this.tx;
final float ty = this.ty;
this.a = a * cos - b * sin;
this.b = a * sin + b * cos;
this.c = c * cos - d * sin;
this.d = c * sin + d * cos;
this.tx = tx * cos - ty * sin;
this.ty = tx * sin + ty * cos;
}
public final Transformation setToRotate(final float pAngle) {
final float angleRad = MathConstants.DEG_TO_RAD * pAngle;
final float sin = FloatMath.sin(angleRad);
final float cos = FloatMath.cos(angleRad);
this.a = cos;
this.b = sin;
this.c = -sin;
this.d = cos;
this.tx = 0.0f;
this.ty = 0.0f;
return this;
}
public final void preScale(final float pScaleX, final float pScaleY) {
this.a *= pScaleX;
this.b *= pScaleX;
this.c *= pScaleY;
this.d *= pScaleY;
}
public final void postScale(final float pScaleX, final float pScaleY) {
this.a = this.a * pScaleX;
this.b = this.b * pScaleY;
this.c = this.c * pScaleX;
this.d = this.d * pScaleY;
this.tx = this.tx * pScaleX;
this.ty = this.ty * pScaleY;
}
public final Transformation setToScale(final float pScaleX, final float pScaleY) {
this.a = pScaleX;
this.b = 0.0f;
this.c = 0.0f;
this.d = pScaleY;
this.tx = 0.0f;
this.ty = 0.0f;
return this;
}
public final void preSkew(final float pSkewX, final float pSkewY) {
final float tanX = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewX);
final float tanY = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewY);
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
final float tx = this.tx;
final float ty = this.ty;
this.a = a + tanY * c;
this.b = b + tanY * d;
this.c = tanX * a + c;
this.d = tanX * b + d;
this.tx = tx;
this.ty = ty;
}
public final void postSkew(final float pSkewX, final float pSkewY) {
final float tanX = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewX);
final float tanY = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewY);
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
final float tx = this.tx;
final float ty = this.ty;
this.a = a + b * tanX;
this.b = a * tanY + b;
this.c = c + d * tanX;
this.d = c * tanY + d;
this.tx = tx + ty * tanX;
this.ty = tx * tanY + ty;
}
public final Transformation setToSkew(final float pSkewX, final float pSkewY) {
this.a = 1.0f;
this.b = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewY);
this.c = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewX);
this.d = 1.0f;
this.tx = 0.0f;
this.ty = 0.0f;
return this;
}
public final void postConcat(final Transformation pTransformation) {
this.postConcat(pTransformation.a, pTransformation.b, pTransformation.c, pTransformation.d, pTransformation.tx, pTransformation.ty);
}
private void postConcat(final float pA, final float pB, final float pC, final float pD, final float pTX, final float pTY) {
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
final float tx = this.tx;
final float ty = this.ty;
this.a = a * pA + b * pC;
this.b = a * pB + b * pD;
this.c = c * pA + d * pC;
this.d = c * pB + d * pD;
this.tx = tx * pA + ty * pC + pTX;
this.ty = tx * pB + ty * pD + pTY;
}
public final void preConcat(final Transformation pTransformation) {
this.preConcat(pTransformation.a, pTransformation.b, pTransformation.c, pTransformation.d, pTransformation.tx, pTransformation.ty);
}
private void preConcat(final float pA, final float pB, final float pC, final float pD, final float pTX, final float pTY) {
final float a = this.a;
final float b = this.b;
final float c = this.c;
final float d = this.d;
final float tx = this.tx;
final float ty = this.ty;
this.a = pA * a + pB * c;
this.b = pA * b + pB * d;
this.c = pC * a + pD * c;
this.d = pC * b + pD * d;
this.tx = pTX * a + pTY * c + tx;
this.ty = pTX * b + pTY * d + ty;
}
public final void transform(final float[] pVertices) {
int count = pVertices.length >> 1;
int i = 0;
int j = 0;
while(--count >= 0) {
final float x = pVertices[i++];
final float y = pVertices[i++];
pVertices[j++] = x * this.a + y * this.c + this.tx;
pVertices[j++] = x * this.b + y * this.d + this.ty;
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}