OasisInputManager设计与实现

作者&投稿:子车馨 (若有异议请与网页底部的电邮联系)
~

引言

交互输入是引擎功能层中十分重要的一个功能,它允许用户使用设备,触摸或手势来与应用程序进行人机交互,在0.6里程碑中,我们初步搭建了Oasis的交互系统,目前已经支持了点击与键盘,而本文将与大家分享开发过程中的思路与不足。

整体设计

主要架构

输入设备,触摸,XR设备等都属于交互系统的输入,在Oasis中我们将输入的所有逻辑收拢在输入管理器(InputManager)中,根据各种不同类型的输入再细分出触控管理器(PointerManager)与键盘管理器(KeyBoardManager)等特定输入。输入管理器分管所有特定输入管理器,在交互的帧处理中,只需要处理各个管理器内特定输入的逻辑即可。

API设计

帧内生命周期

如下是Oasis运行时帧处理的生命周期:InputManager的内部生命周期如下:

如何使用

Pointer

为三维空间内有碰撞体积的物体增加碰撞体。

参考脚本组件(Script)内回调接口的触发条件添加适宜的逻辑。|接口|触发时机与频率||---|---||onPointerEnter|当触控点进入Entity的碰撞体范围时触发一次||onPointerExit|当触控点离开Entity的碰撞体范围时触发一次||onPointerDown|当触控点在Entity的碰撞体范围内按下时触发一次||onPointerUp|当触控点在Entity的碰撞体范围内松开时触发一次||onPointerClick|当触控点在Entity的碰撞体范围内按下并松开,在松开时触发一次||onPointerDrag|当触控点在Entity的碰撞体范围内按下时持续触发,直至触控点解除按下状态|

KeyBoard

直接调用交互管理器(InputManager)提供的方法判断按键状态。

方法名称方法释义isKeyHeldDown返回这个按键是否被持续按住isKeyDown返回当前帧是否按下过此按键isKeyUp返回当前帧是否抬起过此按键

鼠标与触控

背景

PointerEvent是浏览器内鼠标与触控交互后续发展的势头,Pointer是输入设备的硬件层抽象,开发者不需要关心数据来源是鼠标,触控板或是触摸屏,但是它也有一定兼容性问题,可以看到在canIUse中,PointerEvent的设备覆盖率为:92.82%,需要通过导入Polyfill来解决。

需求调研

在脚本组件中增加响应Pointer的钩子函数,对于在三维空间中有碰撞体积的实体,可以让开发者通过补充对应钩子函数内的逻辑方便地实现点击,拖动,选中等交互操作。

钩子函数触发时机与频率onPointerEnter当触控点进入Entity的碰撞体范围时触发一次onPointerExit当触控点离开Entity的碰撞体范围时触发一次onPointerDown当触控点在Entity的碰撞体范围内按下时触发一次onPointerUp当触控点在Entity的碰撞体范围内松开时触发一次onPointerClick当触控点在Entity的碰撞体范围内按下并松开,在松开时触发一次onPointerDrag当触控点在Entity的碰撞体范围内按下时持续触发,直至触控点解除按下状态

原生事件

和MouseEvent,TouchEvent一样,PointerEvent也可以通过监听捕获。canvas.addEventListener('pointerXXX',callBack);

MouseEventTouchEventPointerEvent按下mousedowntouchstartpointerdown抬起mouseuptouchendpointerup移动mousemovetouchmovepointermove离开mouseout|mouseleavetouchend|touchcancelpointerout|pointercancel|pointerleave

流程图

可以归纳出Pointer处理的大致流程,其中绿框代表原生事件。

射线检测

在Pointer中要解决的最大问题是如何根据原生事件中的位置信息在三维空间中做射线检测,因为这部分内容不仅仅包含空间转换的基本知识,还包含了物理系统的基础使用。

在我们捕获了PointerEvent后,需要

从原生事件中获取有效的屏幕位置信息。

将位置从屏幕空间转换到三维空间,并获取检测射线。

射线与碰撞体相交检测。

回调脚本。

屏幕位置信息

我们期望拿到指针相对于目标元素的位置,但是原生事件中关于坐标的属性有很多,因此需要甄别哪个坐标信息是有效的。

原生事件坐标属性属性释义clientX&clientY相对于触发事件的应用区域的坐标(可视区域坐标)offsetX&offsetY相对于目标元素的坐标pageX&pageY相对于整个Document的坐标(包含滚动区域)screenX&screenY相对于主显示屏左上角的坐标(基本不会使用)x&y同clientX&clientY

他们有以下的转换关系(假设原生事件为event,点击的目标元素为canvas):可以得到的结论是:大多坐标属性都可以得到期望的坐标信息,其中offset最直接方便。

空间转换

简化射线检测,根据从获取到屏幕上点击的坐标得到三维空间中的一条射线,然后与三维空间中碰撞体进行碰撞检测。

