Description
This demonstrates basic setup and use of 3d graphics in a Java Applet using Opengl.
Demo
Java (Main Program Code)
- import java.awt.*;
- import java.awt.image.*;
- import java.awt.event.*;
-
- import javax.swing.*;
- import javax.swing.border.*;
-
- import java.net.*;
- import java.io.*;
- import java.nio.*;
- import javax.imageio.*;
-
- import javax.media.opengl.*;
- import javax.media.opengl.glu.*;
- import com.sun.opengl.util.*;
-
- /**
- * Main Program class
- * Setup window and opengl context for opengl code
- * Uses opengl and jogl bindings
- * Covers NeHe tutorials 6,7
- * @author Andrew Lowndes
- * @date 09/08/08
- */
- public class MainProgram extends GLCanvas implements GLEventListener, KeyListener {
- //window properties
- private GL gl;
-
- //object manipulation
- private float rotSquareX = 0.0f;
- private float rotSquareY = 0.0f;
- private float rotSquareXSpeed = 2.0f;
- private float rotSquareYSpeed = 2.0f;
- private float posSquareZ = -5.0f;
-
- //texturing
- private int numTextures = 3;
- private BufferedImage texture;
- private int[] texturesData;
- private int filter = 0;
-
- //lighting
- private float[] lightAmbient = { 0.5f, 0.5f, 0.5f, 1.0f};
- private float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
- private float[] lightPosition = { 0.0f, 0.0f, 2.0f, 1.0f};
-
- /**
- * Constructor
- */
- public MainProgram(Image textureImage) {
- //setup this panel
- super(new GLCapabilities());
- addGLEventListener(this);
-
- //convert the image to a buffered image
- BufferedImage textureBufferedImage = new BufferedImage(textureImage.getWidth(null),textureImage.getHeight(null),BufferedImage.TYPE_INT_RGB);
- Graphics textureGraphics = textureBufferedImage.getGraphics();
- textureGraphics.drawImage(textureImage, 0, 0, null);
- textureGraphics.dispose();
- this.texture = textureBufferedImage;
- }
-
-
- /*
- * Main Function
- * Create the window and opengl context and start the animator
- */
- public static void main(String[] args) {
- //setup the look and feel
- try {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- } catch(Exception e) {
- }
-
- //make the stand alone window
- JFrame ourWindow = new JFrame();
-
- //setup the window
- ourWindow.setTitle("Opengl lessons");
- ourWindow.setSize(400,300);
- ourWindow.setLocation(100,100);
- ourWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- ourWindow.setFocusable(true);
- ourWindow.setBackground(Color.BLACK);
-
- //load the textures image
- Image raw_texture = new ImageIcon(MainProgram.class.getResource("textures.png")).getImage();
-
- //setup the opengl container
- MainProgram graphicsWindow = new MainProgram(raw_texture);
- graphicsWindow.setFocusable(true);
-
- //put everything together
- ourWindow.getContentPane().setBackground(Color.BLACK);
- ourWindow.getContentPane().setLayout(new BorderLayout());
- ourWindow.getContentPane().add(graphicsWindow);
-
- //setup the animator
- final FPSAnimator programAnimControl = new FPSAnimator(graphicsWindow,60);
- ourWindow.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- new Thread(new Runnable() {
- public void run() {
- programAnimControl.stop();
- }
- }).start();
- }
- });
-
- //display our window now
- ourWindow.setVisible(true);
-
- programAnimControl.start();
- }
-
- //key events
- public void keyTyped(KeyEvent e) { }
- public void keyReleased(KeyEvent e) { }
-
- public void keyPressed(KeyEvent e) {
- switch (e.getKeyCode()) {
- //if the esc key is pressed, kill the window
- case KeyEvent.VK_ESCAPE:
- System.exit(0);
- break;
- //toggle the filter being used
- case KeyEvent.VK_F:
- filter++;
- if (filter>2) filter=0;
-
- break;
- //move the object further away if page up is pressed
- case KeyEvent.VK_PAGE_UP:
- posSquareZ-=0.02f;
-
- break;
- //move the object closer if page down is pressed
- case KeyEvent.VK_PAGE_DOWN:
- posSquareZ+=0.02f;
-
- break;
- //increase the speed vertically if up is pressed
- case KeyEvent.VK_UP:
- rotSquareXSpeed-=0.01f;
-
- break;
- //decrease the speed vertically if down is pressed
- case KeyEvent.VK_DOWN:
- rotSquareXSpeed+=0.01f;
-
- break;
- //increase the speed horizontally if up is pressed
- case KeyEvent.VK_RIGHT:
- rotSquareYSpeed+=0.01f;
-
- break;
- //decrease the speed horizontally if down is pressed
- case KeyEvent.VK_LEFT:
- rotSquareYSpeed-=0.01f;
-
- break;
- default:
- break;
- }
- }
-
- /**
- * Convert an image into a suitable texture form
- * @param texture image
- * @param has alpha channel
- * @return texture as byte buffer
- */
- private ByteBuffer convertImageToTexture(BufferedImage img, boolean storeAlphaChannel) {
- int[] packedPixels = new int[img.getWidth() * img.getHeight()];
-
- PixelGrabber pixelgrabber = new PixelGrabber(img, 0, 0, img.getWidth(), img.getHeight(), packedPixels, 0, img.getWidth());
- try {
- pixelgrabber.grabPixels();
- } catch (InterruptedException e) {
- throw new RuntimeException();
- }
-
- int bytesPerPixel = storeAlphaChannel ? 4 : 3;
- ByteBuffer unpackedPixels = BufferUtil.newByteBuffer(packedPixels.length * bytesPerPixel);
-
- for (int row = img.getHeight() - 1; row >= 0; row--) {
- for (int col = 0; col < img.getWidth(); col++) {
- int packedPixel = packedPixels[row * img.getWidth() + col];
- unpackedPixels.put((byte) ((packedPixel >> 16) & 0xFF));
- unpackedPixels.put((byte) ((packedPixel >> 8) & 0xFF));
- unpackedPixels.put((byte) ((packedPixel >> 0) & 0xFF));
- if (storeAlphaChannel) {
- unpackedPixels.put((byte) ((packedPixel >> 24) & 0xFF));
- }
- }
- }
-
- unpackedPixels.flip();
-
- return unpackedPixels;
- }
-
- /**
- * Every frame, render our polygons, colour and rotate them
- */
- public void display(GLAutoDrawable glComponent) {
- gl = glComponent.getGL();
-
- gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); //clear the colour and depth buffers
-
- //positioning the square
- gl.glLoadIdentity();
- gl.glTranslatef( 0f, 0.0f,posSquareZ); //center of square
-
- gl.glRotatef(rotSquareX, 1.0f, 0.0f, 0.0f); //rot on x axis
- gl.glRotatef(rotSquareY, 0.0f, 1.0f, 0.0f); //rot on y axis
-
- //bind the texture
- gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[filter]);
-
- //draw our square
- gl.glBegin(gl.GL_QUADS);
- // Front Face
- gl.glNormal3f( 0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
- gl.glTexCoord2f(0.0000f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
- gl.glTexCoord2f(0.1666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
- gl.glTexCoord2f(0.1666f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
- gl.glTexCoord2f(0.0000f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
-
- // Back Face
- gl.glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer
- gl.glTexCoord2f(0.3333f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
- gl.glTexCoord2f(0.3333f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
- gl.glTexCoord2f(0.1666f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
- gl.glTexCoord2f(0.1666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
-
- // Top Face
- gl.glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up
- gl.glTexCoord2f(0.3333f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
- gl.glTexCoord2f(0.3333f, 0.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
- gl.glTexCoord2f(0.4999f, 0.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
- gl.glTexCoord2f(0.4999f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
-
- // Bottom Face
- gl.glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down
- gl.glTexCoord2f(0.6666f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
- gl.glTexCoord2f(0.4999f, 1.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
- gl.glTexCoord2f(0.4999f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
- gl.glTexCoord2f(0.6666f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
-
- // Right face
- gl.glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right
- gl.glTexCoord2f(0.8222f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
- gl.glTexCoord2f(0.8222f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
- gl.glTexCoord2f(0.6666f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
- gl.glTexCoord2f(0.6666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
-
- // Left Face
- gl.glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
- gl.glTexCoord2f(0.8333f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
- gl.glTexCoord2f(1.0000f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
- gl.glTexCoord2f(1.0000f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
- gl.glTexCoord2f(0.8333f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
- gl.glEnd();
-
- rotSquareX += rotSquareXSpeed;
- rotSquareY += rotSquareYSpeed;
- }
-
- /**
- * Do nothing
- */
- public void displayChanged(GLAutoDrawable glComponent, boolean modeChanged, boolean deviceChanged) {
- }
-
- /**
- * Setup how our opengl will render our shapes
- */
- public void init(GLAutoDrawable glComponent) {
- gl = glComponent.getGL();
-
- gl.glShadeModel(gl.GL_SMOOTH); //enable smooth shading
-
- gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //clear to black
- gl.glClearDepth(1.0f); //clear the depth buffer too
-
- //used for depth test of 3d objects
- gl.glEnable(gl.GL_DEPTH_TEST);
- gl.glDepthFunc(gl.GL_LEQUAL);
-
- gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST); //make our perspective look nice
-
- //enable texturing
- gl.glEnable(gl.GL_TEXTURE_2D);
-
- //free textures space in opengl
- texturesData = new int[numTextures];
- gl.glGenTextures(numTextures, texturesData, 0);
-
- //generate textures from the texture images data
- ByteBuffer textureBytes = convertImageToTexture(texture, false);
-
- gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[0]);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST);
- gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, texture.getWidth(), texture.getHeight(), 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
-
- gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[1]);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
- gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, texture.getWidth(), texture.getHeight(), 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
-
- gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[2]);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_NEAREST);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
- new GLU().gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGB, texture.getWidth(), texture.getHeight(), gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
-
- //remove the loaded texture
- //texture = null;
-
- //sort out the lighting
- gl.glLightfv(gl.GL_LIGHT1, gl.GL_AMBIENT, lightAmbient,0);
- gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, lightDiffuse,0);
- gl.glLightfv(gl.GL_LIGHT1, gl.GL_POSITION, lightPosition,0);
-
- gl.glEnable(gl.GL_LIGHT1);
- gl.glEnable(gl.GL_LIGHTING);
-
- //assign the key/muose handlers
- glComponent.addKeyListener(this);
- }
-
- /**
- * On resize, keep our perspective and render our objects
- */
- public void reshape(GLAutoDrawable glComponent, int x, int y, int width, int height) {
- gl = glComponent.getGL();
- GLU glu = new GLU();
-
- if (height==0) height=1; //make sure we dont divide by 0
-
- gl.glViewport(0,0, width, height); //set the viewport matrix parameters
-
- //change our projection matrix to relate to the new aspect ratio
- gl.glMatrixMode(gl.GL_PROJECTION);
- gl.glLoadIdentity();
-
- glu.gluPerspective(45.0f, (float)width/(float)height, 0.1f, 100.0f);
-
- gl.glMatrixMode(gl.GL_MODELVIEW);
- gl.glLoadIdentity();
- }
- }
Java (Applet Code)
- import java.applet.*;
- import java.awt.*;
-
- import javax.media.opengl.*;
- import com.sun.opengl.util.*;
-
- /**
- * Main Program Applet Class
- * Sets up an applet for us with opengl event class
- * @author Andrew Lowndes
- * @date 09/08/08
- */
- public class MainProgramApplet extends Applet {
- FPSAnimator programAnimControl;
-
- /**
- * On applet load, create our opengl context and add it to
- * our applet
- */
- public void init() {
- //load the texture
- MediaTracker textureTracker = new MediaTracker(this);
-
- Image texture = getImage(getCodeBase(), "textures.png");
- textureTracker.addImage(texture, 1);
-
- try {
- textureTracker.waitForAll();
- } catch (Exception e) { }
-
- //setup the opengl container
- MainProgram graphicsWindow = new MainProgram(texture);
- graphicsWindow.setFocusable(true);
-
- //put everything together
- setBackground(Color.BLACK);
- setLayout(new BorderLayout());
- add(graphicsWindow);
-
- //setup the animator
- programAnimControl = new FPSAnimator(graphicsWindow,60);
- }
-
- /**
- * Start the animator when the applet is started
- */
- public void start() {
- programAnimControl.start();
- }
-
- /**
- * Stop the animator when the applet is stopped
- */
- public void stop() {
- programAnimControl.stop();
- }
- }