package org.andengine.opengl.util;
import org.andengine.util.exception.AndEngineRuntimeException;
import org.andengine.util.math.MathConstants;
import android.opengl.Matrix;
/**
* TODO Measure performance with inlined or native Matrix implementations.
*
* (c) Zynga 2011
*
* @author Nicolas Gramlich <ngramlich@zynga.com>
* @since 14:49:23 - 04.08.2011
*/
public class GLMatrixStack {
// ===========================================================
// Constants
// ===========================================================
public static final int GLMATRIXSTACK_DEPTH_MAX = 32;
public static final int GLMATRIX_SIZE = 16;
private static final int GLMATRIXSTACKOFFSET_UNDERFLOW = -1 * GLMatrixStack.GLMATRIX_SIZE;
private static final int GLMATRIXSTACKOFFSET_OVERFLOW = GLMatrixStack.GLMATRIXSTACK_DEPTH_MAX * GLMatrixStack.GLMATRIX_SIZE;
// ===========================================================
// Fields
// ===========================================================
final float[] mMatrixStack = new float[GLMatrixStack.GLMATRIXSTACK_DEPTH_MAX * GLMatrixStack.GLMATRIX_SIZE];
int mMatrixStackOffset;
private final float[] mTemp = new float[2 * GLMatrixStack.GLMATRIX_SIZE];
// ===========================================================
// Constructors
// ===========================================================
public GLMatrixStack() {
this.glLoadIdentity();
}
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
public void getMatrix(final float[] pMatrix) {
System.arraycopy(this.mMatrixStack, this.mMatrixStackOffset, pMatrix, 0, GLMatrixStack.GLMATRIX_SIZE);
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void glLoadIdentity() {
Matrix.setIdentityM(this.mMatrixStack, this.mMatrixStackOffset);
}
public void glTranslatef(final float pX, final float pY, final float pZ) {
Matrix.translateM(this.mMatrixStack, this.mMatrixStackOffset, pX, pY, pZ);
}
public void glRotatef(final float pAngle, final float pX, final float pY, final float pZ) {
Matrix.setRotateM(this.mTemp, 0, pAngle, pX, pY, pZ);
System.arraycopy(this.mMatrixStack, this.mMatrixStackOffset, this.mTemp, GLMatrixStack.GLMATRIX_SIZE, GLMatrixStack.GLMATRIX_SIZE);
Matrix.multiplyMM(this.mMatrixStack, this.mMatrixStackOffset, this.mTemp, GLMatrixStack.GLMATRIX_SIZE, this.mTemp, 0);
}
public void glScalef(final float pScaleX, final float pScaleY, final float pScaleZ) {
Matrix.scaleM(this.mMatrixStack, this.mMatrixStackOffset, pScaleX, pScaleY, pScaleZ);
}
public void glSkewf(final float pSkewX, final float pSkewY) {
GLMatrixStack.setSkewM(this.mTemp, 0, pSkewX, pSkewY);
System.arraycopy(this.mMatrixStack, this.mMatrixStackOffset, this.mTemp, GLMatrixStack.GLMATRIX_SIZE, GLMatrixStack.GLMATRIX_SIZE);
Matrix.multiplyMM(this.mMatrixStack, this.mMatrixStackOffset, this.mTemp, GLMatrixStack.GLMATRIX_SIZE, this.mTemp, 0);
}
public void glOrthof(final float pLeft, final float pRight, final float pBottom, final float pTop, final float pZNear, final float pZFar) {
Matrix.orthoM(this.mMatrixStack, this.mMatrixStackOffset, pLeft, pRight, pBottom, pTop, pZNear, pZFar);
}
public void glPushMatrix() throws GLMatrixStackOverflowException {
if (this.mMatrixStackOffset + GLMatrixStack.GLMATRIX_SIZE >= GLMatrixStack.GLMATRIXSTACKOFFSET_OVERFLOW) {
throw new GLMatrixStackOverflowException();
}
System.arraycopy(this.mMatrixStack, this.mMatrixStackOffset, this.mMatrixStack, this.mMatrixStackOffset + GLMatrixStack.GLMATRIX_SIZE, GLMatrixStack.GLMATRIX_SIZE);
this.mMatrixStackOffset += GLMatrixStack.GLMATRIX_SIZE;
}
public void glPopMatrix() {
if (this.mMatrixStackOffset - GLMatrixStack.GLMATRIX_SIZE <= GLMatrixStack.GLMATRIXSTACKOFFSET_UNDERFLOW) {
throw new GLMatrixStackUnderflowException();
}
this.mMatrixStackOffset -= GLMatrixStack.GLMATRIX_SIZE;
}
public void reset() {
this.mMatrixStackOffset = 0;
this.glLoadIdentity();
}
private static void setSkewM(final float[] pMatrixStack, final int pOffset, final float pSkewX, final float pSkewY) {
pMatrixStack[pOffset + 0] = 1.0f;
pMatrixStack[pOffset + 1] = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewY);
pMatrixStack[pOffset + 2] = 0.0f;
pMatrixStack[pOffset + 3] = 0.0f;
pMatrixStack[pOffset + 4] = (float) Math.tan(-MathConstants.DEG_TO_RAD * pSkewX);
pMatrixStack[pOffset + 5] = 1.0f;
pMatrixStack[pOffset + 6] = 0.0f;
pMatrixStack[pOffset + 7] = 0.0f;
pMatrixStack[pOffset + 8] = 0.0f;
pMatrixStack[pOffset + 9] = 0.0f;
pMatrixStack[pOffset + 10] = 1.0f;
pMatrixStack[pOffset + 11] = 0.0f;
pMatrixStack[pOffset + 12] = 0.0f;
pMatrixStack[pOffset + 13] = 0.0f;
pMatrixStack[pOffset + 14] = 0.0f;
pMatrixStack[pOffset + 15] = 1.0f;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static class GLMatrixStackOverflowException extends AndEngineRuntimeException {
// ===========================================================
// Constants
// ===========================================================
private static final long serialVersionUID = -800847781599300100L;
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
public GLMatrixStackOverflowException() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
public static class GLMatrixStackUnderflowException extends AndEngineRuntimeException {
// ===========================================================
// Constants
// ===========================================================
private static final long serialVersionUID = -3268021423136372954L;
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
public GLMatrixStackUnderflowException() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
}