Jogl

Rotation and texturing

Works with:
FF3
Chrome
IE6
IE7
Opera
Safari

Description

This demonstrates basic setup and use of 3d graphics in a Java Applet using Opengl.

Demo

Java (Main Program Code)

  1. import java.awt.*;
  2. import java.awt.image.*;
  3. import java.awt.event.*;
  4.  
  5. import javax.swing.*;
  6. import javax.swing.border.*;
  7.  
  8. import java.net.*;
  9. import java.io.*;
  10. import java.nio.*;
  11. import javax.imageio.*;
  12.  
  13. import javax.media.opengl.*;
  14. import javax.media.opengl.glu.*;
  15. import com.sun.opengl.util.*;
  16.  
  17. /**
  18. * Main Program class
  19. * Setup window and opengl context for opengl code
  20. * Uses opengl and jogl bindings
  21. * Covers NeHe tutorials 6,7
  22. * @author Andrew Lowndes
  23. * @date 09/08/08
  24. */
  25. public class MainProgram extends GLCanvas implements GLEventListener, KeyListener {
  26.     //window properties
  27.     private GL gl;
  28.  
  29.     //object manipulation
  30.     private float rotSquareX = 0.0f;
  31.     private float rotSquareY = 0.0f;
  32.     private float rotSquareXSpeed = 2.0f;
  33.     private float rotSquareYSpeed = 2.0f;
  34.     private float posSquareZ = -5.0f;
  35.    
  36.     //texturing
  37.     private int numTextures = 3;
  38.     private BufferedImage texture;
  39.     private int[] texturesData;
  40.     private int filter = 0;
  41.    
  42.     //lighting
  43.     private float[] lightAmbient = { 0.5f, 0.5f, 0.5f, 1.0f};
  44.     private float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
  45.     private float[] lightPosition = { 0.0f, 0.0f, 2.0f, 1.0f};
  46.    
  47.     /**
  48.     * Constructor
  49.     */
  50.     public MainProgram(Image textureImage) {
  51.         //setup this panel
  52.         super(new GLCapabilities());
  53.         addGLEventListener(this);
  54.    
  55.         //convert the image to a buffered image
  56.         BufferedImage textureBufferedImage = new BufferedImage(textureImage.getWidth(null),textureImage.getHeight(null),BufferedImage.TYPE_INT_RGB);
  57.         Graphics textureGraphics = textureBufferedImage.getGraphics();
  58.         textureGraphics.drawImage(textureImage, 0, 0, null);
  59.         textureGraphics.dispose();
  60.         this.texture = textureBufferedImage;
  61.     }
  62.    
  63.    
  64.     /*
  65.     * Main Function
  66.     * Create the window and opengl context and start the animator
  67.     */
  68.     public static void main(String[] args) {
  69.         //setup the look and feel
  70.         try {
  71.             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  72.         } catch(Exception e) {
  73.         }
  74.    
  75.         //make the stand alone window
  76.         JFrame ourWindow = new JFrame();
  77.    
  78.         //setup the window
  79.         ourWindow.setTitle("Opengl lessons");
  80.         ourWindow.setSize(400,300);
  81.         ourWindow.setLocation(100,100);
  82.         ourWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  83.         ourWindow.setFocusable(true);
  84.         ourWindow.setBackground(Color.BLACK);
  85.        
  86.         //load the textures image
  87.         Image raw_texture = new ImageIcon(MainProgram.class.getResource("textures.png")).getImage();
  88.  
  89.         //setup the opengl container
  90.         MainProgram graphicsWindow = new MainProgram(raw_texture);
  91.         graphicsWindow.setFocusable(true);
  92.        
  93.         //put everything together
  94.         ourWindow.getContentPane().setBackground(Color.BLACK);
  95.         ourWindow.getContentPane().setLayout(new BorderLayout());
  96.         ourWindow.getContentPane().add(graphicsWindow);
  97.        
  98.         //setup the animator
  99.         final FPSAnimator programAnimControl = new FPSAnimator(graphicsWindow,60);
  100.         ourWindow.addWindowListener(new WindowAdapter() {
  101.             public void windowClosing(WindowEvent e) {
  102.               new Thread(new Runnable() {
  103.                   public void run() {
  104.                     programAnimControl.stop();
  105.                   }
  106.                 }).start();
  107.             }
  108.         });
  109.        
  110.         //display our window now
  111.         ourWindow.setVisible(true);
  112.        
  113.         programAnimControl.start();
  114.     }
  115.    
  116.     //key events
  117.     public void keyTyped(KeyEvent e) { }
  118.     public void keyReleased(KeyEvent e) { }
  119.    
  120.     public void keyPressed(KeyEvent e) {
  121.         switch (e.getKeyCode()) {
  122.             //if the esc key is pressed, kill the window
  123.             case KeyEvent.VK_ESCAPE:
  124.                 System.exit(0);
  125.                 break;         
  126.             //toggle the filter being used
  127.             case KeyEvent.VK_F:
  128.                 filter++;
  129.                 if (filter>2) filter=0;
  130.                
  131.                 break;
  132.             //move the object further away if page up is pressed
  133.             case KeyEvent.VK_PAGE_UP:
  134.                 posSquareZ-=0.02f;
  135.                
  136.                 break;
  137.             //move the object closer if page down is pressed
  138.             case KeyEvent.VK_PAGE_DOWN:
  139.                 posSquareZ+=0.02f;
  140.            
  141.                 break;
  142.             //increase the speed vertically if up is pressed
  143.             case KeyEvent.VK_UP:
  144.                 rotSquareXSpeed-=0.01f;
  145.                
  146.                 break;
  147.             //decrease the speed vertically if down is pressed
  148.             case KeyEvent.VK_DOWN:
  149.                 rotSquareXSpeed+=0.01f;
  150.                
  151.                 break;
  152.             //increase the speed horizontally if up is pressed
  153.             case KeyEvent.VK_RIGHT:
  154.                 rotSquareYSpeed+=0.01f;
  155.                
  156.                 break;
  157.             //decrease the speed horizontally if down is pressed
  158.             case KeyEvent.VK_LEFT:
  159.                 rotSquareYSpeed-=0.01f;
  160.                
  161.                 break;
  162.             default:
  163.                 break;
  164.         }
  165.     }
  166.    
  167.     /**
  168.     * Convert an image into a suitable texture form
  169.     * @param texture image
  170.     * @param has alpha channel
  171.     * @return texture as byte buffer
  172.     */
  173.     private ByteBuffer convertImageToTexture(BufferedImage img, boolean storeAlphaChannel) {
  174.         int[] packedPixels = new int[img.getWidth() * img.getHeight()];
  175.  
  176.         PixelGrabber pixelgrabber = new PixelGrabber(img, 0, 0, img.getWidth(), img.getHeight(), packedPixels, 0, img.getWidth());
  177.         try {
  178.             pixelgrabber.grabPixels();
  179.         } catch (InterruptedException e) {
  180.             throw new RuntimeException();
  181.         }
  182.  
  183.         int bytesPerPixel = storeAlphaChannel ? 4 : 3;
  184.         ByteBuffer unpackedPixels = BufferUtil.newByteBuffer(packedPixels.length * bytesPerPixel);
  185.  
  186.         for (int row = img.getHeight() - 1; row >= 0; row--) {
  187.             for (int col = 0; col < img.getWidth(); col++) {
  188.                 int packedPixel = packedPixels[row * img.getWidth() + col];
  189.                 unpackedPixels.put((byte) ((packedPixel >> 16) & 0xFF));
  190.                 unpackedPixels.put((byte) ((packedPixel >> 8) & 0xFF));
  191.                 unpackedPixels.put((byte) ((packedPixel >> 0) & 0xFF));
  192.                 if (storeAlphaChannel) {
  193.                     unpackedPixels.put((byte) ((packedPixel >> 24) & 0xFF));
  194.                 }
  195.             }
  196.         }
  197.  
  198.         unpackedPixels.flip();
  199.        
  200.         return unpackedPixels;
  201.     }
  202.    
  203.     /**
  204.     * Every frame, render our polygons, colour and rotate them
  205.     */
  206.     public void display(GLAutoDrawable glComponent) {
  207.         gl = glComponent.getGL();
  208.        
  209.         gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); //clear the colour and depth buffers
  210.        
  211.         //positioning the square
  212.         gl.glLoadIdentity();
  213.         gl.glTranslatef( 0f, 0.0f,posSquareZ); //center of square
  214.        
  215.         gl.glRotatef(rotSquareX, 1.0f, 0.0f, 0.0f); //rot on x axis
  216.         gl.glRotatef(rotSquareY, 0.0f, 1.0f, 0.0f); //rot on y axis
  217.        
  218.         //bind the texture
  219.         gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[filter]);
  220.        
  221.         //draw our square
  222.         gl.glBegin(gl.GL_QUADS);
  223.             // Front Face
  224.             gl.glNormal3f( 0.0f, 0.0f, 1.0f);                                   // Normal Pointing Towards Viewer
  225.             gl.glTexCoord2f(0.0000f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
  226.             gl.glTexCoord2f(0.1666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
  227.             gl.glTexCoord2f(0.1666f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f); // Top Right Of The Texture and Quad
  228.             gl.glTexCoord2f(0.0000f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f); // Top Left Of The Texture and Quad
  229.            
  230.             // Back Face
  231.             gl.glNormal3f( 0.0f, 0.0f,-1.0f);                                   // Normal Pointing Away From Viewer
  232.             gl.glTexCoord2f(0.3333f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
  233.             gl.glTexCoord2f(0.3333f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
  234.             gl.glTexCoord2f(0.1666f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
  235.             gl.glTexCoord2f(0.1666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
  236.            
  237.             // Top Face
  238.             gl.glNormal3f( 0.0f, 1.0f, 0.0f);                                   // Normal Pointing Up
  239.             gl.glTexCoord2f(0.3333f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
  240.             gl.glTexCoord2f(0.3333f, 0.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f); // Bottom Left Of The Texture and Quad
  241.             gl.glTexCoord2f(0.4999f, 0.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f); // Bottom Right Of The Texture and Quad
  242.             gl.glTexCoord2f(0.4999f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
  243.            
  244.             // Bottom Face
  245.             gl.glNormal3f( 0.0f,-1.0f, 0.0f);                                   // Normal Pointing Down
  246.             gl.glTexCoord2f(0.6666f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
  247.             gl.glTexCoord2f(0.4999f, 1.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
  248.             gl.glTexCoord2f(0.4999f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
  249.             gl.glTexCoord2f(0.6666f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
  250.            
  251.             // Right face
  252.             gl.glNormal3f( 1.0f, 0.0f, 0.0f);                                   // Normal Pointing Right
  253.             gl.glTexCoord2f(0.8222f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
  254.             gl.glTexCoord2f(0.8222f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
  255.             gl.glTexCoord2f(0.6666f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f); // Top Left Of The Texture and Quad
  256.             gl.glTexCoord2f(0.6666f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
  257.            
  258.             // Left Face
  259.             gl.glNormal3f(-1.0f, 0.0f, 0.0f);                                   // Normal Pointing Left
  260.             gl.glTexCoord2f(0.8333f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
  261.             gl.glTexCoord2f(1.0000f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
  262.             gl.glTexCoord2f(1.0000f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f); // Top Right Of The Texture and Quad
  263.             gl.glTexCoord2f(0.8333f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
  264.         gl.glEnd();
  265.        
  266.         rotSquareX += rotSquareXSpeed;
  267.         rotSquareY += rotSquareYSpeed;
  268.     }
  269.    
  270.     /**
  271.     * Do nothing
  272.     */
  273.     public void displayChanged(GLAutoDrawable glComponent, boolean modeChanged, boolean deviceChanged) {
  274.     }
  275.    
  276.     /**
  277.     * Setup how our opengl will render our shapes
  278.     */
  279.     public void init(GLAutoDrawable glComponent) {
  280.         gl = glComponent.getGL();
  281.        
  282.         gl.glShadeModel(gl.GL_SMOOTH); //enable smooth shading
  283.        
  284.         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //clear to black
  285.         gl.glClearDepth(1.0f); //clear the depth buffer too
  286.        
  287.         //used for depth test of 3d objects
  288.         gl.glEnable(gl.GL_DEPTH_TEST);
  289.         gl.glDepthFunc(gl.GL_LEQUAL);
  290.        
  291.         gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST); //make our perspective look nice
  292.    
  293.         //enable texturing
  294.         gl.glEnable(gl.GL_TEXTURE_2D);
  295.  
  296.         //free textures space in opengl
  297.         texturesData = new int[numTextures];
  298.         gl.glGenTextures(numTextures, texturesData, 0);
  299.        
  300.         //generate textures from the texture images data
  301.         ByteBuffer textureBytes = convertImageToTexture(texture, false);
  302.        
  303.         gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[0]);
  304.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST);
  305.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST);
  306.         gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, texture.getWidth(), texture.getHeight(), 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
  307.        
  308.         gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[1]);
  309.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
  310.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
  311.         gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, texture.getWidth(), texture.getHeight(), 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
  312.        
  313.         gl.glBindTexture(gl.GL_TEXTURE_2D, texturesData[2]);
  314.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_NEAREST);
  315.         gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
  316.         new GLU().gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGB, texture.getWidth(), texture.getHeight(), gl.GL_RGB, gl.GL_UNSIGNED_BYTE, textureBytes);
  317.        
  318.         //remove the loaded texture
  319.         //texture = null;
  320.        
  321.         //sort out the lighting
  322.         gl.glLightfv(gl.GL_LIGHT1, gl.GL_AMBIENT, lightAmbient,0);
  323.         gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, lightDiffuse,0);
  324.         gl.glLightfv(gl.GL_LIGHT1, gl.GL_POSITION, lightPosition,0);
  325.        
  326.         gl.glEnable(gl.GL_LIGHT1);
  327.         gl.glEnable(gl.GL_LIGHTING);
  328.        
  329.         //assign the key/muose handlers
  330.         glComponent.addKeyListener(this);
  331.     }
  332.    
  333.     /**
  334.     * On resize, keep our perspective and render our objects
  335.     */
  336.     public void reshape(GLAutoDrawable glComponent, int x, int y, int width, int height) {
  337.         gl = glComponent.getGL();
  338.         GLU glu = new GLU();
  339.        
  340.         if (height==0) height=1; //make sure we dont divide by 0
  341.        
  342.         gl.glViewport(0,0, width, height); //set the viewport matrix parameters
  343.        
  344.         //change our projection matrix to relate to the new aspect ratio
  345.         gl.glMatrixMode(gl.GL_PROJECTION);
  346.         gl.glLoadIdentity();
  347.        
  348.         glu.gluPerspective(45.0f, (float)width/(float)height, 0.1f, 100.0f);
  349.        
  350.         gl.glMatrixMode(gl.GL_MODELVIEW);
  351.         gl.glLoadIdentity();
  352.     }
  353. }

Java (Applet Code)

  1. import java.applet.*;
  2. import java.awt.*;
  3.  
  4. import javax.media.opengl.*;
  5. import com.sun.opengl.util.*;
  6.  
  7. /**
  8. * Main Program Applet Class
  9. * Sets up an applet for us with opengl event class
  10. * @author Andrew Lowndes
  11. * @date 09/08/08
  12. */
  13. public class MainProgramApplet extends Applet {
  14.     FPSAnimator programAnimControl;
  15.    
  16.     /**
  17.     * On applet load, create our opengl context and add it to
  18.     * our applet
  19.     */
  20.     public void init() {
  21.         //load the texture
  22.         MediaTracker textureTracker = new MediaTracker(this);
  23.        
  24.         Image texture = getImage(getCodeBase(), "textures.png");
  25.         textureTracker.addImage(texture, 1);
  26.        
  27.         try {
  28.             textureTracker.waitForAll();
  29.         } catch (Exception e) { }
  30.        
  31.         //setup the opengl container
  32.         MainProgram graphicsWindow = new MainProgram(texture);
  33.         graphicsWindow.setFocusable(true);
  34.        
  35.         //put everything together
  36.         setBackground(Color.BLACK);
  37.         setLayout(new BorderLayout());
  38.         add(graphicsWindow);
  39.        
  40.         //setup the animator
  41.         programAnimControl = new FPSAnimator(graphicsWindow,60);
  42.     }
  43.    
  44.     /**
  45.     * Start the animator when the applet is started
  46.     */
  47.     public void start() {
  48.         programAnimControl.start();
  49.     }
  50.    
  51.     /**
  52.     * Stop the animator when the applet is stopped
  53.     */
  54.     public void stop() {
  55.         programAnimControl.stop();
  56.     }
  57. }