import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import org.lwjgl.opengl.*;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.opengl.glu.Sphere;
import org.lwjgl.input.Keyboard;
public class FryEgg {
private boolean done = false;
private final String windowTitle = "Fry a Digital Egg";
private DisplayMode displayMode;
float rotation = 0f;
float camx = -.5f, camy=-2.7f, camz=18, keyDelta = 0.3f;
private float cameraRotation = 12.6f;
private float cameraDistance = 16.7f;
// Spheres
Sphere sphere, lightSphere;
// color of overall scene lighting
float ambient[] = { .65f, .65f, .65f, 1f };
// color of light source
float lightDiffuse[] = { .9f, .9f, .9f, 1f }; // direct light (yellowish)
float lightSpecular[] = { .8f, .8f, .8f, 1f }; // highlight (yellowish)
float lightAmbient[] ={.4f,.4f,.4f,1};// { .2f, .2f, 1f, 1f }; // scattered light (yellowish)
// light position: if last value is 0, then this describes light direction.
// If 1, then light position.
float lightPosition[] = { -2f, 2f, 8, 1f };
// Material for planet
GLMaterial yolkMaterial = new GLMaterial();
float mtlDiffuse[] = { .99f, .99f, .2f, 1f };
float mtlAmbient[] = { .85f, .85f, .2f, 1f };
float mtlSpecular[] = { .5f, .5f, .5f, 1f };
float mtlShininess = 40f;
GLMaterial eggWhiteMaterial = new GLMaterial();
float[] eggd = {1,1,1,1};
float[] egga = {1,1,1,1};
float[] eggs = {1,1,1,1};
float eggShine = 4;
// Material, glowing (for "light")
GLMaterial materialE = new GLMaterial();
float mtlEmissive[] = { 1f, 1f, .1f, 1f }; // yellow/white
/**
* Main function just creates and runs the application.
*/
public static void main(String args[]) {
FryEgg app = new FryEgg();
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();
initShapes();
rotateCamera();
}
/**
* Create an OpenGL display, in this case a fullscreen window.
*
* @throws Exception
*/
private void initDisplay() throws Exception {
// 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;
}
}
// set the display to the resolution we picked
Display.setDisplayMode(displayMode);
Display.setFullscreen(false);
Display.setTitle(windowTitle);
// create the window
Display.create();
}
/**
* Initialize OpenGL
*
*/
private void initGL() {
// 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
// Select The Modelview Matrix (controls model orientation)
GL11.glMatrixMode(GL11.GL_MODELVIEW);
// turn depth testing on
GL11.glEnable(GL11.GL_DEPTH_TEST);
// OpenGL won't draw backward facing triangles ("back faces")
GL11.glEnable(GL11.GL_CULL_FACE);
// turn lighting on (does not create a light)
GL11.glEnable(GL11.GL_LIGHTING);
// Tell OpenGL to force all normal lengths to 1,
// so light illuminates all surfaces evenly
GL11.glEnable(GL11.GL_NORMALIZE);
// Create a light
// diffuse is the color of direct light from this light source
// ambient is the color of reflected light from this source
// position is where the light is, or it's direction
setLight(GL11.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition);
// overall scene lighting
setAmbientLight(ambient);
// "planet" material settings
yolkMaterial.setSurfaceColorLit(mtlDiffuse);
yolkMaterial.setSurfaceColorShadow(mtlAmbient);
yolkMaterial.setReflectionColor(mtlSpecular);
yolkMaterial.setShininess(mtlShininess);
yolkMaterial.apply();
eggWhiteMaterial.setSurfaceColorLit(eggd);
eggWhiteMaterial.setSurfaceColorShadow(egga);
eggWhiteMaterial.setReflectionColor(eggs);
eggWhiteMaterial.setShininess(eggShine);
// make a glowing material for the "light"
materialE.setGlowColor(mtlEmissive);
}
private void initShapes() {
sphere = new Sphere();
lightSphere = new Sphere();
}
private void mainloop() {
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Escape is pressed
done = true;
}
if (Display.isCloseRequested()) { // Window is closed
done = true;
}
boolean r = false;
if (Keyboard.isKeyDown(Keyboard.KEY_R)) {
cameraDistance -= keyDelta;
r = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
cameraDistance += keyDelta;
r = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
cameraRotation -= 2*keyDelta;
r = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
cameraRotation += 2*keyDelta;
r = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
camy += keyDelta;
r = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
camy -= keyDelta;
r = true;
}
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
lightPosition[0] = 2;
} else {
lightPosition[0] = -2;
}
if(r) rotateCamera();
if (Display.isCloseRequested()) { // Window is closed
done = true;
}
// clear = !Keyboard.isKeyDown(Keyboard.KEY_SPACE);
}
private void rotateCamera() {
camx = cameraDistance * (float) Math.sin(Math.toRadians(cameraRotation));
camz = cameraDistance * (float) Math.cos(Math.toRadians(cameraRotation));
System.out.printf("%5.2f, %5.2f, %5.2f\nr: %f d:%f\n:",
camx, camy, camz, cameraRotation, cameraDistance);
render();
}
/**
* Render the scene.
*/
private void render() {
rotation += .05f;
// Clear screen and depth buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// Select The Modelview Matrix (controls model orientation)
GL11.glMatrixMode(GL11.GL_MODELVIEW);
// Reset the Modelview matrix
// this resets the coordinate system to center of screen
GL11.glLoadIdentity();
GLU.gluLookAt(
camx, camy, camz, // eye position
0f, 0f, 0f, // target to look at
0f, 1f, 0f); // which way is up
materialE.apply();
setLight(GL11.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition);
// materialE.apply();
yolkMaterial.apply();
GL11.glPushMatrix();
{
GL11.glScalef(3,3,3);
// GL11.glColor4f(1,1,1,0.1f);
sphere.draw(1, 48, 48);
}
GL11.glPopMatrix();
eggWhiteMaterial.apply();
GL11.glTranslatef(0, 0, 1f);
GL11.glScalef(.8f,.8f,.8f);
GL11.glColor4f(1,1,1,1);
GL11.glNormal3f(0, 0, 1);
drawQuads();
}
public void drawCube() {
GL11.glBegin(GL11.GL_QUADS);
// Front Face
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Right
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left
// Back Face
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Left
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left
// Top Face
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right
// Bottom Face
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Top Left
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right
// Right face
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Left
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left
// Left Face
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left
GL11.glEnd();
}
/**
* Draw a 1x1 quad, centered on the origin, facing toward +Z.
* Add a normal for lighting.
*/
public void drawQuad(float z) {
GL11.glBegin(GL11.GL_QUADS);
GL11.glNormal3f( 0.0f, 0.0f, 1.0f);
GL11.glVertex3f( -.5f, -.5f, z); // left bottom
GL11.glVertex3f( .5f, -.5f, z); // rite bottom
GL11.glVertex3f( .5f, .5f, z); // rite top
GL11.glVertex3f( -.5f, .5f, z); // left top
GL11.glEnd();
}
/**
* draw a ground plane using quads (100x100)
*
*/
public void drawQuads() {
for (int r=0; r < 50; r++) {
for (int c=0; c < 50; c++) {
GL11.glPushMatrix();
{
GL11.glTranslatef(r-25,c-25,0);
drawQuad((float)Math.random());
}
GL11.glPopMatrix();
}
}
}
private void cleanup() {
Display.destroy();
}
/**
* Simple way to setup a light. Uses same color for direct light (diffuse),
* reflected highlight (specular) and scattered light (ambient). Ambient
* color is darkened to 1/4 of the light color.
*
* @param GLLightHandle
* @param color
* @param position
*/
public static void setLight(int GLLightHandle, float[] color, float[] position) {
float[] ambientLight = { color[0] / 4f, color[1] / 4f, color[2] / 4f, color[3] / 4f };
FloatBuffer lightColor = allocFloats(color);
FloatBuffer ambientColor = allocFloats(ambientLight);
FloatBuffer ltPosition = allocFloats(position);
GL11.glLight(GLLightHandle, GL11.GL_DIFFUSE, lightColor); // color of
// the
// direct
// illumination
GL11.glLight(GLLightHandle, GL11.GL_SPECULAR, lightColor); // color of
// the
// highlight
// (same as
// direct
// light)
GL11.glLight(GLLightHandle, GL11.GL_AMBIENT, ambientColor); // color of
// the
// scattered
// light
// (darker)
GL11.glLight(GLLightHandle, GL11.GL_POSITION, ltPosition);
GL11.glEnable(GLLightHandle); // Enable the light (GL_LIGHT1 - 7)
}
/**
* Set the color of a 'positional' light (a light that has a specific
* position within the scene).
*
* Params:
* an OpenGL light number (GL11.GL_LIGHT1),
* 'Diffuse': color of direct light from this source,
* 'Ambient': color of scattered light from this source
* 'Specular': color of this light reflected off a surface,
* position.
*/
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_AMBIENT, ltAmbient); // color of
// the
// reflected
// light
GL11.glLight(GLLightHandle, GL11.GL_SPECULAR, ltSpecular); // color of
// the
// highlight
// (same as
// direct
// light)
GL11.glLight(GLLightHandle, GL11.GL_POSITION, ltPosition);
GL11.glEnable(GLLightHandle); // Enable the light (GL_LIGHT1 - 7)
// GL11.glLightf(GLLightHandle, GL11.GL_QUADRATIC_ATTENUATION, .005F);
// // how light beam drops off
}
/**
* Set the position of a light to the given xyz.
*/
public static void setLightPos(int GLLightHandle, float x, float y, float z) {
float[] position = new float[] { x, y, z, 1 };
GL11.glLight(GLLightHandle, GL11.GL_POSITION, allocFloats(position));
}
/**
* Set the color of the Global Ambient Light. Affects all objects in scene
* regardless of their placement.
*/
public static void setAmbientLight(float[] ambientLightColor) {
FloatBuffer ltAmbient = allocFloats(ambientLightColor);
GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, ltAmbient);
}
public static final int SIZE_FLOAT = 4;
public static FloatBuffer allocFloats(int howmany) {
return ByteBuffer.allocateDirect(howmany * SIZE_FLOAT).order(ByteOrder.nativeOrder())
.asFloatBuffer();
}
public static FloatBuffer allocFloats(float[] floatarray) {
FloatBuffer fb = ByteBuffer.allocateDirect(floatarray.length * SIZE_FLOAT).order(
ByteOrder.nativeOrder()).asFloatBuffer();
fb.put(floatarray).flip();
return fb;
}
}