2014年2月2日 星期日

JOGL Animation

在JOGL中,動畫的環境由com.sun.opengl.util.Animator類別處理,其建構函式為:

  public Animator()
  public Animator(GLAutoDrawable drawable)

其中參數drawableGLAutoDrawable介面之物件,可GLCanvasGLJPanel類別建立、或以GLAutoDrawable介面的getGL()方法建立。

Animator物件建立之後,可使用以下方法處理動畫:
  • start()開始處理動畫。
  • stop()停止處理動畫。
  • isAnimating()判斷是否正在執行動畫處理。
以Java Swing為例:


// Set OpenGL Capabilities
GLCapabilities glcapabilities = new GLCapabilities();
// Set Drawable Factory
GLDrawableFactory gldrawablefactory =
  GLDrawableFactory.getFactory();
GLDrawable gldrawable = gldrawablefactory.getGLDrawable(
  this, glcapabilities, null);
// Set Double Buffer
glcapabilities.setDoubleBuffered(true);

// 建立GLJPanel物件 
GLJPanel glpanel = new GLJPanel(glcapabilities);
// 註冊GLEventListener
glpanel.addGLEventListener(this);
...

// 建立Animator物件
Animator animator = new Animator(glpanel);
glpanel.requestFocusInWindow();
// 開始動畫處理
animator.start();
...


當以start()方法開始處理動畫時,則整個GLJPanel物件將處於動畫的狀態,但如何處理動畫,仍需自行設計。

請參考以下範例,以Animator類別處理動畫環境,此外並使用以下的方法:
  • glLoadIdentity():載入單位矩陣 (Identity Matrix)。
  • glMaterialfv():設定物體的材質 (Material)。
  • glMatrixMode():設定座標系統。
  • glPopMatrix():自堆疊最上層移除矩陣。
  • glPushMatrix():複製目前矩陣至堆疊最上層。
  • gluNewQuadric():建立二次曲面 (Quadric)。
  • gluQuadricOrientation():設定二次曲面的方向 (Orientation)。
  • glutWireSphere():繪製線框球體 (Wireframe Sphere)。


// 實作GLEventListener介面之方法
// 初始化JOGL
public void init(GLAutoDrawable drawable) {
  GL gl = drawable.getGL();
  gl.setSwapInterval(1);

  float white[] = {1.0f, 1.0f, 1.0f, 1.0f};

  gl.glEnable(GL.GL_CULL_FACE);
  // 啟用光源 
  gl.glEnable(GL.GL_LIGHTING);
  // 啟用光源0 
  gl.glEnable(GL.GL_LIGHT0);
  gl.glEnable(GL.GL_DEPTH_TEST);

  /* make the Ball */
  ball = gl.glGenLists(1);

  GLUquadric quad;
  quad = glu.gluNewQuadric();
  glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE);
  glu.gluQuadricNormals    (quad, GLU.GLU_SMOOTH);
  glu.gluQuadricTexture    (quad, true);

  gl.glNewList(ball, GL.GL_COMPILE);
  gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, white, 0);

  glut.glutWireSphere(5, 25, 25);
  gl.glEndList();
          
  gl.glEnable(GL.GL_NORMALIZE);
}

// 繪製圖形
public void display(GLAutoDrawable drawable) {
  angle += 100.0f;

  GL gl = drawable.getGL();
  
  if ((drawable instanceof GLJPanel) &&
      !((GLJPanel) drawable).isOpaque() &&
      ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {

    // 以目前之顏色清除視窗
    gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
  } 
  else {
    // 以目前之顏色清除視窗
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
  }
          
  // 複製目前之矩陣至堆疊最上層
  gl.glPushMatrix();
  // 沿x座標旋轉指定角度
  gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
  // 沿y座標旋轉指定角度
  gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
  // 沿z座標旋轉指定角度
  gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
          
  // 沿x,y,z座標旋轉指定角度
  gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
  gl.glCallList(ball);
  // 自堆疊最上層移除矩陣
  gl.glPopMatrix();
  // 即刻執行JOGL指令 
  gl.glFlush();
}

// 當視窗大小改變時
public void reshape(GLAutoDrawable drawable, 
  int x, int y, int width, int height) {
  
  GL gl = drawable.getGL();

  float h = (float)height / (float)width;
          
  // 設定座標系統
  gl.glMatrixMode(GL.GL_PROJECTION);

  gl.glLoadIdentity();
  gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
  // 設定座標系統
  gl.glMatrixMode(GL.GL_MODELVIEW);
  gl.glLoadIdentity();
  gl.glTranslatef(0.0f, 0.0f, -40.0f);
}


【執行結果】


【參考資料】

[1] Java Platform, Standard Edition 7, API Specification.
[2] JOGL.
[3] 黃嘉輝,完全探索Java遊戲程式設計,上奇資訊。

© Chia-Hui Huang


沒有留言:

張貼留言