HTC VIVE开发教程(五)

前面几节我们了解了SteamVR的基本原理,现在可以进行实战开发了。但在进行VR开发前,我还要先介绍一套强大的VR开发工具——VRTK

在进行VIVE开发时,我们经常要用手柄进行一些操作,比如监听按键响应,通过手柄触摸板进行移动,抓取物体等等。这些交互功能实现起来其实不复杂,但是如果我们自己一个个去写又比较麻烦,为了避免重复造轮子,github上便有了vrtk这套SteamVR开发的工具集。

获取vrtk有两种方法
①gitHub的地址:https://github.com/thestonefox/VRTK
②在AssertStore中导入VRTK插件包
HTC VIVE开发教程(五)_第1张图片

但是当我们把VRTK下载下来之后就头疼,这个工具集非常的庞大,由于开发人员也有很多,上面有很多代码甚至是冲突的,也没有一套很详细的说明文档,用起来非常不方便。

所以我们是没必要将这套VR开发工具集全部下载下来的,我们只需要选择里面我们需要的工具类下载下来使用就好了。我选择了下图中几种比较常用的工具类,并且选择几个类来进行源码分析。

HTC VIVE开发教程(五)_第2张图片

第一个常用的工具类是VRTK_ControllerEvents,我们只需要把这个脚本挂到手柄控制器上,就能方便的获取到所有的按键状态。

在介绍这个类之前,我前讲讲我们是如何在SteamVR中获取按键并且响应的。HTC VIVE的手柄如下

HTC VIVE开发教程(五)_第3张图片

HTC手柄的按键数据结构如下

    public class ButtonMask
    {
        public const ulong System;          // 保留按键
        public const ulong ApplicationMenu  //菜单按钮,对应图中的①
        public const ulong Grip             //手柄按钮,对应图中的⑧
        public const ulong Axis0            
        public const ulong Axis1            
        public const ulong Axis2        
        public const ulong Axis3            
        public const ulong Axis4            
        public const ulong Touchpad         //触控板,对应图中的②
        public const ulong Trigger          //扳机按钮,对应图中的⑦
    }

想要获取手柄的按键状态,得先拿到手柄的索引,获取索引有两种方法

/*IVRSystem是SteamVR SDK中的一个接口,可以通过OpenVR.System或者SteamVR.hmd来访问,比如获取左手的索引*/
IVRSystem.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole unDeviceType)


/*获取左手柄的索引*/
uint leftIndex
=OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);

/*获取右手柄的索引*/
uint rightIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand)

/*SteamVR_TrackedObject是挂载在手柄和头显上用来跟踪位置的脚本,在之前的文章中我讲过,这个脚本中记录了当前设备的索引*/
uint index=SteamVR_TrackedObject.index;

获取到手柄的索引后,我们就可以在update中通过下面的代码来监听按键了

/*这里的index就是我们前面获取的设备索引*/
var device = SteamVR_Controller.Input((int)index);

/*
这里输入我们之前提到过的按键数据结构
SteamVR_Controller.ButtonMask.Trigger 对应扳机键
SteamVR_Controller.ButtonMask.ApplicationMenu 对应菜单键
……
*/
device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)

知道了如何监听手柄的按键响应后,我们在来看看这个VRTK_ControllerEvents这个手柄控制工具类

脚本的开头定义了一系列的委托,通过代码可以看到,都是手柄的交互委托,我们只需要注册这些委托事件的回调,就能很方便的获取我们想要监听的按键操作。

HTC VIVE开发教程(五)_第4张图片

我们在来看看它的实现代码