以透视相机为例,当获取到屏幕上点击的坐标后,只需要完成以下步骤便可得到射线:

offset->屏幕空间

屏幕空间->裁剪空间

裁剪空间->世界空间

有图形引擎基础的同学比较熟悉我们在渲染时经过了如下变换:

模型空间->世界空间

世界空间->观察空间->裁剪空间

裁剪空间->屏幕空间

似乎只需要得到屏幕空间的坐标,然后再经过几个空间变换的逆变换即可。

offset->裁剪空间

需要对像素(pixel),设备独立像素(dips与设备像素比(divicePixelRatio有一个大致的了解,从点击事件中的属性offset获取的坐标信息携带的单位是设备独立像素,因此在求解屏幕空间坐标的时候需要注意分子与分母的单位一致。

裁剪空间是XYZ范围皆在-1到1的左手坐标系(裁剪空间可以形象地理解为当渲染范围超出这个区间就会被裁减),此处转换时需注意:

求解触摸点在屏幕空间的相对位置时要注意分子与父母应都为像素或都为设备独立像素。

裁剪空间Y轴方向向上,offset参考坐标系Y轴方向向下,因此Y轴需翻转。

裁剪空间中depth离观察者越远值越大,简单来说近平面是-1远平面是1。

屏幕空间的点->世界空间的射线

公示推导中矩阵为列为主序。

以透视相机为例,世界空间经过View变换和Project变换即可转换到裁剪空间,那么从裁剪空间转换到世界空间只需要经历这些变换的逆即可。

检测射线

上式中代入近平面深度与远平面深度依次求得触摸点在世界坐标空间下近平面与远平面的投影点,连接这两个点即可得到检测射线。

射线相交检测

碰撞体由规则几何体组成(长方体,球体等)可以查阅相关射线与几何体相交算法。

脚本回调

当物理引擎返回命中的碰撞体后,可以认为它的Entity这就是当前帧的所有onPointerXXX回调的当事人了,在这个环节只需要根据收集的原生事件进行脚本回调即可。

性能优化

压流:捕获PointerEvent后将原生事件压入数组,待执行到交互系统的tick时,再按序处理相应逻辑。

Pointer合并:射线检测的性能损耗较大,所以在屏幕上有多个触控点时,我们会按照一定规则合并这几个触控点,因此在触控交互逻辑中每帧的射线检测至多只会执行一次。

多相机场景:当出现多相机时,会依次检查渲染范围包含了点击点的所有相机,并根据相机的渲染顺序进行排序(后渲染优先),如果当前比较的相机渲染场景内没有命中碰撞体且相机的背景透明,点击事件会继续传递至上一个渲染的相机,直至命中或遍历完所有相机。

注意事项

正如开篇提到的兼容性问题,如果你的Oasis项目可能运行在低系统版本的机器中,可以导入我们定制的PointerPolyFill。https://github.com/oasis-engine/polyfill-pointer-event

键盘输入

需求调研

获取当前帧所有按下过的按键

获取当前帧所有松开过的按键

获取当前还按着的按键

判断某个按键在当前帧是否按下过

判断某个按键在当前帧是否松开过

判断某个按键现在还按着

原生事件

KeyBoardEvent可以通过监听捕获。canvas.addEventListener('keyXXX',callBack);

事件触发时机keypress字符键按下时触发keydown任意键按下时触发keyup任意键抬起时触发

流程图

可以归纳出键盘处理的大致流程,其中绿框代表原生事件。

索引值的选定

无论是在不同的大小写状态或不同键盘的布局下,按键都是一个可枚举的值,如果可以键值以枚举的形式存储,无论对性能还是使用都将带来极大的便利,因此需要确定适宜作为枚举值的属性。

以下为KeyEvent内可作为枚举值的属性:

属性属性释义简单示例兼容性code触发事件的物理按键,与布局无关无论大小写或布局,当你按下Y键时,返回都是物理键“KeyY”兼容key触发事件的键值当小写时为“y”,大写时为“Y”兼容charCode已弃用keyCode已弃用char已弃用

可以发现,最适用的属性是code,参考https://w3c.github.io/uievents-code/。

性能优化

每帧按键的交互逻辑较为简单,维护按下,松开与按住的三个数组即可满足所有需求,重点是如何降低帧级别增,删,查操作的性能损耗。

优化增加元素与重置数组长度,可以使用无序数组

优化查询可以额外增加索引

无序数组

无序数组在绝大多数情况下减少了增加与删除元素时性能损耗,下图表示无序数组组成:下图表示无序数组如何降低性能损耗:

存储与索引

若仅使用三个无序数组,当需要查特定按键的状态依旧需要遍历数组,在极端情况下带来的性能损耗也不可小觑,如果将此现成的按键枚举作为Key,当前帧的是否按下过记录成Value就可以避免遍历。虽然这样实现可以让查询变得更快,却额外增加了维护成本——每帧开始需要重置映射表的状态,但如果保存的是帧序号,就可以完美避免这个消耗,只需要在每帧开始的时候更新帧序号即可。依葫芦画瓢,在记录HeldDown的按键时也增加了一个表来映射按键在无序数组中的索引。

快速上手按键状态isKeyHeldDownisKeyDownisKeyUp该键从上帧开始就一直按着truefalsefalse该键当前帧按下后就没有松开truetruefalse该键在当前帧松开后又按下truetruetrue该键在当前帧按下后又松开falsetruetrue该键在当前帧被抬起falsefalsetrue该键没按下且没交互falsefalsefalse不会出现这种情况truefalsetrue不会出现这种情况falsetruefalse

注意事项

当按住某个按键持续一段时间时,原生的keydown事件会不断触发,Oasis已经考虑并过滤了此情形,所以开发者无需做任何额外处理。

某些状态按键的原生事件表现可能比较怪异,甚至在FireFox和Chrome上触发事件的表现都不一致。(如CapsLock)

如何进一步了解我们

Oasis开源社区群(钉钉):

Oasis开源社区群管理员(微信):

网站

官网地址https://oasisengine.cnGit源码地址https://github.com/oasis-engine/engine

原文:https://juejin.cn/post/7098272905762439176




如何查看Apache的configure编译参数
–disable-asis as-is filetypes –enable-info server information –enable-suexec set uid and gid for spawned processes –disable-cgid CGI scripts –enable-cgi CGI scripts –disable-cgi CGI scripts –enable-cgid CGI scripts –enable-dav-fs DAV provider for the filesystem –enable-dav-lock DAV...

电脑英文简写?
MB表示兆字节。M=Mega,构词成分,表示“兆;百万”。GB:Giga Byte,GB表示千兆字节。G=Giga,构词成分,表示“千兆;十亿”。CAI:Computer-Asisted Instruction或Computer-Aided Instruction,计算机辅助教学。它将是二十一世纪最重要、最受欢迎的教学手段。CAD:Computer-Aided Design,计算机辅助设计 ...

本人刚学电脑,想找点关于计算机上常用的英语的汉语翻译
CAI:Computer-Asisted Instruction或Computer-Aided Instruction,计算机辅助教学。它将是二十一世纪最重要、最受欢迎的教学手段。 CAD:Computer-Aided Design,计算机辅助设计。 ISO:International Standard Organization,国际标准化组织。ISO于1987年推出有关质量管理和质 量保证的ISO 9000系列国际标准,于1994年又发布了经...

计算机硬件英文字母
FIFO(First Input First Output,先入先出队列) flip-chip(芯片反转) FLOP(Floating Point Operations Per Second,浮点操作\/秒) FMUL(Floationg Point Multiplication,浮点乘) FPU(Float Point Unit,浮点运算单元) FSUB(Floationg Point Subtraction,浮点减) GVPP(Generic Visual Perception Processor,常规视觉处理器)...

关于计算机的英语单词或句子,要有中文翻译的,要快!!~~
CAI:Computer-Asisted Instruction或Computer-Aided Instruction,计算机辅助教学。它将是二十一世纪最重要、最受欢迎的教学手段。CAD:Computer-Aided Design,计算机辅助设计。ISO:International Standard Organization,国际标准化组织。ISO于1987年推出有关质量管理和质量保证的ISO 9000系列国际标准,于1994年...

UEFITool如何修改BIOS的开机检测项目
MAC地址内修改。找到主板上网口位置的MAC地址,图示左下角白色的网口位置贴纸上就是本机的MAC地址,使用UEFITool打开BIOSbin文件,Intelimage下有GbEregion,就是MAC地址了,右键导出并保存,会有一个后缀rgn的文件(软件不要关,修改后还要替换回去),回到UEFITool打开的BIOS.bin文件,右键Replaceasis,选择...

电脑知识
BIOS(Basic-Input-&-Output-System基本输入\/输出系统):直译过来后中文名称就是“基本输入输出系统”。它的全称应该是ROM-BIOS,意思是只读存储器基本输入输出...CAI:Computer-Asisted Instruction或Computer-Aided Instruction,计算机辅助教学。它将是二十一世纪最重要、最受欢迎的教学手段。 CAD:Computer-Aided Design,...

计算机有关的英语单词及翻译两样都要。
input 输入inquiry 询问instruction 指令integrated circuit 集成电路to interpret 解释item 项目,项jump 转移key 键,关键码keyboard 键盘latency time 等待时间 library 库,程序库linkage 连接to load 装入,寄存,写入,加载location 存储单元logger 登记器,记录器loop 循环machine language 机器语言magnetic storage 磁存储器...

你可能想看的相关专题

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网