《视觉悬崖》技术实现

今天线下微课堂将要学习如何使用Python制作一款惊险刺激的VR体验内容---“视觉悬崖”。说到这个Demo就厉害了,当年扎克伯格就是体验了这个Demo决定收购了Oculus。(那个时候WorldViz的整体解决方案中采用了Oculus的头盔,小扎在WorldViz展会上体验了这个Demo并且与WorldViz的CEO交流虚拟现实相关技术,由于WorldViz更多面向企业级应用与Facebook战略不同,最后决定收购Oculus)

正式讲解前,T3博士先来带领大家体验一下《视觉悬崖》的神奇。

本篇图文为纯纯的技术贴,非开发人员看起来或许内心是这个样子的

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(1)

开始讲解之前,需要各位小伙伴安装Vizard虚拟现实开发引擎,这个引擎的开发语言使用了当今最具潜力的Python语言,据2016年统计的最受欢迎的开发语言中Python位居第一占据26.7%的市场份额。Vizard可以到WorldViz官网下载安装(http://www.worldviz.com/virtual-reality-software-downloads/)。

Vizard安装好之后,大家可在安装目录下的\examples\pit\pit.py找到“视觉悬崖”的源码。

模型中的平台(pit)和铁板桥(platform)是两个独立的物件并且有各自的名称,一会我们就通过编码来控制这两个物件。

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(2)

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(3)

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(4)

2

接下来,就是程序的整体结构。与Unity游戏开发引擎相比,Vizard可以看成为更单纯的IDE开发环境。代码的编写不会散落在场景中的各个组件中,整体架构不用必须按照引擎的特定要求设计而是完全根据业务的需要进行程序架构设计。

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(5)

其中,Pit类是用来对模型进行初始化加载、声音加载以及升降控制操作等。

TrackedFaller类是坠落的基类用来实时判断是否达到坠落的条件以及坠落的速度和位置等。

PitTrackedFaller类继承了TrackedFaller,用来实现在平台上坠落后的一些具体操作。

我们先想一想在整个Demo体验过程中,需要考虑哪些关键点?

1、平台以及铁板桥的升降

2、音效和画面效果的变化

3、得到体验者的位置并判断是否坠落以及坠落位置

平台和铁板桥的升降控制

Pit类中togglePit这个方法用来控制平台的升降。

pos = self._pit_positions[self._pit_lowered] 是用来获取即将降落或升起的位置,这个语句写得很精妙,self._pit_positions = [[0, -8.1, 0], [0, 0, 0]] 这个列表在构造函数中进行了赋值。self._pit_lowered初始化为False,False即0,则pos取值为[0,-8.1,0]也就是平台即将降落的位置,self._pit_lowered = not self._pit_lowered 在平台降到底端后self._pit_lowered 设置为True即1,则在下一次升起时pos取值为[0,0,0]

铁板桥的升降也同理。

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(6)

音效和画面效果变化

在togglePit方法中,有self._pit_running_sound用来控制声音播放还是停止。

self._pit_running_sound加载了平台运行时的音效,在平台或铁板桥升降时需要播放。Vizard原生支持3D音效。

如下图中,fallSound加载了跌落的音效,在体验者跌落时播放。

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(7)

self._flashQuad加载了一个可复用的特效模块,用来模拟体验者坠落后流血和昏迷的感觉,用到了一些简单的Shader,本章节不做特别介绍,有兴趣的小伙伴可以自己学习了解。

得到体验者的位置并判断是否坠落

这个就要研究TrackedFaller类了,具体代码大家可以自己阅读学习。我来介绍几个关键点:

事件:

Vizard的事件定义和注册很灵活,你可以根据实际情况选择不同的实现方式,事件的具体介绍可查看Vizard的帮助文档。在TrackedFaller类的构造函数中先注册update这个事件,该事件为每帧更新时所触发。

self._updater = vizact.onupdate(10, self.update)

获取体验者位置:

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(8)

self._tracker.getPosition(viz.ABS_GLOBAL) 通过该语句获取追踪器的位置,可以理解为实际物理设备的追踪位置。

tracker_pos[1] = self._transport.getPosition(viz.ABS_GLOBAL)[1]

通过该语句获取Transport位置,可理解为体验者由控制器摇杆操控的位置。只需要获取Y轴数据即可。

view_pos[1] = self.STEP_HEIGHT根据追踪位置获取视点位置,由于Transport位置的Y轴紧贴地面,为了准确判断与场景中其他模型交叉,需要再向上额外增加一个self.STEP_HEIGHT的高度。

判断是否坠落:

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(9)

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(10)

在update函数中,需要以view_pos为起始点向下建立向量,该向量交叉的场景模型有可能就是坠落后的着陆点。这里需要说明的是,人体是立体的所以除了人体中间的这个向下向量外还需要根据self.FALL_EDGE_BUFFER设置的参数在体验者四边额外形成四条向下的向量。

扎克伯格为什么能成功(当年扎克伯格体验过的视觉悬崖实现技术大剖析)(11)

当没离开铁板桥面时,向量最先交叉的仍然是桥面,所以不会产生坠落。当体验者中心及四周共5条向下向量均都不与铁板桥交叉,则产生坠落。

坠落的点即为五条向量中离体验者最近的交叉点位置。坠落过程中根据两帧之间的间隔时间以及预先定义的self.GRAVITY重力加速度来计算速度和当前帧应设置的位置。

基本上《视觉悬崖》的大致思路如上所述,但其中还是有很多细节需要大家仔细了解学习,哪里不明白的也欢迎在线下微课群里或微信公众号上直接提问。

提问

最后大家思考一个问题,为什么不使用物理引擎来实现呢?可关注我们的微信公众号进行交流。

《视觉悬崖》除了技术实现的众多细节需要大家了解,其中蕴含的心理学原理我们会在后续章节给大家做一下讲解,敬请期待。

获取更多精彩内容,请在微信端搜索并关注“T3教育”公众号。

关于T3教育:

T3教育,专注前沿科技知识的教学与推广,核心讲师来自美国硅谷和国内顶尖高校的专家教授以及一线的科研人员,以在线精品培训短视频的方式将专家教授教学思想和科研人员的学习实践成果毫无保留的传授给每一位学员。

,