直播链接[英文直播]探索OpenXR VR模板(官方字幕)_哔哩哔哩_bilibili

OpenXR

OpenXR是一个免版权费的开放标准,用于提供对AR、VR、MR设备(统称为XR设备)的高性能访问。

  • 用于XR应用的API
  • 应用和runtime之间的接口
  • 一种用于与AR、VR、MR交互的机制,并且不受平台的影响

OpenXR官网:OpenXR Overview - The Khronos Group Inc

现在的厂商都使用自己的SDK去开发VR应用,如果需要将Oculus的应用迁移到StreamVR上,就需要将底层的SDK更换一次,耗时费力,使用统一的OpenXR接口可以避免这种情况。2609afec95b1d5370b9e9d7aad52b028.pngOpenXR分为标准接口和extension接口,厂商可以在standard接口的基础上实现自己的ext接口从而支持其硬件独有的功能或者一些额外的拓展功能。

VRTemplate

打开4.27,选择VR模板

  • 注意到项目默认设置使用前向渲染

  • 默认打开了mobile multi-view

Multi-view浅析

  • 默认关闭了移动HDR,即无法使用移动端后处理,但是可以提升性能并且使用立体化渲染

注意mobile前缀,即只影响移动端

在模板中使用tab键开启旁观者模式,可以使用其中的捕获的RT做镜子或者录制第三人称的视频

  • motioncontroller组件是硬件手柄在游戏世界中的具现化,实时接收openxr接口发送过来的数据。

可以看见并没有指定模型,那为什么运行时可以看见模型呢,是因为 显示设备模型 开关,这里会在运行时去关联一个对应的交互输入的profile,而这个profile中指定了相关联的设备模型mesh可以在OpenXR Content中找到所有可用模型

 

(注意vive和oculus的手柄可能会有一点位置和旋转值的偏移,是ue的bug)

之前oculus和vive会自定义手柄的原点,现在OpenXR将其标准化,称之为grip position,即手柄上一个抓握时与手对齐的点,motioncontroller-》getworldposition拿到的也是OpenXR runtime 返回这个的grip position位置。

 

可以通过GetMotionControllerData拿到相关数据,除此之外还有一个aim pos,标识手柄上一个可以用于瞄准的点,可以用于传送或者瞄准。注意其中还有一些hand相关的数据,如hand key positions等,这个手部追踪功能目前只支持hololens。

可以新建一个motion controller,将其motion source改为aim,这样它就会自动追踪瞄准点,可以看见下图那个小球,就是oculus手柄的aim pos

01f9b757cc976821d687c08b0197770a.png 

VR Templete很好的一点是将逻辑清晰的分解了,将物体被抓握的能力集成在了一个grip component上,这样只要是一个actor具有grip component,并正确设置,那它就可以被抓握。同时输入等事件也通过蓝图接口去调用,如一个遥控器可以被按下,那这个遥控器actor继承VRInteraction BPI并实现press接口,玩家只管对握持的actor调用press而不需要关心其类型,也不需要关心是否有物体接收这个输入,很好的实现了观察者监听者模式。

VR扩展插件 Mordentral,示例游戏Robo Recall

UE4OpenXR Plugin

UE4OpenXR插件严格遵守OpenXR的生命周期顺序。

Ue4 openxr使用的所有openxr接口

xrAcquireSwapchainImage

xrApplyHapticFeedback

xrAttachSessionActionSets

xrBeginFrame

xrBeginSession

xrCreateAction

xrCreateActionSet

xrCreateActionSpace

xrCreateInstance

xrCreateReferenceSpace

xrCreateSession

xrCreateSwapchain

xrDestroyAction

xrDestroyActionSet

xrDestroyInstance

xrDestroySession

xrDestroySpace

xrDestroySwapchain

xrEndFrame

xrEndSession

xrEnumerateApiLayerProperties

xrEnumerateBoundSourcesForAction

xrEnumerateEnvironmentBlendModes

xrEnumerateInstanceExtensionProperties

