package org.lwjgl.test.opengles.util; import org.lwjgl.util.vector.Matrix4f; import org.lwjgl.util.vector.Vector3f; import java.util.Stack; import static java.lang.Math.*; /** Emulates the matrix stack in fixed-function OpenGL. */ public final class GLMatrix { public static final int GL_MODELVIEW = 0x1700; public static final int GL_PROJECTION = 0x1701; private static final float PI = (float)Math.PI; /** The model/view matrix stack. */ private static final Stack<Matrix4f> mvMatrixStack = new Stack<Matrix4f>(); /** The projection matrix stack. */ private static final Stack<Matrix4f> pMatrixStack = new Stack<Matrix4f>(); private static final Matrix4f m4f = new Matrix4f(); private static final Vector3f v3f = new Vector3f(); private static int mode = GL_MODELVIEW; static { mvMatrixStack.push(new Matrix4f()); pMatrixStack.push(new Matrix4f()); } private GLMatrix() { } private static Stack<Matrix4f> getCurrentStack() { switch ( mode ) { case GL_MODELVIEW: return mvMatrixStack; case GL_PROJECTION: return pMatrixStack; default: return null; // Cannot happen } } private static Matrix4f getCurrentMatrix() { return getCurrentStack().peek(); } public static void glMatrixMode(final int mode) { if ( mode != GL_MODELVIEW && mode != GL_PROJECTION ) throw new IllegalArgumentException("Invalid matrix mode specified: " + mode); GLMatrix.mode = mode; } public static void glPushMatrix() { final Stack<Matrix4f> stack = getCurrentStack(); stack.push(new Matrix4f(stack.peek())); } public static void glPopMatrix() { final Stack<Matrix4f> stack = getCurrentStack(); if ( stack.size() == 1 ) throw new IllegalStateException("The last matrix in the stack cannot be popped."); getCurrentStack().pop(); } public static void glLoadIdentity() { final Matrix4f m = getCurrentMatrix(); m.setIdentity(); } public static void glLoadMatrix(final Matrix4f s) { getCurrentMatrix().load(s); } public static void glMultMatrix(final Matrix4f m) { final Matrix4f c = getCurrentMatrix(); Matrix4f.mul(c, m, c); } public static void glTranslatef(final float x, final float y, final float z) { final Matrix4f m = getCurrentMatrix(); v3f.set(x, y, z); m.translate(v3f); } public static void glRotatef(final float angle, final float x, final float y, final float z) { final Matrix4f m = getCurrentMatrix(); v3f.set(x, y, z); m.rotate((float)toRadians(angle), v3f); } public static void glOrtho(final float l, final float r, final float b, final float t, final float n, final float f) { final Matrix4f m = m4f; m.setIdentity(); m.m00 = 2.0f / (r - l); m.m30 = -(r + l) / (r - l); m.m11 = 2.0f / (t - b); m.m31 = -(t + b) / (t - b); m.m22 = -2.0f / (f - n); m.m32 = -(f + n) / (f - n); glMultMatrix(m); } public static void glFrustum(final float l, final float r, final float b, final float t, final float n, final float f) { final Matrix4f m = m4f; m.setIdentity(); m.m00 = 2.0f * n / (r - l); m.m20 = (r + l) / (r - l); m.m11 = 2.0f * n / (t - b); m.m21 = (t + b) / (t - b); m.m22 = -(f + n) / (f - n); m.m32 = -(2.0f * f * n) / (f - n); m.m23 = -1.0f; m.m33 = 0.0f; glMultMatrix(m); } public static void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) { final float radians = fovy / 2.0f * PI / 180.0f; final float deltaZ = zFar - zNear; final float sine = (float)sin(radians); if ( (deltaZ == 0) || (sine == 0) || (aspect == 0) ) { return; } final float cotangent = (float)cos(radians) / sine; final Matrix4f m = m4f; m.setIdentity(); m.m00 = cotangent / aspect; m.m11 = cotangent; m.m22 = -(zFar + zNear) / deltaZ; m.m23 = -1.0f; m.m32 = -2 * zNear * zFar / deltaZ; m.m33 = 0.0f; glMultMatrix(m); } public static void glGetMatrix(final Matrix4f d) { d.load(getCurrentMatrix()); } }