WebVR開發教程——交互事件(一)頭顯與手柄

前兩期主要介紹了開發WebVR應用的基本套路,不過開發出來的場景還只是「可遠觀而不可褻玩」,缺少交互性,本期將帶你們走進VR交互世界,看看WebVR事件是如何開發的。dom

VR交互有哪些?

在可交互的VR世界裏,用戶再也不只是個觀察者,而是虛擬世界中一個生命,能夠與虛擬世界進行通訊。這種通訊應該是雙向的:虛擬場景能感知你的存在(位置、方向),同時你的輸入又對物體產生做用。這裏借鑑一個VR遊戲場景:ide

  1. 一位MM想讓你給她選衣服,彈出一個菜單讓你選,你用touchpad滑動選擇給MM裝扮,你選了一條裙子並點擊手柄的按鈕確認;
  2. MM問你看起來好很差看,你趕忙點頭;
  3. MM很高興,讓你給她拍照,這時候你的手柄已變成了相機,對準她按下按鈕就能夠拍照;
  4. 然而你二話不說蹲下去想欣賞MM的裙底,結果MM生氣了,遊戲結束!
    VR女朋友——點頭與搖頭

上述共採用了四種交互方式,根據輸入設備可分爲headset頭顯交互和gamepad手柄交互,前者經過頭顯行爲觸發事件(如二、4),後者經過手柄行爲觸發事件(如一、3)。this

這些交互行爲都須要硬件支持(好比陀螺儀和加速計提供方向追蹤支持),咱們須要經過JavaScript API來獲取headset或者gamepad的動態數據。google

因爲各VR產商的頭顯和手柄具備差別,所以對於用戶交互層面的支持度也良莠不齊,如下展現各主流VR平臺在頭顯和手柄方面的在交互上的支持狀況。spa

VR類型 |headset|gamepad
:------------:|:------------:|:------------:
Cardboard|3-DoF|無
Daydream Smartphone VR|3-DoF|3-DoF
Daydream Standalone VR|6-DoF|?-DoF
Gear VR|3-DoF|3-DoF
Oculus Rift|6-DoF|6-DoF
HTC Vive|6-DoF|6-DoF
Microsoft MR|6-DoF|6-DoF調試

表中的DoF(degree of freedom)就是咱們常說的自由度,主要爲Orientation自由度和Position自由度兩種。code

  • Orientation自由度,支持方向追蹤,通常由陀螺儀、加速計等傳感器支持
  • Position自由度,支持位置追蹤,通常分爲outside-in(外向追蹤)的紅外追蹤技術和inside-out(內向追蹤)的SLAM技術支持

一般在VR體系裏,3-DoF指的是VR硬件支持Orientation,6-DoF指的是支持Orientation + Position。對象


Headset交互事件

Headset交互根據自由度可分爲3-DoF和6-DoF,顯然,全部的VR頭顯都應支持Orientation方向的3-DoF追蹤。教程

  • 3-DoF依賴於設備的陀螺儀和加速計支持,根據頭部朝向來渲染場景視角,能夠支持gaze注視和搖頭點頭的行爲,通常以手機VR爲主;
  • 6-DoF則指的是支持空間追蹤,因爲能夠感知空間移動,能夠支持Lean, dodge, duck的交互方式,如Oculus Rift和Htc Vive,以及Microsoft MR和Daydream Standalone等。

DoF of Headset

實現headset交互,首先是要能看獲得虛擬世界,上期WebVR深度剖析中VR渲染是實現headset交互的第一步,咱們須要使用WebVR API來獲取headset數據。three

這裏再複習一下:當用戶戴着headset扭頭或走動時,渲染器在每幀經過VRFrameData的視覺-投影矩陣,動態計算出每一個物體的MVP複合矩陣,最後進行頂點和片元繪製。
使人興奮的是,three.js已經將這個過程封裝到了相機和渲染器中,幫咱們實現了第一步。

第二步,咱們須要讓三維場景感知用戶(頭部)的存在,舉個例子,當一個球朝着玩家丟過來的時候,玩家機靈一躲,程序根據球體與玩家的位置判斷玩家是否躲閃成功。
6-DoF交互:躲閃小球
這時候,咱們還須要用到VRFrameData一個重要屬性pose,經過frameData.pose返回一個VRPose對象,可獲取headset的傳感器信息,好比位置、方向、速度和加速度等。

VRPose

屬性|類型|說明
:------------:|:------------:|:------------:
position|Float32Array|返回headset的位置矩陣
orientation|Float32Array|返回headset的方向矩陣
angularAcceleration|Float32Array|返回x, y, z軸每秒的角加速度
angularVelocity |Float32Array|返回x, y, z軸每秒的角速度
linearAcceleration|Float32Array|返回x, y, z軸每秒的線性加速度
linearVelocity |Float32Array|返回x, y, z軸的線性速度

經過這幾個屬性,咱們可讓相機具有物理數據,擁有實體感知能力,而不僅僅只是觀察者模式。

好比,下面實現用戶在使用HTC Vive此類6-DoF的headset時,走動超過範圍彈出警告的功能:

update() {
  const { vrdisplay, frameData, userModel } = this; 
  frameData = vrdisplay.getFrameData(frameData);
  const vrpose = frameData.pose;
  userModel.position.fromArray(vrpose.position); // 將VRPose位置矩陣賦予用戶角色
  const { x, y, z } = userModel.position; // 解構用戶位置的x,y,z座標
  if ( Math.abs(x) > 20 || Math.abs(y) > 20 || Math.abs(z) > 20 ) {
    // 當用戶離初始點超過20×20×20的空間時,彈出警告
    showWarningToast();  // 展現警告框
  }
}

一樣,three.js在VR模式下會自動將VRPose的positionorientation轉化成camera的Object3D屬性,所以咱們能夠直接調用camera.positioncamera.quaternation/rotation獲取用戶的位置和朝向,代碼簡化以下:

update() {
  const { camera, userModel } = this;
  userModel.position.copy(camera.position);
  const { x, y, z } = userModel.position; // 解構用戶位置座標
  if ( Math.abs(x) > 20 || Math.abs(y) > 20 || Math.abs(z) > 20 ) {
    showWarningToast();  // 用戶離初始點超過20×20×20的空間時,彈出警告框
  }
}

基本的headset交互事件就是這樣,理解了這些,咱們能夠實現gaze事件監聽,點頭搖頭事件監聽等。


GamePad交互事件

除了headset,如今大部分VR還搭配gamepad,用戶經過手持手柄能夠與虛擬場景進行交互。

對於gamepad手柄而言,也有3-DoF和6-DoF的兩種類型:

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

相比headset傳感器輸入產生的交互,gamepad還多了各類輸入元件,如按鈕、touchpad觸控板或thumbstick手搖桿等。

因而,根據手柄輸入硬件又可將gamepad事件分爲三類:

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

那麼如何實現gamepad的交互事件呢?其實換個問題就是:如何訪問手柄的硬件信息,答案是使用Gamepad API,詳見WebVR開發教程——交互事件(二)使用Gamepad


WebVR開發傳送門:

WebVR開發教程——深度剖析 關於WebVR的開發調試方案以及原理機制
WebVR開發教程——標準入門 使用Three.js開發WebVR場景的入門教程

相關文章
相關標籤/搜索