xrEnumerateReferenceSpaces

xrEnumerateSwapchainFormats

xrEnumerateSwapchainImages

xrEnumerateViewConfigurations

xrEnumerateViewConfigurationViews

xrGetActionStateBoolean

xrGetActionStateFloat

xrGetActionStatePose

xrGetActionStateVector2f

xrGetCurrentInteractionProfile

xrGetInputSourceLocalizedName

xrGetInstanceProcAddr

xrGetInstanceProperties

xrGetReferenceSpaceBoundsRect

xrGetSystem

xrGetSystemProperties

xrGetViewConfigurationProperties

xrLocateSpace

xrLocateViews

xrPathToString

xrPollEvent

xrReleaseSwapchainImage

xrRequestExitSession

xrResultToString

xrStopHapticFeedback

xrStringToPath

xrStructureTypeToString

xrSuggestInteractionProfileBindings

xrSyncActions

xrWaitFrame

xrWaitSwapchainImage

Input

控制流程:

虚幻先绑定现有的控制器FOpenXRInput::BuildActions()

TMap<FString, FInteractionProfile> Profiles;

    Profiles.Add("SimpleController", FInteractionProfile(SimpleControllerPath, true));

    Profiles.Add("Daydream", FInteractionProfile(GetPath(Instance, "/interaction_profiles/google/daydream_controller"), false));

    Profiles.Add("Vive", FInteractionProfile(GetPath(Instance, "/interaction_profiles/htc/vive_controller"), true));

    Profiles.Add("MixedReality", FInteractionProfile(GetPath(Instance, "/interaction_profiles/microsoft/motion_controller"), true));

    Profiles.Add("OculusGo", FInteractionProfile(GetPath(Instance, "/interaction_profiles/oculus/go_controller"), false));

    Profiles.Add("OculusTouch", FInteractionProfile(GetPath(Instance, "/interaction_profiles/oculus/touch_controller"), true));

    Profiles.Add("ValveIndex", FInteractionProfile(GetPath(Instance, "/interaction_profiles/valve/index_controller"), true));

以Oculus Touch Trigger键为例

名称

类型

KeyName

OculusTouch_Left_Trigger_Axis

FName

根据下标将这个键值分为4段,先检测ue是否支持v[0] eg.OculusTouch

然后根据"/user/hand/" + v[1] eg./user/hand/left 拿到toplevel

定义Identifier 为v[2] eg.trigger Path += Identifier /user/hand/left/trigger

定义Component为v[3] eg.axis 对Path做相应变换,最后拿到path /user/hand/left/trigger/value

然后调用XrActionSuggestedBinding传入xractionhandle 和path 进行绑定

  • input模块在每帧tick时调用xrSyncActions更新输入
  • 按键信息接收是在FOpenXRInputPlugin::FOpenXRInput::SendControllerEvents()中通过xrGetCurrentInteractionProfile拿到控制器信息再反向映射回到引擎中
  • HMD位置则在openXRHMD中通过xrLocateSpace 更新,同时通过xrLocateSpace的返回值和标志位XR_SPACE_LOCATION_ORIENTATION_TRACKED_BITXR_SPACE_LOCATION_POSITION_TRACKED_BIT判定设备是否处于跟踪状态
  • 在input中 通过xrStopHapticFeedbackxrApplyHapticFeedback控制震动
  • 在UE4的OpenXR content资源文件夹中有各厂商手柄的模型

 

pico手柄模型:

 

Oculus OpenXR Extension Plugin
96fd849873926d1079f1ab563ecddbf3.png

UE4 的OpenXR Extension扩展框架主要是继承IOpenXRExtensionPlugin

列出一些Oculus有做修改以及比较重要的接口

主要的核心是重写了GetCustomLoader以加载Oculus 的loader

还可以重写GetInteractionProfileAddActions去扩展设备和输入按键

对于loader,ue会先去加载extension->getcustomloader,加载找到的第一个loader,如果没有extension,会去加载默认的loader。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