/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package computergraphicsproject.Engines;
import computergraphicsproject.Engines.CameraHandling.CameraHandler;
import computergraphicsproject.Engines.InputHandling.MouseEvent;
import computergraphicsproject.Engines.InputHandling.KeyboardEvent;
import computergraphicsproject.Engines.InputHandling.InputHandler;
import computergraphicsproject.model.Menus.MenuModel;
import computergraphicsproject.model.Objects.ObjectModel;
import computergraphicsproject.model.Menus.Particle;
import computergraphicsproject.model.Scenes.SceneModel;
import computergraphicsproject.utilities.libraries.GLApp.glapp.GLApp;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
/**
*
* @author hussein
*/
public class GraphicsEngine implements Runnable {
private ArrayList<ObjectModel> objects;
private ArrayList<SceneModel> scenes;
private ArrayList<MenuModel> menus;
private boolean loading = false;
private CameraHandler cameraHandler = new CameraHandler();
private int lastSelectedID = 0;
private InputHandler inputHandler = null;
private boolean exitSignal = false;
private Boolean analygraph = false;
public GraphicsEngine() {
objects = new ArrayList<ObjectModel>();
scenes = new ArrayList<SceneModel>();
menus = new ArrayList<MenuModel>();
}
public void run() {
try {
// Init Display, Keyboard, Mouse, OpenGL
init();
// Main loop
while (!exitSignal) {
if (!Display.isVisible()) { // window is minimized
Thread.sleep(200L);
} else if (Display.isCloseRequested()) { // window X button clicked
exitSignal = true;
continue;
}
if (!menus.isEmpty()) {
renderInSelectionModeMenu();
} else {
renderInSelectionMode();
}
logic(); // do the animation logic here
synchronized (getAnalygraph()) {
if (getAnalygraph() == true) {
renderAnalygraphMode();
} else {
render();
}
}
Display.update();
processInput();
}
} catch (Exception e) {
System.err.println(e);
}
// prepare to exit
cleanup();
System.exit(0);
}
/**
*
*/
public void processInput() {
Mouse.poll();
Keyboard.poll();
if (inputHandler == null) {
return;
}
if (Keyboard.next()) {
inputHandler.keyPressed(new KeyboardEvent(Keyboard.getEventKey(), Keyboard.getEventCharacter(), Keyboard.getEventKeyState()));
}
if (Mouse.next()) {
inputHandler.mousePressed(
new MouseEvent(lastSelectedID,
Mouse.getEventButton(),
Mouse.getDWheel(),
Mouse.getEventDX(),
Mouse.getEventDY(),
Mouse.getEventButtonState(),
Mouse.isButtonDown(0),
Mouse.isButtonDown(1),
Mouse.isButtonDown(2)));
}
}
/**
*
*/
public void init() {
// load settings from config file (display size, resolution, etc.)
// loadSettings(configFilename);
initDisplay();
initInput();
initGL();
}
/**
*
*/
public void initGL() {
try {
// Depth test setup
GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
// Some basic settings
GL11.glClearColor(0f, 0f, 0f, 1f); // Black Background
GL11.glEnable(GL11.GL_NORMALIZE); // force normal lengths to 1
GL11.glEnable(GL11.GL_TEXTURE_2D); // use textures
GL11.glEnable(GL11.GL_BLEND); // enable transparency
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GL11.glEnable(GL11.GL_TEXTURE_1D);
// How to handle transparency: average colors together
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// Enable alpha test so the transparent backgrounds in texture images don't draw.
// This prevents transparent areas from affecting the depth or stencil buffer.
// alpha func will accept only fragments with alpha greater than 0
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glAlphaFunc(GL11.GL_GREATER, 0f);
// Perspective quality
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
// Set the size and shape of the screen area
GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(),
Display.getDisplayMode().getHeight());
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45f,
(float) Display.getDisplayMode().getWidth()
/ Display.getDisplayMode().getHeight(), 0.01f, 100000f);
// return to modelview matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
} catch (Exception e) {
System.err.println(e);
}
}
private void setOrthoOn() {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix(); // preserve perspective view
GL11.glLoadIdentity(); // clear the perspective matrix
GL11.glOrtho( // turn on 2D mode
0, Display.getDisplayMode().getWidth(), // left, right
Display.getDisplayMode().getHeight(), // bottom, top
0, -5, 5); // Zfar, Znear
// clear the modelview matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPushMatrix(); // Preserve the Modelview Matrix
GL11.glLoadIdentity(); // clear the Modelview Matrix
}
private void setOrthoOff() {
// restore the original positions and views
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPopMatrix();
}
/**
*
*/
public void initDisplay() {
// Initialize the Window
try {
Display.create();
Display.setTitle("Chess");
Display.setFullscreen(false);
} catch (Exception exception1) {
System.err.println(exception1);
System.exit(1);
}
}
/**
*
*/
public void renderInSelectionModeMenu() {
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
int buffer[] = new int[512]; // Set Up A Selection Buffer
int hits; // The Number Of Objects That We Selected
// The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>
int viewport[] = new int[4];
// This Sets The Array <viewport> To The Size And Location Of The Screen Relative To The Window
IntBuffer temp = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
temp.order();
GL11.glGetInteger(GL11.GL_VIEWPORT, temp);
temp.get(viewport);
//temp = ByteBuffer.allocateDirect(2048).asIntBuffer();
temp = ByteBuffer.allocateDirect(2048).order(ByteOrder.nativeOrder()).asIntBuffer();
temp.order();
//temp = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asIntBuffer();
GL11.glSelectBuffer(temp); // Tell OpenGL To Use Our Array For Selection
// Puts OpenGL In Selection Mode. Nothing Will Be Drawn. Object ID's and Extents Are Stored In The Buffer.
GL11.glRenderMode(GL11.GL_SELECT);
GL11.glInitNames(); // Initializes The Name Stack
GL11.glPushName(0); // Push 0 (At Least One Entry) Onto The Stack
GL11.glMatrixMode(GL11.GL_PROJECTION); // Selects The Projection Matrix
GL11.glPushMatrix(); // Push The Projection Matrix
GL11.glLoadIdentity(); // Resets The Matrix
// This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is.
GLU.gluPickMatrix((float) Mouse.getX(), (float) (Mouse.getY()), 1f, 1f, IntBuffer.wrap(viewport));
GL11.glOrtho( // turn on 2D mode
0, Display.getDisplayMode().getWidth(), // left, right
Display.getDisplayMode().getHeight(), // bottom, top
0, -5, 5);
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
// Preserve the Modelview Matrix
synchronized (menus) {
for (MenuModel model : menus) {
model.render();
}
} // Render The Targets To The Selection Buffer
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glPopMatrix(); // Pop The Projection Matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW);
hits = GL11.glRenderMode(GL11.GL_RENDER); // Switch To Render Mode, Find Out How Many
temp.get(buffer);
if (hits > 0) { // If There Were More Than 0 Hits
long depth = buffer[1]; // Store How Far Away It Is
int choose = buffer[3]; // Make Our Selection The First Object
for (int i = 1; i < hits; i++) { // Loop Through All The Detected Hits
// If This Object Is Closer To Us Than The One We Have Selected
if (buffer[i * 4 + 3] == 9999) {
continue;
}
if (buffer[i * 4 + 1] < depth) {
choose = buffer[i * 4 + 3]; // Select The Closer Object
depth = buffer[i * 4 + 1]; // Store How Far Away It Is
}
}
lastSelectedID = choose;
} else {
lastSelectedID = 0;
}
}
/**
*
*/
public void renderInSelectionMode() {
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
int buffer[] = new int[512]; // Set Up A Selection Buffer
int hits; // The Number Of Objects That We Selected
// The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>
int viewport[] = new int[4];
// This Sets The Array <viewport> To The Size And Location Of The Screen Relative To The Window
IntBuffer temp = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
temp.order();
GL11.glGetInteger(GL11.GL_VIEWPORT, temp);
temp.get(viewport);
//temp = ByteBuffer.allocateDirect(2048).asIntBuffer();
temp = ByteBuffer.allocateDirect(2048).order(ByteOrder.nativeOrder()).asIntBuffer();
temp.order();
//temp = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asIntBuffer();
GL11.glSelectBuffer(temp); // Tell OpenGL To Use Our Array For Selection
// Puts OpenGL In Selection Mode. Nothing Will Be Drawn. Object ID's and Extents Are Stored In The Buffer.
GL11.glRenderMode(GL11.GL_SELECT);
GL11.glInitNames(); // Initializes The Name Stack
GL11.glPushName(0); // Push 0 (At Least One Entry) Onto The Stack
GL11.glMatrixMode(GL11.GL_PROJECTION); // Selects The Projection Matrix
GL11.glPushMatrix(); // Push The Projection Matrix
GL11.glLoadIdentity(); // Resets The Matrix
// This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is.
GLU.gluPickMatrix((float) Mouse.getX(), (float) (Mouse.getY()), 1f, 1f, IntBuffer.wrap(viewport));
// Apply The Perspective Matrix
GLU.gluPerspective(45f,
(float) Display.getDisplayMode().getWidth()
/ Display.getDisplayMode().getHeight(), 0.01f, 10000f);
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
cameraHandler.applyCamera();
synchronized (objects) {
for (ObjectModel model : objects) {
model.render();
}
} // Render The Targets To The Selection Buffer
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glPopMatrix(); // Pop The Projection Matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
hits = GL11.glRenderMode(GL11.GL_RENDER); // Switch To Render Mode, Find Out How Many
temp.get(buffer);
if (hits > 0) { // If There Were More Than 0 Hits
long depth = buffer[1]; // Store How Far Away It Is
int choose = buffer[3]; // Make Our Selection The First Object
for (int i = 1; i < hits; i++) { // Loop Through All The Detected Hits
// If This Object Is Closer To Us Than The One We Have Selected
if (buffer[i * 4 + 3] == 9999) {
continue;
}
if (buffer[i * 4 + 1] < depth) {
choose = buffer[i * 4 + 3]; // Select The Closer Object
depth = buffer[i * 4 + 1]; // Store How Far Away It Is
}
}
//System.out.println(choose + " " + depth);
//if(choose ==)
lastSelectedID = choose;
} else {
lastSelectedID = 0;
}
}
/**
*
*/
public void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLoadIdentity();
GL11.glPushMatrix();
cameraHandler.applyCamera();
setOrthoOn();
GLApp.setLight(GL11.GL_LIGHT7,
new float[]{1.0f, 1.0f, 0.15f, 1.0f}, // diffuse color
new float[]{1.0f, 1.0f, 1.0f, 1.0f}, // ambient
new float[]{0.03f, 0.0f, 0.0f, 1.0f}, // specular
new float[]{0, 0, 10, 0});
synchronized (menus) {
for (MenuModel menu : menus) {
menu.render();
}
}
GL11.glDisable(GL11.GL_LIGHT7);
setOrthoOff();
if (!loading) {
synchronized (scenes) {
for (SceneModel scene : scenes) {
scene.render();
}
}
synchronized (objects) {
for (ObjectModel model : objects) {
model.render();
}
}
}
GL11.glPopMatrix();
}
private void logic() {
synchronized (objects) {
for (ObjectModel object : objects) {
if (object.getID() != 9999) {
if (lastSelectedID == object.getID()) {
object.logic(1);
} else {
object.logic(0);
}
}
}
}
synchronized (menus) {
for (MenuModel menuItmes : menus) {
if (menuItmes.getID() != 9999) {
if (lastSelectedID == menuItmes.getID()) {
menuItmes.logic(1);
} else {
menuItmes.logic(0);
}
}
}
}
}
/**
*
*/
public void renderAnalygraphMode() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLoadIdentity();
GL11.glColorMask(true, false, false, true);
GL11.glPushMatrix();
cameraHandler.applyRightCamera();
setOrthoOn();
GLApp.setLight(GL11.GL_LIGHT7,
new float[]{1.0f, 1.0f, 0.15f, 1.0f}, // diffuse color
new float[]{1.0f, 1.0f, 1.0f, 1.0f}, // ambient
new float[]{0.03f, 0.0f, 0.0f, 1.0f}, // specular
new float[]{0, 0, 10, 0});
synchronized (menus) {
for (MenuModel menu : menus) {
menu.render();
}
}
GL11.glDisable(GL11.GL_LIGHT7);
setOrthoOff();
if (!loading) {
synchronized (scenes) {
for (SceneModel scene : scenes) {
scene.render();
}
}
synchronized (objects) {
for (ObjectModel model : objects) {
model.render();
}
}
}
GL11.glPopMatrix();
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColorMask(false, true, true, true);
GL11.glPushMatrix();
cameraHandler.applyLeftCamera();
setOrthoOn();
GLApp.setLight(GL11.GL_LIGHT7,
new float[]{1.0f, 1.0f, 0.15f, 1.0f}, // diffuse color
new float[]{1.0f, 1.0f, 1.0f, 1.0f}, // ambient
new float[]{0.03f, 0.0f, 0.0f, 1.0f}, // specular
new float[]{0, 0, 10, 0});
synchronized (menus) {
for (MenuModel menu : menus) {
menu.render();
}
}
GL11.glDisable(GL11.GL_LIGHT7);
setOrthoOff();
if (!loading) {
synchronized (scenes) {
for (SceneModel scene : scenes) {
scene.render();
}
}
synchronized (objects) {
for (ObjectModel model : objects) {
model.render();
}
}
}
GL11.glPopMatrix();
GL11.glColorMask(true, true, true, true);
}
/**
*
*/
public void cleanup() {
Keyboard.destroy();
Mouse.destroy();
Display.destroy();
}
/**
*
*/
public void initInput() {
try {
// init keyboard and mouse
Keyboard.create();
Mouse.create();
Mouse.setGrabbed(false);
} catch (Exception e) {
System.err.println(e);
}
}
/**
*
* @param object
*/
public void addObject(ObjectModel object) {
synchronized (objects) {
objects.add(object);
}
}
/**
*
* @param scene
*/
public void addScene(SceneModel scene) {
synchronized (scenes) {
scenes.add(scene);
}
}
/**
*
* @param menu
*/
public void addMenu(MenuModel menu) {
synchronized (menus) {
menus.add(menu);
}
}
/**
*
* @param menu
*/
public void removeMenu(MenuModel menu) {
synchronized (menus) {
menus.remove(menu);
}
}
public void removeAllMenus() {
synchronized (menus) {
menus.clear();
}
}
/**
*
* @param object
*/
public void removeObject(ObjectModel object) {
synchronized (objects) {
objects.remove(object);
}
}
/**
*
* @param scene
*/
public void removeScene(SceneModel scene) {
synchronized (scenes) {
scenes.remove(scene);
}
}
/**
*
*/
public void clearDisplay() {
synchronized (menus) {
menus.clear();
}
synchronized (objects) {
objects.clear();
}
synchronized (scenes) {
scenes.clear();
}
}
/**
*
* @return
*/
public boolean isLoading() {
return loading;
}
/**
*
* @param loading
*/
public void setLoading(boolean loading) {
this.loading = loading;
}
/**
*
*/
public void clearInputHandler() {
inputHandler = null;
}
/**
*
* @param inputHandler
*/
public void setInputHandler(InputHandler inputHandler) {
this.inputHandler = inputHandler;
}
/**
*
* @return
*/
public int getLastSelectedID() {
return lastSelectedID;
}
/**
*
* @return
*/
public CameraHandler getCameraHandler() {
return cameraHandler;
}
/**
*
* @param exitSignal
*/
public void setExitSignal(boolean exitSignal) {
this.exitSignal = exitSignal;
}
void addMenus(MenuModel[] newMenus) {
synchronized (menus) {
for (int i = 0; i < newMenus.length; i++) {
menus.add(newMenus[i]);
}
}
}
void addMenus(Particle[] newParticles) {
synchronized (menus) {
for (int i = 0; i < newParticles.length; i++) {
menus.add(newParticles[i]);
}
}
}
public static FloatBuffer allocFloats(int howmany) {
return ByteBuffer.allocateDirect(howmany * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
}
public static FloatBuffer allocFloats(float[] floatarray) {
FloatBuffer fb = ByteBuffer.allocateDirect(floatarray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
fb.put(floatarray).flip();
return fb;
}
public static void setSpotLight(int GLLightHandle,
float[] diffuseLightColor,
float[] ambientLightColor,
float[] specularLightColor,
float[] position, float[] direction, float cutoffAngle) {
FloatBuffer ltDirection = allocFloats(direction);
setLight(GLLightHandle, diffuseLightColor, ambientLightColor, specularLightColor, position);
GL11.glLightf(GLLightHandle, GL11.GL_SPOT_CUTOFF, cutoffAngle); // width of the beam
GL11.glLight(GLLightHandle, GL11.GL_SPOT_DIRECTION, ltDirection); // which way it points
GL11.glLightf(GLLightHandle, GL11.GL_CONSTANT_ATTENUATION, 2F); // how light beam drops off
}
public static void setLight(int GLLightHandle,
float[] diffuseLightColor,
float[] ambientLightColor,
float[] specularLightColor,
float[] position) {
FloatBuffer ltDiffuse = allocFloats(diffuseLightColor);
FloatBuffer ltAmbient = allocFloats(ambientLightColor);
FloatBuffer ltSpecular = allocFloats(specularLightColor);
FloatBuffer ltPosition = allocFloats(position);
GL11.glLight(GLLightHandle, GL11.GL_DIFFUSE, ltDiffuse); // color of the direct illumination
GL11.glLight(GLLightHandle, GL11.GL_SPECULAR, ltSpecular); // color of the highlight
GL11.glLight(GLLightHandle, GL11.GL_AMBIENT, ltAmbient); // color of the reflected light
GL11.glLight(GLLightHandle, GL11.GL_POSITION, ltPosition);
GL11.glEnable(GLLightHandle);
}
public static void disableAllLights() {
GL11.glDisable(GL11.GL_LIGHT0);
GL11.glDisable(GL11.GL_LIGHT1);
GL11.glDisable(GL11.GL_LIGHT2);
GL11.glDisable(GL11.GL_LIGHT3);
GL11.glDisable(GL11.GL_LIGHT4);
GL11.glDisable(GL11.GL_LIGHT5);
GL11.glDisable(GL11.GL_LIGHT6);
}
/**
* @return the analygraph
*/
public Boolean getAnalygraph() {
return analygraph;
}
/**
* @param analygraph the analygraph to set
*/
public void setAnalygraph(boolean analygraph) {
synchronized (this.analygraph) {
this.analygraph = analygraph;
}
}
}
|