WebVR開發教程——玩轉Gamepad手柄

VR Gamepad手柄

如今大部分VR搭配gamepad手柄,用戶經過手持手柄能夠與虛擬場景進行交互。 就如headset頭盔同樣,gamepad手柄也有3-DoF和6-DoF的兩種類型:javascript

  • 3-DoF如daydream controller,只支持方向追蹤,因而google推薦採用laser激光筆進行交互。
  • 6-DoF如Oculus touch,能夠進行方向和位置追蹤,所以能夠很好的模擬手臂的動做。

相比headset傳感器輸入產生的交互,gamepad還多了各類輸入元件,如按鈕、touchpad觸控板或thumbstick手搖桿等。 因而,根據手柄輸入硬件又可將gamepad事件分爲三類:java

  • A. 傳感器事件:由傳感器對手柄進行物理追蹤,如激光筆交互;
  • B. 按鈕事件:經過點擊按鈕產生的交互行爲;
  • C. 控制單元事件:由thumbstick, touchpad輸入產生,如swipe滑動來翻頁等。

Gamepad API

Gamepad API是一個HTML5接口,讓開發者能夠經過js訪問遊戲手柄,使用Gamepad API的第一步是獲取gamepad實例。數組

典型的Gamepad構造 一個典型的gamepad通常都會有button按鈕和axes control控制單元,而VR gamepad則是在前二者的基礎上,加上對傳感器的支持。this

Gamepad

屬性 說明
id string類型,包含手柄的標識信息。
connected bool類型,反映手柄是否處於鏈接狀態
buttons 返回GampadButton對象數組,即手柄上的全部可用按鈕
axes 返回double類型數組,數組元素爲手柄控制元件上各軸向數值
pose 返回一個GamepadPose對象,包含手柄的方向和位置信息

獲取headset實例須要調用navigator.getVRDisplays()方法,一樣,獲取一個手柄的實例,則是調用navigator.getGamepads()方法,它返回一個gamepads數組。 一旦有手柄鏈接上,gamepads數組將產生有效的gamepad對象,不然,只能是null。google

function getGamepad(id)
  const gamepads = navigator.getGamepads();
  for (let i = 0; i < gamepads.length; ++i) {
    let gamepad = gamepads[i];
    // 只有gamepad不爲null纔有效
    if (gamepad && gamepad.id === id)  return gamepad;
  }
}
// 或者寫成這樣: let getGamepad = id => navigator.getGamepads().filter( gamepad => gamepad && gamepad.id === id )[0];
this.gamepad = getGamepad('daydream vr controller'); // 獲取daydream controller手柄

上面實現的是根據手柄id獲取單個gamepad實例的方法,有些VR手柄如Vive Controller, Oculus Touch等是雙手柄,則須要獲取兩個gamepad實例。3d

接下來,我將針對gamepad實例的buttons, axes, pose三個重要屬性進行介紹,它們對應的是手柄按鈕、控制元件、傳感器三類組件,是實現gamepad交互事件的三大法寶。code

Gamepad.buttons

Gamepad.buttons做爲gamepad實例的一個重要屬性,表明手柄或遙控器上的全部可用按鈕,返回的是由一個或多個GamepadButton對象組成的數組。對象

GamepadButton顧名思義指的是gamepad上的按鈕實例,咱們能夠該實例獲取按鈕的狀態,好比是否被點擊。 Gamepad Buttons排序

屬性 類型 說明
id string類型 按鈕的id名
pressed bool類型 按鈕是否處於按壓狀態。
touched bool類型 按鈕是否處於觸摸狀態。
value double類型 反映按鈕被按壓的程度

因爲gamepad的構造都不盡相同,若是想識別Gamepad.buttons中確認鍵或者返回鍵對象,能夠經過GamepadButton.id的值來判斷。 下面是利用pressed實現tap事件的代碼,這裏定義的tap事件,是指手指按下按鈕瞬間產生的觸發事件,不按壓或持續按壓過程不會產生tap。接口

