资讯专栏INFORMATION COLUMN

WebVR开发教程——交互事件(二)使用Gamepad API

pubdreamcc / 1503人阅读

摘要:返回的位置矩阵返回的方向矩阵返回轴每秒的角加速度返回轴每秒的角速度返回轴每秒的线性加速度返回轴的线性速度与只有的如和的只包含方向矩阵,因此为而为而的如和由于和兼具,因此和都为。


上期 WebVR开发教程——交互事件(一)头显与手柄 从头显和手柄两个层面对VR交互事件进行介绍,前者使用的是WebVR API,而后者则需用到Gamepad API,本期将对Gamepad API展开介绍。

Gamepad API

Gamepad API是一个HTML5接口,让开发者可以通过js访问游戏手柄,使用Gamepad API的第一步是获取gamepad实例。


一个典型的gamepad一般都会有button按钮和axes control控制单元,而VR gamepad则是在前两者的基础上,加上对传感器的支持。

Gamepad

属性|说明
:------------:|:------------:
id|string类型,包含手柄的标识信息。
connected|bool类型,反映手柄是否处于连接状态
buttons|返回GampadButton对象数组,即手柄上的所有可用按钮
axes|返回double类型数组,数组元素为手柄控制元件上各轴向数值
pose| 返回一个GamepadPose对象,包含手柄的方向和位置信息

获取headset实例需要调用navigator.getVRDisplays()方法,同样,获取一个手柄的实例,则是调用navigator.getGamepads()方法,它返回一个gamepads数组。
一旦有手柄连接上,gamepads数组将产生有效的gamepad对象,否则,只能是null。

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实例。

接下来,我将针对gamepad实例的buttons, axes, pose三个重要属性进行介绍,它们对应的是手柄按钮、控制元件、传感器三类组件,是实现gamepad交互事件的三大法宝。

Gamepad.buttons

Gamepad.buttons作为gamepad实例的一个重要属性,代表手柄或遥控器上的所有可用按钮,返回的是由一个或多个GamepadButton对象组成的数组。

GamepadButton顾名思义指的是gamepad上的按钮实例,我们可以该实例获取按钮的状态,比如是否被点击。

属性|类型|说明
:------------:|:------------:|:------------:
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轴位置。

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 ); // 将位置矩阵赋值给遥控器模型
}

Acceleration与Velocity

GamepadPose还提供了一系列运动属性:角加速度、角速度、线性速度、线性加速度,我们可以根据这些属性进行更丰富的物理行为,比如使用加速度×质量来计算物体受力情况,适用于诸如砍杀、击球等复杂运动形式,这里就不展开细说了。

小结

至此,WebVR事件开发基础已经讲完,接下来,我将对各主流VR类型进行针对性实现,根据交互的复杂性,将按照Cardboard→Gear VR→Daydream→Oculus Rift 由屌丝到高富帅的路线。

WebVR开发传送门:

WebVR开发教程——交互事件(三)Cardboard与注视
WebVR开发教程——深度剖析 关于WebVR的开发调试方案以及原理机制
WebVR开发教程——标准入门 使用Three.js开发WebVR场景的入门教程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89437.html

相关文章

  • WebVR开发教程——交互事件(一)头显与手柄

    摘要:交互事件交互根据自由度可分为和,显然,所有的头显都应支持方向的追踪。交互事件除了,现在大部分还搭配,用户通过手持手柄可以与虚拟场景进行交互。 showImg(https://segmentfault.com/img/remote/1460000011813767?w=880&h=471); 前两期主要介绍了开发WebVR应用的基本套路,不过开发出来的场景还只是可远观而不可亵玩,缺乏交互...

    harriszh 评论0 收藏0
  • WebVR开发教程——交互事件(三)Cardboard与注视

    摘要:开发传送门开发教程交互事件一头显与手柄开发教程交互事件二使用开发教程深度剖析关于的开发调试方案以及原理机制开发教程标准入门使用开发场景的入门教程 showImg(https://segmentfault.com/img/remote/1460000011814846?w=1240&h=587); Cardboard可以说是手机VR头显的元老了,狭义上指的是Google推出的一个带有双凸...

    Allen 评论0 收藏0
  • SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

    摘要:在文末,我会附上一个可加载的模型方便学习中文艺术字渲染用原生可以很容易地绘制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 Web...

    objc94 评论0 收藏0
  • WebVR教程——Web Audio开发3D音效

    摘要:输入结点主要负责加载解码音频源,比如获取二进制音频源的获取音频源的等处理结点主要对音频数据进行计算处理,比如处理音频振幅的等输出结点则将音频输出至扬声器或耳机,便是默认的输出节点。 showImg(https://segmentfault.com/img/remote/1460000012753856); 在VR开发中,除了图形视觉渲染,音频处理是重要的一环,好的音频处理可以欺骗用户的...

    youkede 评论0 收藏0
  • 前端清单第 27 期:React Patent License 回复,Shopify WebVR

    摘要:新闻热点国内国外,前端最新动态就开源许可证风波进行回复数周前,基金会决定禁止旗下项目使用,因为其在标准的许可证之外添加了专利声明此举引发了社区的广泛讨论,希望能够更新其开源许可证。 showImg(https://segmentfault.com/img/remote/1460000010777089); 前端每周清单第 27 期:React Patent License 回复,Sho...

    jeffrey_up 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<