package solarsim.gl;
import solarsim.common.State;
import solarsim.*;
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureCoords;
import com.sun.opengl.util.texture.TextureIO;
import java.awt.Frame;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;
/**
* SolarSim.java
* author: Brian Paul (converted to Java by Ron Cemer and Sven Goethel)
*
* This version is equal to Brian Paul's version 1.2 1999/10/21
*/
public class SolarSim implements GLEventListener, Runnable, KeyListener, MouseListener {
float rotate = 0;
private final double SCALE_FACTOR = 150E9F; // 150 million km
int MoveX = 0;
int MoveY = 0;
float x1[][]= new float[361][2];
float x2[][]= new float[361][2];
float x3[][]= new float[721][2];
float Xvalue = 0;
float Yvalue = 0;
float Angle = 0;
static final int MODE_SCALE = 0;
static final int MODE_ROTATE = 1;
static final int MODE_NOTHING = -1;
int press_x, press_y;
float msX_angle = 0;
float msY_angle = 0;
int mouseX, mouseY;
int mode ;
float scale_size = 1;
private GLU glu = new GLU();
//private boolean newTexture;
private boolean flushTexture;
private File file;
private Texture textureEarth, textureSun;
private LinkedList states;
static int count = 0;
private volatile boolean running;
private Thread thread;
Iterator it;
public SolarSim(){
this.states = new LinkedList();
}
void drawState(State s) {
if( count == 0 )
System.out.println(s);
if( count++ % 1 != 0 )
return;
if( s == null )
return;
synchronized( states ) {
states.addFirst(s);
states.notify();
}
}
public void init(GLAutoDrawable drawable) {
// Use debug pipeline
// drawable.setGL(new DebugGL(drawable.getGL()));
int i = 0;
for(i=0; i <= 360; i++)
{
x1[i][0] = (float)(Math.sin(i*3.1416/180)*3);
x1[i][1] = (float)(Math.cos(i*3.1416/180)*3);
}
for(i=0; i <= 360; i++)
{
x2[i][0] = (float)(Math.sin(i*3.1416/180)*1);
x2[i][1] = (float)(Math.cos(i*3.1416/180)*1);
}
for(i=0; i <= 720; i++)
{
x3[i][0] = (float)(Math.sin(i*3.1416/180)*5);
x3[i][1] = (float)(Math.cos(i*3.1416/180)*5);
}
GL gl = drawable.getGL();
System.err.println("INIT GL IS: " + gl.getClass().getName());
// Enable VSync
gl.setSwapInterval(1);
// Setup the drawing area and shading mode
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glShadeModel(GL.GL_SMOOTH); // try setting this to GL_FLAT and see what happens.
it = states.iterator();
/* gl.glViewport(0,0,500,300);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, 800.0f / 600.0f, 1.0f, 500.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);*/
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL gl = drawable.getGL();
//GLU glu = new GLU();
if (height <= 0) { // avoid a divide by zero error!
height = 1;
}
final float h = (float) width / (float) height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, h, 1.0, 20.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void display(GLAutoDrawable drawable) {
/* synchronized( states ) {
while( states.isEmpty() ) {
try {
states.wait();
} catch (InterruptedException ex) { }
}
}*/
//if (it.hasNext())
// while (it.hasNext())
// {
// State s = it.next();
try {
GL gl = drawable.getGL();
File file = new File("images/earthS.png");
textureEarth = TextureIO.newTexture(file, true);
file = new File("images/sunS.jpg");
textureSun = TextureIO.newTexture(file, true);
// Clear the drawing area
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// Reset the current matrix to the "identity"
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -6.0f);
if (mode == MODE_ROTATE) {
msX_angle += (mouseX - press_x) / 5.0;
// System.out.println("changed "+msX_angle);
if (msX_angle > 180) {
msX_angle -= 360;
} else if (msX_angle < -180) {
msX_angle += 360;
}
press_x = mouseX;
msY_angle += (mouseY - press_y) / 5.0;
if (msY_angle > 180) {
msY_angle -= 360;
} else if (msY_angle < -180) {
msY_angle += 360;
}
press_y = mouseY;
} else if (mode == MODE_SCALE) {
float old_size = scale_size;
scale_size *= (1 + (mouseY - press_y) / 60.0);
if (scale_size < 0) {
scale_size = old_size;
}
press_y = mouseY;
}
//glu.gluLookAt(0.0, 7.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
glu.gluLookAt(0,7,2, 0,0,0, 0,1,0);
gl.glColor3f((float) 1.0, (float) 1.0, (float) 1.0);
//rotate scale the entire image
gl.glRotatef(msX_angle, 0, 1, 0);
gl.glRotatef(msY_angle, 1, 0, 0);
gl.glScalef(scale_size, scale_size, scale_size);
GLUquadric qobj = glu.gluNewQuadric();
glu.gluQuadricDrawStyle(qobj, GLU.GLU_FILL);
glu.gluQuadricNormals(qobj, GLU.GLU_SMOOTH);
/* synchronized(states) {
// for( State s : states ) {
Particle p = s.getParticles().get(0);
Vector r = p.getPosition();
int dx = +(int)(r.x/SCALE_FACTOR*300)/20;
int dy = -(int)(r.y/SCALE_FACTOR*300)/20;
System.out.println(dx + " " + dy);
//earth
// glu.gluLookAt (0.0, 10.0, 2.0, 0.0, 0.0, 0.0, 1.0, .0, 0.0);
gl.glPushMatrix();
gl.glTranslatef(dx, dy, 0.0f);
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
gl.glColor3f(0f, 0f, 1f);
glu.gluSphere(qobj,0.2, 15, 15);
gl.glTranslatef(-dx, -dy, 0.0f);
gl.glPopMatrix();
// }
//}*/
/* gl.glPushMatrix();
gl.glTranslatef(Xvalue, 0.0f, Yvalue);
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
gl.glColor3f(0f, 0f, 1f);
glu.gluSphere(qobj,0.5, 20, 20);
gl.glTranslatef(Xvalue, 0.0f, Yvalue);
gl.glPopMatrix();*/
if (textureSun != null) {
textureSun.enable();
textureSun.bind();
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
TextureCoords coords = textureSun.getImageTexCoords();
//sun
gl.glPushMatrix();
//glu.gluLookAt (0.0, 10.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
gl.glTranslatef(Xvalue, 0.0f, Yvalue);
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
//glu.gluQuadricNormals(qobj, GLU.GLU_SMOOTH);
// gl.glColor4f(1f, 1f, 0f, 1f);
gl.glTexCoord2f(coords.left(), coords.bottom());
glu.gluQuadricTexture(qobj, true);
glu.gluSphere(qobj, 0.2f, 15, 15);
textureSun.disable();
glu.gluQuadricTexture(qobj, false);
gl.glPopMatrix();
}
if (textureEarth != null) {
textureEarth.enable();
textureEarth.bind();
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
TextureCoords coords = textureEarth.getImageTexCoords();
//earth
//glu.gluLookAt (0.0, 10.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
gl.glPushMatrix();
if (MoveX == 360) {
MoveX = 0;
}
gl.glTranslatef(x1[MoveX][1], x1[MoveX][0], 0.0f);
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
//gl.glColor3f(0f, 0f, 1f);
gl.glTexCoord2f(coords.left(), coords.bottom());
glu.gluQuadricTexture(qobj, true);
glu.gluSphere(qobj, 0.3f, 15, 15);
textureEarth.disable();
glu.gluQuadricTexture(qobj, false);
gl.glTranslatef(x2[MoveX][0], x2[MoveX][1], 0.0f);
glu.gluSphere(qobj, 0.1f, 10, 10);
gl.glPopMatrix();
}
//saturn
gl.glPushMatrix();
// glu.gluLookAt (0.0, 10.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
if (MoveY == 720) {
MoveY = 0;
}
gl.glTranslatef(x3[MoveY / 2][1], x3[MoveY / 2][0], 0.0f);
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
glu.gluSphere(qobj, 0.3f, 15, 15);
int i = 0;
//glBegin(GL_LINE_STRIP);
gl.glBegin(gl.GL_QUAD_STRIP);
for (i = 0; i <= 360; i++) {
gl.glVertex3f((float) (Math.sin(i*3.1416/180)*0.5), (float) (Math.cos(i*3.1416/180)*0.5), 0f);
gl.glVertex3f((float) (Math.sin(i*3.1416/180)*0.7), (float) (Math.cos(i*3.1416/180)*0.7), 0f);
}
gl.glEnd();
gl.glRotatef(Angle, 0.0f, 0.0f, 1.0f);
gl.glPopMatrix();
gl.glFlush();
Angle += 15.0;
// glu.glutPostRedisplay();
MoveX += 1;
MoveY += 1;
// Flush all drawing operations to the graphics card
} catch (Exception ex) {
Logger.getLogger(SolarSim.class.getName()).log(Level.SEVERE, null, ex);
}
//}
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
public void run() {
this.running = true;
this.thread = Thread.currentThread();
while( running ) {
synchronized( states ) {
while( states.isEmpty() ) {
try {
states.wait();
} catch (InterruptedException ex) { }
}
// State s = states.removeLast();
}
try {
thread.sleep(40);
} catch( Exception ex ) {}
}
}
public void keyTyped(KeyEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
public void keyPressed(KeyEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
public void keyReleased(KeyEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseClicked(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void mousePressed(MouseEvent e) {
System.out.println("pressed");
switch(e.getModifiers()) {
case InputEvent.BUTTON1_MASK: {
mode = MODE_ROTATE;
mouseX=e.getX();
mouseY=e.getY();
System.out.println("That's the LEFT button");
break;
}
case InputEvent.BUTTON3_MASK: {
mode = MODE_SCALE;
mouseX=e.getX();
mouseY=e.getY();
System.out.println("That's the RIGHT button");
break;
}
//throw new UnsupportedOperationException("Not supported yet.");
}
}
public void mouseReleased(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseEntered(MouseEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseExited(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public static void main(String[] args) {
try{
SolarSim sim = new SolarSim();
new Thread(sim).start();
Frame frame = new Frame("Simple JOGL Application");
GLCanvas canvas = new GLCanvas();
canvas.requestFocus();
canvas.addGLEventListener(sim);
canvas.addKeyListener(sim);
canvas.addMouseListener(sim);
frame.add(canvas);
frame.setSize(800, 600);
final Animator animator = new Animator(canvas);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// Run this on another thread than the AWT event queue to
// make sure the call to Animator.stop() completes before
// exiting
new Thread(new Runnable() {
public void run() {
animator.stop();
System.exit(0);
}
}).start();
}
});
// Center frame
frame.setLocationRelativeTo(null);
frame.setVisible(true);
animator.start();
/* InputStream is = new FileInputStream("sim.dat");
// TODO must have stop message
for( int i = 0; i < 1000000; i++ ) {
State s = State.readStateFromInputStream(is);
sim.drawState(s);
}*/
System.out.println("Stopping.");
Thread.currentThread().sleep(1000 * 10);
} catch(Exception e) {
e.printStackTrace();
}
}
}