WebGL 範例:簡單的互動操作

基本上還是延續上一篇的立體方塊的範例繼續寫下去了∼在上一篇的例子是完成了一個會自動旋轉的立體方塊,而在這一篇則是讓使用者可以透過滑鼠和鍵盤,做簡單的操作。

在 WebGL 裡的事件觸發與控制,主要是透過 JavaScript 來做的,所以其實所要加入的程式,主要都是 JavaScript 的部分;而這個範例裡使用的方法,是當使用者觸發了特訂的事件後,再透過去修改一些內部的變數,進而影響到最後畫出來的結果。

首先先來看 diaplay() 部分的變化:

function display()
{
  // Clear the canvas
  gWGL.clear( gWGL.COLOR_BUFFER_BIT | gWGL.DEPTH_BUFFER_BIT );

  // Compute a model/view matrix.
  gWGL.mvpMatrix.makeIdentity();
  gWGL.mvpMatrix.rotate( gAngleY, 0, 1, 0 );
  gWGL.mvpMatrix.rotate( gAngleX, 1, 0, 0 );
  gWGL.mvpMatrix.translate( 0, 0, gZpos );

  // Coompute the model-view * projection matrix
  gWGL.mvpMatrix.multRight( gWGL.ProjectionMatrix );

  // pass the matrix into shader
  gWGL.uniformMatrix4fv( gWGL.u_mvpMatrixLoc, false, gWGL.mvpMatrix.getAsWebGLFloatArray() );

  // Draw the cube
  gWGL.drawElements( gWGL.TRIANGLES, gWGL.RenderObject.numIndices, gWGL.UNSIGNED_BYTE, 0 );

  // Finish up.
  gWGL.flush();
}

這邊和之前的程式主要的差異有兩部分,其中一部分就是上方黃色的區域,這部分的程式是變成透過 gAngleY、gAngleX、gZPos 三個變數來計算 model view matrix;另一部分則是將本來 diaplay() 最後面,用來計算 currentAngle、以做到自動旋轉的程式拿掉了。而也由於這兩部分的修改,所以本來的全域變數 currentAngle 和 incAngle 都用不到了∼相對的,則是要宣告 gAngleY、gAngleX、gZPos 這三個新的變數。

而在 display() 這樣修改後,之後要用來作互動的 JavaScript 程式只要去修改 gAngleY、gAngleX、gZPos 這三個變數的值,就可以做到簡單的互動了!

在這個範例,由於只是要做最簡單的互動測試,所以只會針對兩種 event 做處理,其中一個是 Canvas、也就是 WebGL 繪製區域的 mouse move 事件(onmousemove),另一個則是整個網頁的鍵盤輸入事件(onkeydown);如果有需要的話,其實也是可以再額外定義不同事件的處理函式,不過在這邊就先不提了。

而這部分的程式,主要是要在主程式 RunWebGL() 裡,加上對於事件處理的設定。

function RunWebGL()
{
  // try to get WebGL Context
  try
  {
    gCanvas = document.getElementById( "canvas_object" );
    gWGL = gCanvas.getContext( "experimental-webgl" );
  }
  catch( e )
  {
    alert( "WebGL 初始化失敗" );
    return;
  }

  // set event handle
  gCanvas.onmousemove = mouseMove;
  document.onkeydown = keyboardEvent;

  // setup viewport
  gWGL.viewport( 0, 0, gCanvas.width, gCanvas.height );
  ...

這部分的程式就是上方黃色的區塊,第一行是設定當滑鼠游標在 gCanvas 上移動時,就去執行 mouseMove() 這個函式;而第二行則是設定當按下鍵盤時,就去執行 keyboardEvent() 這個函式。

mouseMove() 所做的事實際上是根據滑鼠游標的位置,來修改 gAngleY、gAngleX 的值,進而做到立體方塊的旋轉;他的程式碼如下:

function mouseMove( ev )
{
  var w = gCanvas.width / 2, h = gCanvas.height / 2;
  gAngleY = 90 * ( ev.clientX - gCanvas.offsetLeft - w ) / w;
  gAngleX = 90 * ( ev.clientY - gCanvas.offsetTop - h ) / h;
}

這邊的程式主要是會計算出滑鼠位置(ev.clientX / ev.clientY)和 canvas 的中心點的差,然後再把他調整成 -1 ~ 1 的值,之後再乘上 90 度;所以最後所得到的 gAngleX 和 gAngleY 的值會根據滑鼠的位置,而在 -90 ~ 90 之間。

不過有一點要注意的是,由於這是比較簡單的範例,所以 canvas 本身的位置可以直接用 ( gCanvas.offsetLeft, gCanvas.offsetTop ) 來計算;但是如果網頁設計的複雜些的話,有可能會要需要做其他較複雜的處理,才能真正算出他的位置。

keyboardEvent() 則是用來接收鍵盤按下的事件,在這個範例裡,只有針對 Page Up 和 Page Down 兩個鈕做處理,用來做物體的拉遠、拉近控制;他的程式碼如下:

function keyboardEvent( ev )
{
  switch( ev.keyCode )
  {
  case 33: //page up
    gZPos  = 0.1;
    break;

  case 34: //page down
    gZPos -= 0.1;
    break;
  }
}

這部分的程式,基本上就是在按下 Page Up 時,把 gZPos 的值變大,在按下 Page Down 時,把 gZPos 的值變小了∼

而最後的網頁,則可以在這裡下載

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。