基本上還是延續上一篇的立體方塊的範例繼續寫下去了∼在上一篇的例子是完成了一個會自動旋轉的立體方塊,而在這一篇則是讓使用者可以透過滑鼠和鍵盤,做簡單的操作。
在 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 的值變小了∼
而最後的網頁,則可以在這裡下載。