package com.callumcarmicheal.old.solar;
import java.awt.Font;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.newdawn.slick.Color;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.util.ResourceLoader;
import com.callumcarmicheal.OpenGL.GLUT;
import com.callumcarmicheal.OpenGL.Util;
import com.callumcarmicheal.old.solar.objects.IPlanet;
import com.callumcarmicheal.old.solar.render.Camera;
/*
* @name SolarSystem Demo
* @author Callum Carmicheal
* @date 02/07/2015
*/
public class Main {
public static Main instance;
// Variables
boolean disposing = false;
boolean spinMode = true;
boolean singleStep = false;
TrueTypeFont renderFont;
boolean fontLoaded = false;
boolean renderInfo = true;
Camera renderCamera;
boolean grabMouse = false;
public boolean projectionLines = true;
float
FOV = 60.0f,
zNear = 0.001f, //TODO : fix clipping range (Favour close over far)
zFar = 8500.0f;
// Animation -> Simulation Variables
float HourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); // Set to 0.0f if problem occurs
float DayOfYear = Calendar.getInstance().get(Calendar.DAY_OF_YEAR); // Set to 0.0f if problem occurs
int NumberOfYear = Calendar.getInstance().get(Calendar.YEAR);; // Set to currentYear (MANUALLY) if problem occurs
public float AnimateIncrement = 24.0f; // 24 hour per tick
String simOutput;
List<IPlanet> simObjects;
// Render using code or Objects
boolean HardRender = true;
void keyboardListener() {
// Check if our keyboard listener is created and then execute commands from it
if(Keyboard.isCreated()) {
// HOLD KEYS
renderCamera.keyboardUpdate(false, false);
// Fetch all pressed keys (Press once)
while(Keyboard.next()) {
// Check if key is pressed
if(Keyboard.getEventKeyState()) { /* KEY PRESSED */
if(Keyboard.getEventKey() == Keyboard.KEY_R) {
if ( singleStep ) {
// If ending single step mode
singleStep = false;
spinMode = true; // Restart animation
}
else {
spinMode = !spinMode; // Toggle animation on and off.
}
}
if(Keyboard.getEventKey() == Keyboard.KEY_T) {
singleStep = true;
spinMode = true;
}
if(Keyboard.getEventKey() == Keyboard.KEY_G) {
this.HardRender = !this.HardRender;
}
// Page up
if(Keyboard.getEventKey() == Keyboard.KEY_PRIOR) {
// Double the animation time step
AnimateIncrement *= 2.0f;
}
// Page down
if(Keyboard.getEventKey() == Keyboard.KEY_NEXT) {
// Halve the animation time step
AnimateIncrement /= 2.0f;
}
if(Keyboard.getEventKey() == Keyboard.KEY_M) {
// Toggle mouse grab
this.grabMouse = !this.grabMouse;
}
if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
this.disposing = true;
}
if(Keyboard.getEventKey() == Keyboard.KEY_U) {
this.projectionLines = !this.projectionLines;
}
renderCamera.keyboardUpdate(true, true);
} else /* KEY RELEASED*/ {
renderCamera.keyboardUpdate(true, false);
}
}
} else /* Try to create keyboard listener */ {
try {
Keyboard.create();
} catch (LWJGLException e) {
System.err.println("Failed to create LWJGL Keyboard Listener");
e.printStackTrace();
}
}
}
void mouseListener() {
// Check if our mouse listener is created and then execute commands from it
if(Mouse.isCreated()) {
// Set Grabbed state
Mouse.setGrabbed(this.grabMouse);
if(grabMouse){
// Now do everything we need to
renderCamera.mouseUpdate();
Mouse.setCursorPosition(
(Display.getWidth() / 2),
(Display.getHeight() / 2)
);
}
} else /* Try to create mouse listener */ {
try {
Mouse.create();
} catch (LWJGLException e) {
System.err.println("Failed to create LWJGL Mouse Listener");
e.printStackTrace();
}
}
}
void Animate() {
if(renderCamera.getLocation().y > 3000 || renderCamera.getLocation().y < -3000) {
if(renderCamera.getLocation().y > 6000 || renderCamera.getLocation().y < -6000) {
if(zFar == 100000) {
zNear = 1000f;
zFar = 1000000f;
onWindowResize(false);
}
} else if (zNear == 0.001f) {
zNear = 100f;
zFar = 100000f;
onWindowResize(false);
}
} else {
if(zNear != 0.001f) {
zNear = 0.001f;
zFar = 8500.0f;
onWindowResize(false);
}
}
// Clear the rendering output/buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
//GL11.glEnable(GL11.GL_BLEND);
//GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
Util.fixCamera();
GL11.glScaled(1, 1, 1);
GL11.glPushMatrix();
//GL11.glLoadIdentity();
renderCamera.useCamera();
GL11.glPopMatrix();
//GL11.glPolygonMode( GL11.GL_FRONT_AND_BACK, GL11.GL_LINE );
//GL11.glPolygonMode( GL11.GL_FRONT_AND_BACK, GL11.GL_FILL );
// Update the animation state
if(spinMode) {
// Calculate the time
HourOfDay += AnimateIncrement;
DayOfYear += AnimateIncrement/24.0;
if(DayOfYear > 364) { NumberOfYear++; }
HourOfDay = HourOfDay - ((int)(HourOfDay/24))*24;
DayOfYear = DayOfYear - ((int)(DayOfYear/365))*365;
this.simOutput = (
"Creators: CallumC, Bastien Fremondiere" + "\n" +
"Hour : " + HourOfDay + "\n" +
"Day : " + DayOfYear + "\n" +
"Year : " + NumberOfYear + "\n" +
"H Inc : " + AnimateIncrement + "\n" +
"Spin : " + spinMode + "\n" +
"H Ren : " + HardRender + "\n"
);
}
// Clear the current matrix (Model View)
GL11.glLoadIdentity();
// Back off eight units to be able to view from origin
GL11.glTranslatef( 0.0f, 0.0f, -8.0f );
// Rotate the plane of the elliptic
// (rotate the model's plane about the x axis by fifteen degrees)
GL11.glRotatef( 15.0f, 1.0f, 0.0f, 0.0f );
// Hard Render = Render it using raw code no Planet Objects
//
//if(HardRender)
{
// Draw the sun -- as yellow, sphere
GL11.glColor3f( 1.0f, 1.0f, 0.0f );
GLUT.WireSphere3D( 1, 15, 15 );
// Draw Earth and the Moon
// Earth
{
// Draw the Earth
// First position it around the sun
// Use DayOfYear to determine its position
GL11.glRotatef( (float)(360.0 * (DayOfYear) / 365.0), 0.0f, 1.0f, 0.0f );
GL11.glTranslatef( 5.0f, 0.0f, 0.0f );
GL11.glPushMatrix(); // Save Matrix State
{
// Second, rotate earth on its axis
// Once again we will use HourOfDay to determine its rotation
//GL11.glRotatef( (float)(360.0 * HourOfDay/24.0), 0.0f, 1.0f, 0.0f );
// Third, we draw earth as a Sphere
GL11.glColor3f( 0.2f, 0.2f, 1.0f );
GLUT.WireSphere3F( 0.4f, 10, 10 );
} GL11.glPopMatrix(); // Restore Matrix State
}
// Its earth's sub-domain the Moon!
{
// Draw the moon
// Use DayOfYear to control its rotation around earth
GL11.glRotatef( (float)360.0 * DayOfYear / 365.0f, 0.0f, 1.0f, 0.0f );
GL11.glTranslatef( 0.7f, 0.0f, 0.0f );
GL11.glColor3f( 1f, 1f, 1f );
GLUT.WireSphere3F( 0.1f, 5, 5);
}
/*/} else { */ if(!HardRender)
for(IPlanet planet : simObjects) {
planet.update(HourOfDay, DayOfYear, NumberOfYear);
}
}
if (singleStep) {
spinMode = false;
}
// RENDER THE HOUR AND DAY
if(fontLoaded && renderInfo) {
GL11.glPushMatrix(); {
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix(); {
GL11.glLoadIdentity();
GL11.glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLoadIdentity();
int diff = 15;
renderFont.drawString(10, diff * 0, "Creators: CallumC, Bastien Fremondiere", Color.red);
renderFont.drawString(10, diff * 1, "Version : Beta 0.3", Color.yellow);
renderFont.drawString(10, diff * 2, "LOC : " + renderCamera.getLocation().toString(), Color.green);
renderFont.drawString(10, diff * 3, "ROT : " + renderCamera.getRotation().toString(), Color.green);
renderFont.drawString(10, diff * 4, "Hour : " + HourOfDay, Color.cyan);
renderFont.drawString(10, diff * 5, "Day : " + DayOfYear, Color.cyan);
renderFont.drawString(10, diff * 6, "Year : " + NumberOfYear, Color.cyan);
renderFont.drawString(10, diff * 7, "H Inc : " + AnimateIncrement, Color.cyan);
renderFont.drawString(10, diff * 8, "Spin : " + spinMode, Color.cyan);
renderFont.drawString(10, diff * 9, "H Ren : " + HardRender, Color.cyan);
renderFont.drawString(10, diff * 10, "Controls on Github (PRESS G)", Color.magenta);
// Just leave the matrix mode, it knows where you live (it will blow up the software)
// FINE ILL LEAVE YOU ALONE, JESUS!
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glMatrixMode(GL11.GL_PROJECTION);
} GL11.glPopMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glDisable(GL11.GL_BLEND);
} GL11.glPopMatrix();
GL11.glTranslatef(0, 0, -20);
} // */
GL11.glScaled (0.5f ,0.5f ,0.5f);
// LWJGL ALREADY HANDLES OPENGL FLUSH's AND BUFFER SWAPS (flushes ?) ill leave it in to be safe
GL11.glFlush();
// LWJGL IS ALREADY DUBBLE BUFFERED SO WE DONT NEED TO
// REQUEST ANOTHER BUFFER TO CREATED FOR ANIMATION PURPOSE
}
// This was the original camera code xD
void render_VINGARDIUM_LEVIOSA() {}
// Initialise OpenGL's rendering mode
@Deprecated
void OpenGLInit() {
GL11.glShadeModel( GL11.GL_FLAT );
GL11.glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
GL11.glClearDepth( 1.0 );
GL11.glEnable( GL11.GL_DEPTH_TEST );
}
// Resize the rendering matrix to wrap around the new WxH
// THIS SEEMS TO BE BROKEN
void onWindowResize(boolean createCam) {
int w = Display.getWidth();
int h = Display.getHeight();
float aspectRatio;
// ??????
h = (h == 0) ? 1 : h;
w = (w == 0) ? 1 : w;
// View port uses whole number
aspectRatio = (float)w/(float)h;
// OLD RENDERING SETTINGS
/*/ Setup the projection view matrix
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluLookAt( FOV, aspectRatio, zNear, zFar);
// Select the Model view Matrix
GL11.glMatrixMode (GL11.GL_MODELVIEW);
// Fix scale-ing of objects and stuff?
GL11.glScissor(0, 0, w, h);
GL11.glViewport(0, 0, w, h); */
if(createCam){
renderCamera = new Camera(FOV, aspectRatio, zNear, zFar);
}
else {
if(renderCamera.ISREADY) {
renderCamera.setRenderSettings(FOV, aspectRatio, zNear, zFar);
}
}
}
public void Init(String[] args) {
boolean displayShown = false;
//1 Create and setup Display
//2 Initialise OpenGL
//3 Initialise Keyboard functions
//4 Initialise resize catch
//5 Start Animation in Render Loop
//6 END
try {
Display.setDisplayMode(new DisplayMode(1024, 800));
Display.setResizable(true);
Display.create();
Keyboard.create(); // Create keyboard listener?
Mouse.create();
displayShown = true;
if(displayShown) {
Display.setTitle("LOADING RESOURCES (Loading Font [res/fonts/constan.ttf])");
// load font from a .ttf file
try {
InputStream inputStream = ResourceLoader.getResourceAsStream("res/fonts/constan.ttf");
Font awtFont2 = Font.createFont(Font.TRUETYPE_FONT, inputStream);
awtFont2 = awtFont2.deriveFont(15f); // set font size
renderFont = new TrueTypeFont(awtFont2, true); // Anti-A
fontLoaded = true;
} catch (Exception e) {
e.printStackTrace();
}
Display.setTitle("LOADING RESOURCES (Loading planets)");
//if(!HardRender) {
simObjects = new ArrayList<IPlanet>();
simObjects.add( new com.callumcarmicheal.old.solar.objects.Sun() );
//simObjects.add( new com.callumcarmicheal.old.solar.objects.Mercury() );
//simObjects.add( new com.callumcarmicheal.old.solar.objects.Venus() );
simObjects.add( new com.callumcarmicheal.old.solar.objects.Earth() );
//simObjects.add( new com.callumcarmicheal.old.solar.objects.Mars() );
//simObjects.add( new com.callumcarmicheal.old.solar.objects.Jupiter() );
//}
Display.setTitle("LOADING RESOURCES (Setting OPENGL settings)");
}
} catch (LWJGLException e) {
e.printStackTrace();
}
if(displayShown) {
// Initialise OpenGL
{
onWindowResize(true);
}
Display.setTitle("Solar System Simulation");
// Start Game loop
while (!disposing){
if(!disposing)
disposing = Display.isCloseRequested();
// Now disposing has been updated, check if we are disposing
// if not lets do our logic, if not lets skip it (JUST THIS ONCE OKAY!)
if(!disposing) {
// Do calculations
if(Display.wasResized())
onWindowResize(false);
// Take the Input
mouseListener();
keyboardListener();
// Render
Animate();
// Check if close was requested and Update Display
Display.update();
}
}
} else {
System.out.println("Failed to init the display output");
System.err.println("Please try again later");
System.exit(0);
}
// End the display instance
Display.destroy();
}
}