void Update()
{
    /*因为这个脚本是挂载在手柄下的,所以直接通过SteamVR_TrackedObject来获取索引,
    trackedController就是SteamVR_TrackedObject脚本*/ 
    controllerIndex = (uint)trackedController.index;
    device = SteamVR_Controller.Input((int)controllerIndex);

    /*对于轴设备,则提供了一个GetAxis函数,返回值是一个Vector对象,分别提供X、Y两个维度的轴数据(扳机键
    只有X轴这个维度)*/
    Vector2 currentTriggerAxis=device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
    Vector2 currentTouchpadAxis = device.GetAxis();


    /*
    在Device里面为每个按键定义了三种状态:Press、PressDown和PressUp。
    分别通过GetPress、表示按键是否松开。
    对于触摸设备,也定义了GetTouch、GetTouchDown和GetTouchUp三个函数分别获取是否在触摸设备上按下、持续按下及松开。
    */

    //监听扳机键
    if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger))
    {
        OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));
        EmitAlias(ButtonAlias.Trigger, true, currentTriggerAxis.x, ref triggerPressed);
    }
    else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger))
    {
        OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));
        EmitAlias(ButtonAlias.Trigger, false, 0f, ref triggerPressed);
    }
    else
    {
        if (Vector2ShallowEquals(triggerAxis, currentTriggerAxis))
        {
        triggerAxisChanged = false;
        }
        else
        {
        OnTriggerAxisChanged(SetButtonEvent(ref triggerAxisChanged, true, currentTriggerAxis.x));
        }
    }

    //监听菜单键
    if (device.GetTouchDown(SteamVR_Controller.ButtonMask.ApplicationMenu))
    {
        OnApplicationMenuPressed(SetButtonEvent(ref applicationMenuPressed, true, 1f));
        EmitAlias(ButtonAlias.Application_Menu, true, 1f, ref applicationMenuPressed);
    }
        else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.ApplicationMenu))
    {

        OnApplicationMenuReleased(SetButtonEvent(ref applicationMenuPressed, false, 0f));
        EmitAlias(ButtonAlias.Application_Menu, false, 0f, ref applicationMenuPressed);
    }

    //监听抓取键
    if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip))
    {
        OnGripPressed(SetButtonEvent(ref gripPressed, true, 1f));
        EmitAlias(ButtonAlias.Grip, true, 1f, ref gripPressed);
    }
    else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Grip))
    {
       OnGripReleased(SetButtonEvent(ref gripPressed, false, 0f));
        EmitAlias(ButtonAlias.Grip, false, 0f, ref gripPressed);
    }

    //监听按压Touchpad
    if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
    {
        OnTouchpadPressed(SetButtonEvent(ref touchpadPressed, true, 1f));
        EmitAlias(ButtonAlias.Touchpad_Press, true, 1f, ref touchpadPressed);
    }
    else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
    {
        OnTouchpadReleased(SetButtonEvent(ref touchpadPressed, false, 0f));
        EmitAlias(ButtonAlias.Touchpad_Press, false, 0f, ref touchpadPressed);
    }

    //监听触摸Touched
    if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))
    {
        OnTouchpadTouchStart(SetButtonEvent(ref touchpadTouched, true, 1f));
        EmitAlias(ButtonAlias.Touchpad_Touch, true, 1f, ref touchpadTouched);
    }
    else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
    {
        OnTouchpadTouchEnd(SetButtonEvent(ref touchpadTouched, false, 0f));
        EmitAlias(ButtonAlias.Touchpad_Touch, false, 0f, ref touchpadTouched);
    }
    else
    {
        if (Vector2ShallowEquals(touchpadAxis, currentTouchpadAxis))
        {
            touchpadAxisChanged = false;
        }
        else {
            OnTouchpadAxisChanged(SetButtonEvent(ref touchpadTouched, true, 1f));
            touchpadAxisChanged = true;
        }
    }

    //保存当前触摸板和扳机键的轴数据
    touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
    triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
}

到这里,我们已经了解了如何监听HTC VIVE的手柄按键,也知道了VRTK_ControllerEvents的这个工具类的实现代码,在后面的章节里,我将陆续分析其他几个常用工具类的源码。

你可能感兴趣的:(VR开发专栏)