Computer Graphics (CMSC 427) - Spring 2000

                                                Prof. Ben Bederson

                                                Homework Six: OpenGL and Magician

                                                Due: Tuesday, Mar 14th, 2000

   

The purpose of this assignment is for you to become familiar with OpenGL and Magican.  Your real task is to read the Magician and OpenGL documentation (see the links page), and to play around with the API, trying things out.  To demonstrate that you have gotten it working, you must write a simple solar system simulation as described below.

First of all, you must get Magician installed and running properly.  There is a sample program at the end of this assignment that you can use to test Magician, and as a starting point for your assignment.  There are two things that must be installed to get this code to work properly: OpenGL and Magician.  OpenGL is freely available from SGI and you can download and install it on your PC (see the links page).  I am actively working on getting WAM to install it in the CS WAM lab, and hopefully it will be installed very soon.  If it is not, I will delay the due date on this assignment. 

Magician is installed in my account on WAM, and you can access it from T:\wam.umd.edu\home\wam\b\e\bederson\magician. In order for Magician to run properly, you must set your PATH variable to <magician>\lib, and the CLASSPATH variable to <magician>\classes.  If you are running Java from the command line, you can set the PATH variable with 'set PATH=%PATH%;<new pathname>', and the CLASSPATH variable similarly.  You can set the classpath within Visual J++ through the Project/... Properties menu on the 'classpath' tab.  To run Visual J++, you must set the PATH variable through autoexec.bat (for Win98) or the Systems control panel (for Win NT).  Because you do not have access to the control panels in the WAM lab, you must run your programs from the command line (sorry).  You can use 'jview /cp ".;T:\wam.umd.edu\home\wam\b\e\bederson\magician\classes" yourApp'

Your solar system simulation must:


/**
 * Sample OpenGL program using Magician in Java.
 * It draws a rotating square and sphere.
 *
 * @author Benjamin B. Bederson
 * @date March 6, 2000
 */
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.hermetica.magician.*;

public class testGL extends Frame implements GLEventListener, KeyListener, WindowListener {
				// The initial dimensions of the window
    static private int WIDTH = 400;
    static private int HEIGHT = 400;

				// The OpenGL state machine 
    GL gl = null;
    CoreGL coreGL = new CoreGL();
    GLU glu = new CoreGLU();

				// The OpenGL-aware Component we are rendering into 
    GLComponent glc = null;

				// Internal model of scene
    float angle = 0.0f;		// The current rotation angle of the scene

    public static void main(String argv[]) {
        testGL d = new testGL();
        d.setTitle("Simple OpenGL Test");
        d.startDemo();
    }

    public testGL() {
        gl = coreGL;
    }

    public void startDemo() {
        setLayout(new BorderLayout());

				// Create the OpenGL Component
        glc = (GLComponent)GLDrawableFactory.createGLComponent(WIDTH, HEIGHT);
        add("Center", glc);
        pack();
	show();

				// Setup the context capabilities
	GLCapabilities cap = glc.getContext().getCapabilities();
	cap.setDoubleBuffered(GLCapabilities.DOUBLEBUFFER);

        glc.addKeyListener(this);      // Add the key listener to the component
        this.addWindowListener(this);  // Add the window listener
        glc.addGLEventListener(this);  // Add the listener and initialize the component
        glc.initialize();
	glc.start();		// Start a simple animation which results in the display
				// method being called over and over again.
    }

    /** 
     * Gets called exactly once when GLComponent.initialize() is invoked 
     */
    public void initialize(GLDrawable component) {
				// Set the clear colour for the framebuffer
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

				// Enable lighting
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_LIGHT0);
        gl.glEnable(GL.GL_COLOR_MATERIAL);
    }

    /** 
     * Handles viewport resizing 
     */
    public void reshape(GLDrawable component, int x, int y, int width, int height) {
        gl.glViewport(component, x, y, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
	gl.glOrtho(-100f, 100f, -100f, 100f, 0.1f, 200.0f);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

				// Add a simple light at (100, 100, 100);
        float[] lightPosition = {100.0f, 100.0f, 100.0f, 0.0f};
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition);
    }

    /** 
     * Renders the scene 
     */
    public void display(GLDrawable component) {
				// Clear the framebuffer
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);

        gl.glLoadIdentity();    // Start in GCS

				// Push everything a bit away from the camera
	gl.glTranslate(0f, 0f, -100f);
				// Rotate everything around the Y axis
	gl.glRotatef(angle, 0f, 1f, 0f);

				// Draw a rectangle
	gl.glColor3f(0.0f, 0.0f, 1.0f);
	gl.glBegin(GL.GL_POLYGON);
	gl.glVertex3f(0f, 0f, 0.0f);
	gl.glVertex3f(0f, 50f, 0.0f);
	gl.glVertex3f(50f, 50f, 0.0f);
	gl.glVertex3f(50f, 0f, 0.0f);
	gl.glEnd();

				// Draw a sphere
	gl.glTranslatef(50f, 50f, 0f);
	GLUQuadric quadric = glu.gluNewQuadric();
	glu.gluSphere(quadric, 10, 16, 16);

	angle += 1f;
    }

    public GL getGL() {
        return coreGL;
    }

    /*****************************************************
     * Utilities
     *****************************************************/

    /**
     * Dump the capabilities of the current OpenGL system
     * to stdout.
     */
    static public void dumpCapabilities() {
	GLCapabilities[] caps = GLCapabilities.enumerateCapabilities();
	for (int i=0; i<caps.length; i++) {
	    System.out.println("Capabilities[" + i + "]: ");
	    System.out.println(caps[i].toString() + "\n");
	}
    }

    /*****************************************************
     * KeyListener Interface implementation
     *****************************************************/

    /** 
     * Handles key pressed event 
     */
    public void keyPressed(KeyEvent evt) {
        if (evt.getKeyChar() == KeyEvent.VK_ESCAPE) {
				// Destroy the GLContext
            glc.destroy();
            dispose();
	    System.exit(0);
	}
    }

    /** 
     * Handles key typed events 
     */
    public void keyTyped(KeyEvent evt) {
    }

    /** 
     * Handles key released events 
     */
    public void keyReleased(KeyEvent evt) {
    }

    /*****************************************************
     * WindowListener Interface implementation
     *****************************************************/

    public void windowClosing(WindowEvent evt) {
        glc.destroy();
        dispose();
	System.exit(0);
    }

    public void windowDeiconified(WindowEvent evt) {
        if (glc.isRunning()) {
            glc.resume();
	}
    }

    public void windowIconified(WindowEvent evt) {
        if (glc.isRunning()) {
            glc.suspend();
	}
    }

    public void windowActivated(WindowEvent evt) {
    }

    public void windowClosed(WindowEvent evt) {
    }

    public void windowDeactivated(WindowEvent evt) {
    }

    public void windowOpened(WindowEvent evt) {
    }
}