package graphics;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.ReadableVector3f;
import org.lwjgl.util.vector.Vector3f;
/**
*
* @author simokr
*/
public class Graphics {
public static int screenWidth = 1024, screenHeight = 640;
public static float zNear = 0.1f, zFar = 100f;
public static String windowTitle = "SteamTrail Deluxe";
private static FloatBuffer viewMatrixBuffer, projectionMatrixBuffer;
private static Matrix4f viewMatrix, projectionMatrix;
private static float [][] frustum;
private static Vector3f clearColor;
private static Camera camera;
public static void create() throws LWJGLException {
viewMatrixBuffer = BufferUtils.createFloatBuffer(16);
viewMatrix = new Matrix4f();
projectionMatrixBuffer = BufferUtils.createFloatBuffer(16);
projectionMatrix = new Matrix4f();
frustum = new float[6][4];
clearColor = new Vector3f(1,1,1);
camera = new Camera();
Display.setDisplayMode(new DisplayMode(screenWidth, screenHeight));
Display.setFullscreen(false);
Display.setTitle(windowTitle);
Display.create();
initGL();
resizeGL();
}
public static void destroy() {
Display.destroy();
}
private static void initGL() {
glClearColor(clearColor.x, clearColor.y, clearColor.z, 0.0f);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
}
private static void resizeGL() {
glViewport(0, 0, screenWidth, screenHeight);
updateProjectionMatrix();
glEnable(GL_CULL_FACE);
}
public static void set2dProjection() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (double) screenWidth, (double) screenHeight, 0.0, -100, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_CULL_FACE);
}
public static void clear() {
glClearColor(clearColor.x, clearColor.y, clearColor.z, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public static void set3dProjection(){
resizeGL();
updateViewMatrix();
ExtractFrustum();
}
private static void updateViewMatrix(){
viewMatrix.setIdentity();
viewMatrix.rotate((float) Math.toRadians(camera.getRotation().getX()), new Vector3f(1, 0, 0));
viewMatrix.rotate((float) Math.toRadians(camera.getRotation().getY()), new Vector3f(0, 1, 0));
viewMatrix.rotate((float) Math.toRadians(camera.getRotation().getZ()), new Vector3f(0, 0, 1));
viewMatrix.translate(new Vector3f(camera.getPosition()).negate(null));
viewMatrix.store(viewMatrixBuffer);
viewMatrixBuffer.flip();
}
private static void updateProjectionMatrix(){
float xymax = zNear * (float)(Math.tan(Math.toRadians(camera.getFieldOfView() * 0.5f)));
float ymin = -xymax;
float xmin = -xymax;
float width = xymax - xmin;
float height = xymax - ymin;
float depth = zFar - zNear;
float q = -(zFar + zNear) / depth;
float qn = -2.0f * (zFar * zNear) / depth;
float w = 2.0f * (zNear / width);
w = w / ((float)screenWidth/(float)screenHeight);
float h = 2.0f * zNear / height;
projectionMatrix.setZero();
projectionMatrix.m00 = w;
projectionMatrix.m11 = h;
projectionMatrix.m22 = q;
projectionMatrix.m23 = -1.0f;
projectionMatrix.m32 = qn;
projectionMatrix.store(projectionMatrixBuffer);
projectionMatrixBuffer.flip();
}
public static FloatBuffer getViewMatrix(){
return viewMatrixBuffer;
}
public static FloatBuffer getProjectionMatrix(){
return projectionMatrixBuffer;
}
public static void setCurrentCamera(Camera cam){
camera = cam;
}
public static Camera getCurrentCamera(){
return camera;
}
public static void setClearColor(ReadableVector3f color){
clearColor.set(color);
}
protected static void ExtractFrustum(){
FloatBuffer proj = getProjectionMatrix();
FloatBuffer modl = getViewMatrix();
FloatBuffer clip = BufferUtils.createFloatBuffer(16);
float t;
/* Combine the two matrices (multiply projection by modelview) */
clip.put( 0, modl.get( 0) * proj.get( 0) + modl.get( 1) * proj.get( 4) + modl.get( 2) * proj.get( 8) + modl.get( 3) * proj.get(12));
clip.put( 1, modl.get( 0) * proj.get( 1) + modl.get( 1) * proj.get( 5) + modl.get( 2) * proj.get( 9) + modl.get( 3) * proj.get(13));
clip.put( 2, modl.get( 0) * proj.get( 2) + modl.get( 1) * proj.get( 6) + modl.get( 2) * proj.get(10) + modl.get( 3) * proj.get(14));
clip.put( 3, modl.get( 0) * proj.get( 3) + modl.get( 1) * proj.get( 7) + modl.get( 2) * proj.get(11) + modl.get( 3) * proj.get(15));
clip.put( 4, modl.get( 4) * proj.get( 0) + modl.get( 5) * proj.get( 4) + modl.get( 6) * proj.get( 8) + modl.get( 7) * proj.get(12));
clip.put( 5, modl.get( 4) * proj.get( 1) + modl.get( 5) * proj.get( 5) + modl.get( 6) * proj.get( 9) + modl.get( 7) * proj.get(13));
clip.put( 6, modl.get( 4) * proj.get( 2) + modl.get( 5) * proj.get( 6) + modl.get( 6) * proj.get(10) + modl.get( 7) * proj.get(14));
clip.put( 7, modl.get( 4) * proj.get( 3) + modl.get( 5) * proj.get( 7) + modl.get( 6) * proj.get(11) + modl.get( 7) * proj.get(15));
clip.put( 8, modl.get( 8) * proj.get( 0) + modl.get( 9) * proj.get( 4) + modl.get(10) * proj.get( 8) + modl.get(11) * proj.get(12));
clip.put( 9, modl.get( 8) * proj.get( 1) + modl.get( 9) * proj.get( 5) + modl.get(10) * proj.get( 9) + modl.get(11) * proj.get(13));
clip.put(10, modl.get( 8) * proj.get( 2) + modl.get( 9) * proj.get( 6) + modl.get(10) * proj.get(10) + modl.get(11) * proj.get(14));
clip.put(11, modl.get( 8) * proj.get( 3) + modl.get( 9) * proj.get( 7) + modl.get(10) * proj.get(11) + modl.get(11) * proj.get(15));
clip.put(12, modl.get(12) * proj.get( 0) + modl.get(13) * proj.get( 4) + modl.get(14) * proj.get( 8) + modl.get(15) * proj.get(12));
clip.put(13, modl.get(12) * proj.get( 1) + modl.get(13) * proj.get( 5) + modl.get(14) * proj.get( 9) + modl.get(15) * proj.get(13));
clip.put(14, modl.get(12) * proj.get( 2) + modl.get(13) * proj.get( 6) + modl.get(14) * proj.get(10) + modl.get(15) * proj.get(14));
clip.put(15, modl.get(12) * proj.get( 3) + modl.get(13) * proj.get( 7) + modl.get(14) * proj.get(11) + modl.get(15) * proj.get(15));
/* Extract the numbers for the RIGHT plane */
frustum[0][0] = clip.get(3) - clip.get(0);
frustum[0][1] = clip.get(7) - clip.get(4);
frustum[0][2] = clip.get(11) - clip.get(8);
frustum[0][3] = clip.get(15) - clip.get(12);
/* Normalize the result */
t = (float)Math.sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
frustum[0][0] /= t;
frustum[0][1] /= t;
frustum[0][2] /= t;
frustum[0][3] /= t;
/* Extract the numbers for the LEFT plane */
frustum[1][0] = clip.get(3) + clip.get(0);
frustum[1][1] = clip.get(7) + clip.get(4);
frustum[1][2] = clip.get(11) + clip.get(8);
frustum[1][3] = clip.get(15) + clip.get(12);
/* Normalize the result */
t = (float)Math.sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
frustum[1][0] /= t;
frustum[1][1] /= t;
frustum[1][2] /= t;
frustum[1][3] /= t;
/* Extract the BOTTOM plane */
frustum[2][0] = clip.get(3) + clip.get(1);
frustum[2][1] = clip.get(7) + clip.get(5);
frustum[2][2] = clip.get(11) + clip.get(9);
frustum[2][3] = clip.get(15) + clip.get(13);
/* Normalize the result */
t = (float)Math.sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
frustum[2][0] /= t;
frustum[2][1] /= t;
frustum[2][2] /= t;
frustum[2][3] /= t;
/* Extract the TOP plane */
frustum[3][0] = clip.get(3) - clip.get(1);
frustum[3][1] = clip.get(7) - clip.get(5);
frustum[3][2] = clip.get(11) - clip.get(9);
frustum[3][3] = clip.get(15) - clip.get(13);
/* Normalize the result */
t = (float)Math.sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
frustum[3][0] /= t;
frustum[3][1] /= t;
frustum[3][2] /= t;
frustum[3][3] /= t;
/* Extract the FAR plane */
frustum[4][0] = clip.get(3) - clip.get(2);
frustum[4][1] = clip.get(7) - clip.get(6);
frustum[4][2] = clip.get(11) - clip.get(10);
frustum[4][3] = clip.get(15) - clip.get(14);
/* Normalize the result */
t = (float)Math.sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
frustum[4][0] /= t;
frustum[4][1] /= t;
frustum[4][2] /= t;
frustum[4][3] /= t;
/* Extract the NEAR plane */
frustum[5][0] = clip.get(3) + clip.get(2);
frustum[5][1] = clip.get(7) + clip.get(6);
frustum[5][2] = clip.get(11) + clip.get(10);
frustum[5][3] = clip.get(15) + clip.get(14);
/* Normalize the result */
t = (float)Math.sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
frustum[5][0] /= t;
frustum[5][1] /= t;
frustum[5][2] /= t;
frustum[5][3] /= t;
}
public static boolean pointInFrustum(Vector3f point, float radius){
int p;
for( p = 0; p < 6; p++ ) {
if( frustum[p][0] * point.x + frustum[p][1] * point.y + frustum[p][2] * point.z + frustum[p][3] < -radius ) {
return false;
}
}
return true;
}
}