update() {
  const button = this.gamepad.buttons[0]; // 確認鍵對象一般位於數組第一個
  if (!this._lastPressed && button.pressed) {
    // 處理tap事件
  }
  this._lastPressed = button.pressed;
}

用代碼的語言來講,就是隻有知足:1) 上一幀的button.pressedfalse; 2) 當前幀的button.pressedtrue的纔會觸發tap事件。 因而,咱們須要定義一個_lastPressed來記錄上一幀button是否pressed。 使用gamepad.buttons能夠輕鬆實現gamepad按鈕的點擊事件,接下來,將介紹另外一個重要屬性gampad.axes,經過它咱們能夠判斷觸控板手勢、搖桿朝向等。

Gamepad.axes

Gamepad.axes返回的是gamepad控制元件的軸數據集,如手柄上的手搖桿Thumbstick、遙控器上的觸控板Touchpad都是具備雙軸向的元件。 當用戶用手指推動搖桿或者輕觸觸控板時,均可以用一個二維笛卡爾座標[x,y]來表示當前搖桿或觸控板被觸發的方位,以下圖,返回一個-1.0~1.0的double數值組,通常將按水平、豎直的順序排序,如axes[0]表示x軸位置、axes[1]表示y軸位置。

Gamepad Axes

update() {
  const axes = this.gamepad.axes; // 獲取軸向數組
  const x = axes[0], y = axes[1], 
  dx = x - this._lastAxes[0], dy = y - this._lastAxes[1];
  // 控制畫廊位移
  gallery.position.x += dx;
  gallery.position.y += dy;
  this._lastAxes = axes; 
}

上面經過計算兩幀之間搖桿在x軸和y軸的位移,控制畫廊的顯示位置,當搖桿向左推時,畫廊也向左移動。

GamepadPose

gamepad.pose屬性返回的GamepadPose對象,與頭顯的VRPose對象相似,GamepadPose訪問的是VR手柄的傳感器(加速計和陀螺儀),能夠直接獲取gamepad的方向、位置、速度和加速度等信息。

屬性 類型 說明
hasPosition bool gamepad是否具備position屬性。
hasOrientation bool gamepad是否具備orientation屬性。
position Float32Array 返回gamepad的位置矩陣
orientation Float32Array 返回gamepad的方向矩陣
angularAcceleration Float32Array 返回x, y, z軸每秒的角加速度
angularVelocity Float32Array 返回x, y, z軸每秒的角速度
linearAcceleration Float32Array 返回x, y, z軸每秒的線性加速度
linearVelocity Float32Array 返回x, y, z軸的線性速度

hasPosition與hasOrientation

只有3-DoF的gamepad如Gear VR和Daydream的Controller只包含orientation方向矩陣,所以hasOrientationtruehasPositionfalse; 而6-DoF的gamepad如Oculus touch和HTC Vive Controller因爲orientationposition兼具,所以hasOrientationhasPosition都爲true。### position與orientation GamepadPose最重要的屬性,經過這兩個屬性能夠將現實的手柄映射到VR三維世界中,好比當用戶使用手柄玩射擊遊戲時,就須要獲取每一幀gamepad的oritentation,並賦值給3d場景裏的模型。

update() {
    const { orientation, position } = this.gamepad.pose;
    controller.quaternion.fromArray( orientation ); // 將方向矩陣賦值給遙控器模型
    controller.position.fromArray( position ); // 將位置矩陣賦值給遙控器模型
}

Drop Dead

Acceleration與Velocity

GamepadPose還提供了一系列運動屬性:角加速度、角速度、線性速度、線性加速度,咱們能夠根據這些屬性進行更豐富的物理行爲,好比使用加速度×質量來計算物體受力狀況,適用於諸如擊劍、擊球等複雜運動形式,這裏就不展開細說了。

相關文章
相關標籤/搜索