Sunday, March 07, 2010

3D繪圖的座標系統概念

在3D繪圖的世界裏,主要有兩種座標系統:

模型坐標系統(Model View)
視窗座標系統(Viewport)

那兩種座標系統要如何轉換呢?基本的轉換流程包含了:

切除(Clipping)。在模型坐標系統中切出可視範圍的空間,一般稱為View Volume。
投影(Projection)。將三維空間的View Volume投影至平面,一般會使用兩種投影法。一種是透視法投影(perspective),另一種是正射投影(Orthographic)。兩種投影法的差別圖示如下


透視法投影



正射投影

JOGL程式的基本架構


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package idv.sean;

import com.sun.opengl.util.FPSAnimator;
import com.sun.opengl.util.GLUT;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

/**
*
* @author sean
*/
public class OpenGLApp3 extends JFrame
implements GLEventListener, KeyListener {

static int year = 0, day = 0;
private KeyEvent key;
private GLCanvas canvas;
private GLCapabilities caps;
GLU glu = new GLU();
GLUT glut = new GLUT();
private FPSAnimator animator;

public OpenGLApp3() {
super("My Test");

caps = new GLCapabilities();
canvas = new GLCanvas(caps);
//canvas.setIgnoreRepaint( true );
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
animator = new FPSAnimator( canvas, 60 );
animator.setRunAsFastAsPossible(false);
getContentPane().add(canvas);
}

public void run() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(512, 512);
setLocationRelativeTo(null);
setVisible(true);
canvas.requestFocus();
animator.start();
}

public static void main(String[] args) {
new OpenGLApp3().run();
}

public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glShadeModel(GL.GL_FLAT);

}

public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();

gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glColor3f(1.0f, 1.0f, 1.0f);

gl.glPushMatrix();
glut.glutWireSphere(1.0, 20, 16); /* draw sun */
gl.glRotatef((float) year, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(2.0f, 0.0f, 0.0f);
gl.glRotatef((float) day, 0.0f, 1.0f, 0.0f);
glut.glutWireSphere(0.2, 10, 8); /* draw smaller planet */
gl.glPopMatrix();
drawable.swapBuffers();

}

public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int w, int h) {
GL gl = drawable.getGL();

gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(60.0, (float) w / (float) h, 1.0, 20.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}

public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
}

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent key) {
this.key = key;
System.out.println(key.getKeyCode());
switch (key.getKeyChar()) {

case 'd':
day = (day + 10) % 360;
break;
case 'D':
day = (day - 10) % 360;
break;
case 'y':
year = (year + 5) % 360;
break;
case 'Y':
year = (year - 5) % 360;
break;
default:
break;
}

canvas.display();
}

public void keyReleased(KeyEvent e) {
}
}


JOGL的核心在於GLEventListener與GLAutoDrawable這兩個介面。GLAutoDrawable這個介面有兩個實作,一個是GLCanvas,另一個是GLJPanel。前者是AWT的元件,後者是Swing的元件,當你將AWT與Swing元件混用的時候會有一些問題,但是GLCanvas會直接與OpenGL互動,所以效率比較好,之間的取捨就看需求。

GLEventListner則是JOGL繪圖的核心,包含了init、display、reshape、dispose四個函式。init只會被呼叫一次,負責繪圖環境的建置。display相當於java2d的paintComponent,負責實際的繪圖動作。reshape則是在GLAutoDrawable改變大小時進行視點、Viewport的變化。dispose則是GLAutoDrawable物件消失時,負責資源回收的工作。

Labels:

學習JOGL的網路資源

JOGL的公式網頁:
https://jogl.dev.java.net/
說實話,好像看不到什麼活動跡象XD
JOGL api資料:
http://download.java.net/media/jogl/jogl-2.x-docs/
基本上大部份的說明都是連結到對應的OpenGL api說明
OpenGL紅皮書:
http://www.glprogramming.com/red/index.html
這裏的說明能幫助你理解OpenGL基本的運作流程與概念
NeHe:
http://nehe.gamedev.net/
由淺入深的OpenGL範例與說明,Java版原始碼的下載位置
http://pepijn.fab4.be/software/nehe-java-ports/

把以上的文件與程式碼瀏覽過一篇,應該就大致能掌握JOGL的基本概念

Labels:

Thursday, March 04, 2010

JOGL起始

既然這陣子都在玩這塊,就當作工作筆記順手記一下吧。

JOGL是OPENGL的JAVA BINDING,目前看到除了學術界的運用之外,大概只有Android的3D遊戲會用這種先天不良的3D平台吧。為什麼說是先天不良呢?因為Java的跨平台特性,讓它難以使用現在3D程式大量使用的矩陣高速處理指令之類的加速工具,所以除非是為跨平台,還真的沒必要使用這個技術平台。不過平心而論,這個版本其實也只是把OpenGL包上個Java皮,所以摸到一定程度之後,其實OpenGL的資源拿來稍微修改,也就可以使用,某種意義上比Java3D的資源還多些。

不過這年頭還回頭寫blog,我還真是個科技弱者,不知道下次什麼時候會更新……

Labels: