import java.nio.*; // Native IO buffers: LWJGL uses these to efficiently exchange data with system memory
import java.util.*;
import org.lwjgl.Sys;
import org.lwjgl.opengl.*;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.opengl.glu.Sphere;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.glu.*;
/**
* Circle crawling in random direction, turning random colors and leaving traces on the screen
combines lighting and screen saving -- draws in spheres, circles and squares
Press 's' to toggle sqare mode, and 'f' to toggle circle mode
*/
public class circles5 {
private boolean done = false;
private final String windowTitle = "Crawlies";
private DisplayMode displayMode;
double startTime, currentTime;
Random rn = new Random();
int randx =0, randy = 0, randz =0;
int randr =0, randg = 0, randb = 0;
float r = .5f, g = .1f, b = .1f;
float x = 0, y = 0, z = 0;
// For copying screen image to a texture
int screenTextureSize = 1024; // how large should texture be to hold screen
// will hold screen image as texture
int screenTextureHandle;
boolean square = false, flat = false, ball = true;
Sphere s = new Sphere();
// color of light source
float lightDiffuse[] = { 1f, .6f, .6f, 1f }; // direct light (reddish)
float lightSpecular[] = { 1f, .6f, .6f, 1f };
float lightAmbient[] = { .5f, .1f, .1f, 1f};
// light position: if last value is 0, then this describes light direction. If 1, then light position.
float lightPosition[] = {-2, 4, 3, 0};
// Material for planet
GLMaterial material = new GLMaterial();
float mtlDiffuse[] = { r, g, b, .2f }; // purple
float mtlAmbient[] = { .1f, 0f, .2f, 1f }; // dark purple
float mtlSpecular[] = { .6f, .6f, .6f, 1f }; // light gray: reflective
float mtlShininess = 100f; // 0=no shine, 127=max shine
/**
* Main function just creates and runs the application.
*/
public static void main(String args[]) {
circles5 app = new circles5();
app.run();
}
/**
* Initialize the app, then sit in a render loop until done==true.
*/
public void run() {
try {
init();
while (!done) {
mainloop();
render();
Display.update();
}
cleanup();
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
/**
* Initialize the environment
* @throws Exception
*/
private void init() throws Exception {
initDisplay();
initGL();
startTime = currentTime = getTimeInMillis();
// allocate a texture big enough to hold screen image
// the texure will be square, the dimensions will be some power of two, as
// large or larger than the width of the screen.
screenTextureHandle = makeTextureForScreen(displayMode.getWidth());
// capture the screen now to initialize the texture image
// It's a good idea to call glClear() before capturing the screen for the first time.
frameSave(screenTextureHandle);
}
/**
* Create an OpenGL display, in this case a fullscreen window.
* @throws Exception
*/
private void initDisplay() throws Exception {
// set to full screen, no chrome
Display.setFullscreen(false);
// get all possible display resolutions
DisplayMode d[] = Display.getAvailableDisplayModes();
// find a resolution we like
for (int i = 0; i < d.length; i++) {
if (d[i].getWidth() == 800
&& d[i].getHeight() == 600
&& d[i].getBitsPerPixel() == 32) {
displayMode = d[i];
break;
}
}
Display.setVSyncEnabled(true);
Display.setFullscreen(false);
// set the display to the resolution we picked
Display.setDisplayMode(displayMode);
Display.setTitle(windowTitle);
// create the window
Display.create();
}
/**
* Initialize OpenGL
*
*/
private void initGL() {
// make sure OpenGL correctly layers objects
GL11.glEnable(GL11.GL_DEPTH_TEST);
// OpenGL won't draw backward facing triangles ("back faces")
GL11.glEnable(GL11.GL_CULL_FACE);
// set the background color
GL11.glClearColor(0f, 0f, .07f, 1);
// blending
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// Force normals to length 1
GL11.glEnable(GL11.GL_NORMALIZE);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
setLight( GL11.GL_LIGHT0, lightDiffuse, lightAmbient, lightSpecular, lightPosition );
// need textures on for frameDraw() to work
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
/**
* Handle keyboard input. Just check for escape key or user
* clicking to close the window.
*/
private void mainloop() {
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Escape is pressed
done = true;
}
if(Display.isCloseRequested()) { // Window is closed
done = true;
}
if(Keyboard.isKeyDown(Keyboard.KEY_S)){
square = true;
flat = false; ball = false;
}
if(Keyboard.isKeyDown(Keyboard.KEY_F)){
flat = true;
square = false; ball = false;
}
if(Keyboard.isKeyDown(Keyboard.KEY_B)){
ball = true;
square = false; flat = false;
}
}
// float backZ=1, frontZ=0;
/**
* Render the scene.
*/
private void render() {
// NOTE: This switches matrix mode to PROJECTION
frameDraw(screenTextureHandle);
// Select the Projection Matrix (controls perspective)
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Define perspective
GLU.gluPerspective(
45.0f, // Field Of View
(float)displayMode.getWidth() / (float)displayMode.getHeight(), // aspect ratio
0.1f, // near Z clipping plane
100.0f); // far Z clipping plane
// Reset The Model view Matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
// Where is the 'eye'
GLU.gluLookAt(
0f, 0, 10, // eye position
0, 0f, 0f, // target to look at
0f, 1f, 0f); // which way is up
GL11.glMatrixMode(GL11.GL_MODELVIEW);
// Clear screen and depth buffer
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
currentTime = getTimeInMillis();
if(currentTime - startTime > 100){
if(ball) drawCircles();
else if(square) drawSquares();
else if (flat) drawFlat();
startTime = currentTime;
}
// save the screen image to a texture
// do this after you've drawn everything you want to save
frameSave(screenTextureHandle);
}
private void drawFlat()
{
//System.out.println(x+" "+ y +" "+z);
switch(randx){
case 0: x -=.2f; break;
case 1: x = 0; break;
case 2: x += .2f; break;
case 3: x -=.4f; break;
case 4: x += .3f; break;
case 5: x += .4f; break;
}
switch(randy){
case 0: y += .2f; break;
case 1: y = 0; break;
case 2: y -= .2f; break;
case 3: y -=.4f; break;
case 4: y += .3f; break;
case 5: y += .4f; break;
}
switch(randz){
case 0: z -= .2f; break;
case 1: z = 0; break;
case 2: z += .2f; break;
case 3: z -=.4f; break;
case 4: z += .3; break;
case 5: z += .4f; break;
}
switch(randr){
case 0: r -= .05f; break;
case 1: break;
case 2: r += .05f; break;
}
switch(randg){
case 0: g -= .05f; break;
case 1: break;
case 2: g += .05f; break;
}
switch(randb){
case 0: b -= .05f; break;
case 1: break;
case 2: b += .05f; break;
}
if(r
<0) r =0;
if(r>1) r =1;
if(g<0) g =0;
if(g>1) g =1;
if(b<0) b =0;
if(b>1) b =1;
/* if(x>200) x=200;
if(x<-200) x=-200;
if(y>200) y=200;
if(y<-200) y=-200;
if(z>90) z=90;
if(z<1) z=1;*/
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_BLEND);
GL11.glTranslatef(x, y, z);
GL11.glColor4f(r, g, b, .02f);
renderSphere();
randx = rn.nextInt(6);
randy = rn.nextInt(6);
randz = rn.nextInt(6);
randr = rn.nextInt(3);
randg = rn.nextInt(3);
randb = rn.nextInt(3);
}
private void drawCircles()
{
//System.out.println(x+" "+ y +" "+z);
mtlDiffuse[0] = r;
mtlDiffuse[1] = g;
mtlDiffuse [2] = b;
mtlDiffuse [3] = .1f;
mtlAmbient[0] = r/4;
mtlAmbient[1] = g/4;
mtlAmbient[2] = b/4;
mtlAmbient [3] = 1f;
// "planet" material settings
material.setSurfaceColorLit(mtlDiffuse);
material.setSurfaceColorShadow(mtlAmbient);
material.setReflectionColor(mtlSpecular);
material.setShininess(mtlShininess);
material.apply();
switch(randx){
case 0: x -=.2f; break;
case 1: x = 0; break;
case 2: x += .2f; break;
case 3: x -=.4f; break;
case 4: x += .3f; break;
case 5: x += .4f; break;
}
switch(randy){
case 0: y += .2f; break;
case 1: y = 0; break;
case 2: y -= .2f; break;
case 3: y -=.4f; break;
case 4: y += .3f; break;
case 5: y += .4f; break;
}
switch(randz){
case 0: z -= .2f; break;
case 1: z = 0; break;
case 2: z += .2f; break;
case 3: z -=.4f; break;
case 4: z += .3; break;
case 5: z += .4f; break;
}
switch(randr){
case 0: r -= .05f; break;
case 1: break;
case 2: r += .05f; break;
}
switch(randg){
case 0: g -= .05f; break;
case 1: break;
case 2: g += .05f; break;
}
switch(randb){
case 0: b -= .05f; break;
case 1: break;
case 2: b += .05f; break;
}
if(r< .1f) r =.1f;
if(r>1) r =1;
if(g< .1f) g =.1f;
if(g>1) g =1;
if(b<0) b =0;
if(b>1) b =1;
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glTranslatef(x, y, z);
renderSphere();
randx = rn.nextInt(6);
randy = rn.nextInt(6);
randz = rn.nextInt(6);
randr = rn.nextInt(3);
randg = rn.nextInt(3);
randb = rn.nextInt(3);
}
private void drawSquares()
{
//System.out.println(x+" "+ y +" "+z);
switch(randx){
case 0: x -=.2f; break;
case 1: x = 0; break;
case 2: x += .2f; break;
case 3: x -=.4f; break;
case 4: x += .3f; break;
case 5: x += .4f; break;
}
switch(randy){
case 0: y += .2f; break;
case 1: y = 0; break;
case 2: y -= .2f; break;
case 3: y -=.4f; break;
case 4: y += .3f; break;
case 5: y += .4f; break;
}
switch(randz){
case 0: z -= .2f; break;
case 1: z = 0; break;
case 2: z += .2f; break;
case 3: z -=.4f; break;
case 4: z += .3; break;
case 5: z += .4f; break;
}
switch(randr){
case 0: r -= .05f; break;
case 1: break;
case 2: r += .05f; break;
}
switch(randg){
case 0: g -= .05f; break;
case 1: break;
case 2: g += .05f; break;
}
switch(randb){
case 0: b -= .05f; break;
case 1: break;
case 2: b += .05f; break;
}
if(r
* @see makeTextureForScreen() * @param dimension * @return a power of two bigger than the given dimension */ public static int getPowerOfTwoBiggerThan(int dimension) { for (int exp=1; exp <= 32; exp++) { if (dimension <= Math.pow(2, exp)) { return (int)Math.pow(2, exp); } } return 0; } /** * Save entire screen image to a texture. Will copy entire screen even * if a viewport is in use. Texture param must be large enough to hold * screen image (see makeTextureForScreen()). * * @param txtrHandle texture where screen image will be stored * @see frameDraw() * @see makeTextureForScreen() */ public void frameSave(int txtrHandle) { GL11.glColor4f(1,1,1,1); // turn off alpha and color tints GL11.glReadBuffer(GL11.GL_BACK); GL11.glBindTexture(GL11.GL_TEXTURE_2D,txtrHandle); // Copy screen to texture GL11.glCopyTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0,0, 0,0, displayMode.getWidth(),displayMode.getHeight()); //!!! whole frame } /** * Draw the screen-sized image over entire screen area. The screen image * is stored in the given texture at 0,0 (see frameSave()) and has the * same dimensions as the current display mode (DM.getWidth(), DM.getHeight()). *
* Reset the viewport and ortho mode to full screen (viewport may be * different proportion than screen if custom aspectRatio is set). Draw the * quad the same size as texture so no stretching or compression of image. * * @param txtrHandle */ public void frameDraw(int txtrHandle) { // keep it opaque, be sure texturing is enabled GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_TEXTURE_2D); // set viewport to full screen (need to handle custom shaped viewport) //GL11.glViewport(0, 0,displayMode.getWidth(), displayMode.getHeight()); // set ortho view to full screen and draw quad GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPushMatrix(); // preserve current projection { GL11.glLoadIdentity(); // clear the projection matrix GL11.glOrtho(0, displayMode.getWidth(), 0, displayMode.getHeight(), -1, 1); // turn on 2D mode full screen GL11.glColor4f(1,1,1,1); drawQuad(txtrHandle, 0, 0, screenTextureSize, screenTextureSize); // draw the full screen image } GL11.glPopMatrix(); // restore projection view // put these settings back on GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); } /** * Draw arbitrary sized quad at given xy coords, Apple the given texture. */ public static void drawQuad(int textureHandle, int x, int y, float w, float h) { GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle); // draw textured quad GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0f, 0f); GL11.glVertex3f( (float)x, (float)y, (float)0); GL11.glTexCoord2f(1f, 0f); GL11.glVertex3f( (float)x+w, (float)y, (float)0); GL11.glTexCoord2f(1f, 1f); GL11.glVertex3f( (float)x+w, (float)y+h, (float)0); GL11.glTexCoord2f(0f, 1f); GL11.glVertex3f( (float)x, (float)y+h, (float)0); GL11.glEnd(); } }