2008年3月20日 星期四

JOGL - Java與OpenGl(三)

一個好用的程式樣板

讓我們繼續來看兩個class,當你對JOGL感到有點頭昏腦脹時,你也許會發現這個程式樣板相當好用。我已經不止一次把它們當成樣板用了。你可以隨意地使用它們。

這個樣板由兩個class組成。第一個是如下所示的SimpleJoglApp,在簡短說明之後,第二個是SimpleGLEventListener。你必須建立兩個class來編譯樣板。主程式如下:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.media.opengl.*;

/**
* This is a basic JOGL app. 
* Feel free to reuse this code or modify it.
* 這是個基本的JOGL程式,你可以隨意重用或修改它。
*/
public class SimpleJoglApp extends JFrame {
    public static void main(String[] args) {
        final SimpleJoglApp app = new SimpleJoglApp();

        // show what we've done
        // 看一下我們做了什麼
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                app.setVisible(true);
            }
        });
    }

    public SimpleJoglApp() {
        // set the JFrame title
        // 設置JFrame標題
        super("Simple JOGL Application");

        // kill the process when the JFrame is closed
        // 當JFrame關閉的時候,結束程式
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // only three JOGL lines of code ... and here they are
        // 只有三行JOGL code ... 如下
        GLCapabilities glcaps = new GLCapabilities();
        GLCanvas glcanvas = new GLCanvas(glcaps);
        glcanvas.addGLEventListener(new SimpleGLEventListener());

        // add the GLCanvas just like we would any Component
        // 像其它組件一樣把GLCanvas加入
        getContentPane().add(glcanvas, BorderLayout.CENTER);
        setSize(500, 300);

        // center the JFrame on the screen
        // 使JFrame顯示在螢幕中央
        centerWindow(this);
    }

    public void centerWindow(Component frame) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = frame.getSize();

        if (frameSize.width > screenSize.width)
            frameSize.width = screenSize.width;
        if (frameSize.height > screenSize.height)
            frameSize.height = screenSize.height;

        frame.setLocation((screenSize.width - frameSize.width) >> 1,
        (screenSize.height - frameSize.height) >> 1);
    }
}



code就是這些。讓我們把注意力集中在第一個class中與JOGL相關的三行code上。首先:
這決定了我們的JOGL Library和JVM可以使用哪些OpenGL/圖形特性。

接著:

GLCanvas glcanvas = new GLCanvas(glcaps);

我們創建了可以在上面畫畫的GLCanvas。如果我們不想用AWT,改用Swing,則可以 new GLJPanel()。
注意我們把先前創建的GLCapabilities物件傳了進去,這使我們的GLDrawable(這裡指GLCanvas)適當建立。

最後,我們準備在GLCanvas上加入GLEventListener。

我們實現GLEventListener介面的class是SimpleGLEventListener。當它收到GLDrawable或 GLCanvas的呼叫時,它會注意所需要完成的繪圖工作。如你所見,我不打算在這個程式裡畫東西。下面是GLEventListener的code:

import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;

/**
 * For our purposes only two of the GLEventListeners matter. 
 * Those would be init() and display(). 
 * 為了達到我們的目的,GLEventListener中只有兩個方法有用。
 * 它們是init()和display()。
 */
public class SimpleGLEventListener implements GLEventListener {

    /**
     * Take care of initialization here. 注意這兒,我們初始化的地方。
     */
    public void init(GLAutoDrawable drawable) {
    }

    /**
     * Take care of drawing here. 
     * 注意這兒,繪圖的地方。
     */
    public void display(GLAutoDrawable drawable) {
    }

    /**
     * Called when the GLDrawable (GLCanvas or GLJPanel) has changed in size. 
     * We won't need this, but you may eventually need it -- just not yet.
     * 當GLDrawable(GLCanvas或GLJPanel)大小改變時被呼叫。 
     * 我們不需要它,但你可能最後會用到 — 雖然現在並不需要。
     */
    public void reshape(GLAutoDrawable drawable, int x, int y, 
    int width, int height) {
    }

    /**
     * If the display depth is changed while the program is running this method
     * is called. Nowadays this doesn't happen much, unless a programmer has his
     * program do it. 
     * 當程序運行中顯示設定被改變時,會調用此方法。 
     * 現在這種事發生得不多,除非我們在程式裡面刻意觸發此事。
     */
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }
}



以上就是我們要完成的JOGL核心工作。注意下面的UML圖。SimpleJoglApp是一個JFrame。它包含了GLDrawable,實際上是一個GLCanvas(但別那樣叫它)。我們加入了 SimpleGLEventListener。SimpleGLEventListener實現了相對於GLCanvas的 GLEventListener介面,這樣當它想執行任何的OpenGL工作時,GLCanvas就可以知道。GLDrawables能自動執行,所以你確實得使你的GLEventListener最優化。



這個程式跑起來可能會根據你的作業系統而顯得有點亂七八糟。這是預料中事,因為你在這裡只是在銀幕顯示隨機的內容。所以恭喜你,現在具備基本了繪圖能力了。