美文网首页
Hololens开发手记 - 移动全息对象(Manipulati

Hololens开发手记 - 移动全息对象(Manipulati

作者: Zhansongtao | 来源:发表于2016-11-21 22:21 被阅读299次

    本文将以官方案例来说明如何实现移动全息对象操作(211 - chapter4)。此案例主要涉及到了语音、手势识别。

    实现思路:

    • 通过添加的关键字来初始化KeywordRecognizer;
    • 创建一个GestureRecognizer用于实现Manipulation Holographic;
    • 通过语音识别调用对应的函数操作实现选择不同的GestureRecognizer;
    • 通过不同的手势识别操作来对应地向Gaze射线凝视的物体发送消息实现操作;

    以MSDN上官网的demo为例:

    Paste_Image.png

    首先可以创建一个空物体来管理相关的Gaze、Hand、Gesture相关操作。在这里我们将对全息对象的管理脚本(也就是包含语音操作命令)也挂载在此空物体Manager上。

    语音输入 Voice Command


    1. 声明一个KeywordRecognizer ;
    2. 声明一个Dictionary<string, KeywordAction> keywordCollection用于保存关键字和对应的关键字函数;
    3. 在Start()函数中进行添加语音关键字;
    4. 在Start()函数中由添加的关键字字典keywordCollection进行对KeywordRecognizer 初始化并开始关键字识别;
    5. 对关键字对应的操作函数进行编写。此案例中为MoveAstronautCommand函数,主要实现将GestureManager.cs脚本中的不同的GestureRecognizer进行切换;
    **AstronautManager.cs**
    
    using HoloToolkit;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.Windows.Speech;
    
    public class AstronautManager : Singleton<AstronautManager>
    {
        // KeywordRecognizer object.
        KeywordRecognizer keywordRecognizer;
    
        // Defines which function to call when a keyword is recognized.
        delegate void KeywordAction(PhraseRecognizedEventArgs args);
        Dictionary<string, KeywordAction> keywordCollection;
    
        void Start()
        {
            keywordCollection = new Dictionary<string, KeywordAction>();
    
            // Add keyword to start manipulation.
            keywordCollection.Add("Move Astronaut", MoveAstronautCommand); 
    
            // Initialize KeywordRecognizer with the previously added keywords.
            keywordRecognizer = new KeywordRecognizer(keywordCollection.Keys.ToArray());
            keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
            keywordRecognizer.Start();
        }
    
        private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
        {
            KeywordAction keywordAction;
    
            if (keywordCollection.TryGetValue(args.text, out keywordAction))
            {
                keywordAction.Invoke(args);
            }
        }
    
        private void MoveAstronautCommand(PhraseRecognizedEventArgs args)
        {
            GestureManager.Instance.Transition(GestureManager.Instance.ManipulationRecognizer);
        }
    
        void OnDestroy()
        {
            keywordRecognizer.Dispose();
        }
    
    }
    

    手势输入 Gesture Input


    手势识别是HoloLens交互的重要输入方法之一。HoloLens提供了底层API和高层API,可以满足不同的手势定制需求。底层API能够获取手的位置和速度信息,高层API则借助手势识别器来识别预设的手势(包括,单击、双击、长按、平移等等)。本部分主要是高级API使用,通过输入源来识别手势。

    只需要很少的步骤就能使用GestureRecognizer集成手势识别:

    1. 创建GestureRecognizer实例
    2. 注册指定的手势类型
    3. 订阅手势事件
    4. 开始手势识别
    **GestureManager.cs**
    
    using HoloToolkit;
    using UnityEngine;
    using UnityEngine.VR.WSA.Input;
    
    public class GestureManager : Singleton<GestureManager>
    {
        // Manipulation gesture recognizer.
        public GestureRecognizer ManipulationRecognizer { get; private set; }
    
        // Currently active gesture recognizer.
        //此脚本原先有多个GestureManager ,因此由此代表当前激活的GestureManager 
        public GestureRecognizer ActiveRecognizer { get; private set; }
    
        public bool IsManipulating { get; private set; }
    
        public Vector3 ManipulationPosition { get; private set; }
    
        void Awake()
        {
           
            // Instantiate the ManipulationRecognizer.
            ManipulationRecognizer = new GestureRecognizer();
    
            // Add the ManipulationTranslate GestureSetting to the ManipulationRecognizer's RecognizableGestures.
            ManipulationRecognizer.SetRecognizableGestures(
                GestureSettings.ManipulationTranslate);
    
            // Register for the Manipulation events on the ManipulationRecognizer.
            ManipulationRecognizer.ManipulationStartedEvent += ManipulationRecognizer_ManipulationStartedEvent;
            ManipulationRecognizer.ManipulationUpdatedEvent += ManipulationRecognizer_ManipulationUpdatedEvent;
            ManipulationRecognizer.ManipulationCompletedEvent += ManipulationRecognizer_ManipulationCompletedEvent;
            ManipulationRecognizer.ManipulationCanceledEvent += ManipulationRecognizer_ManipulationCanceledEvent;
    
        }
    
        void OnDestroy()
        {
            // Unregister the Manipulation events on the ManipulationRecognizer.
            ManipulationRecognizer.ManipulationStartedEvent -= ManipulationRecognizer_ManipulationStartedEvent;
            ManipulationRecognizer.ManipulationUpdatedEvent -= ManipulationRecognizer_ManipulationUpdatedEvent;
            ManipulationRecognizer.ManipulationCompletedEvent -= ManipulationRecognizer_ManipulationCompletedEvent;
            ManipulationRecognizer.ManipulationCanceledEvent -= ManipulationRecognizer_ManipulationCanceledEvent;
        }
    
        /// <summary>
        /// Transition to a new GestureRecognizer.
        /// </summary>
        /// <param name="newRecognizer">The GestureRecognizer to transition to.</param>
        public void Transition(GestureRecognizer newRecognizer)     //切换此脚本中的两个不同功能的手势识别
        {
            if (newRecognizer == null)      //切换手势识别必须指定一个Recognizer
            {
                return;
            }
    
            if (ActiveRecognizer != null)
            {
                if (ActiveRecognizer == newRecognizer)      //如果切换的新的手势识别是现在正激活的手势识别,就说明没必要切换,直接return
                {
                    return;
                }
    
                ActiveRecognizer.CancelGestures();
                ActiveRecognizer.StopCapturingGestures();
            }
    
            newRecognizer.StartCapturingGestures();          //此脚本中的两个手势识别都是由此语句激活开始的
            ActiveRecognizer = newRecognizer;
        }
    
        private void ManipulationRecognizer_ManipulationStartedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
        {
            if (HandsManager.Instance.FocusedGameObject != null)
            {
                IsManipulating = true;
    
                ManipulationPosition = position;
    
                //HandsManager.Instance.FocusedGameObject追究到下面就是Gaze射线凝视的对象
                HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationStart", position);
            }
        }
    
        private void ManipulationRecognizer_ManipulationUpdatedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
        {
            if (HandsManager.Instance.FocusedGameObject != null)
            {
                IsManipulating = true;
    
                ManipulationPosition = position;
    
                HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationUpdate", position);
            }
        }
    
        private void ManipulationRecognizer_ManipulationCompletedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
        {
            IsManipulating = false;
        }
    
        private void ManipulationRecognizer_ManipulationCanceledEvent(InteractionSourceKind source, Vector3 position, Ray ray)
        {
            IsManipulating = false;
        }
    
    }
    

    此脚本中在订阅的手势事件中对Gaze凝视的对象进行SendMessageUpwards发送消息:

    • ManipulationRecognizer_ManipulationStartedEvent中对Gaze凝视的对象发送的是PerformManipulationStart函数;
    • ManipulationRecognizer_ManipulationUpdatedEvent中对Gaze凝视的对象发送的是PerformManipulationUpdate函数;

    Holographic Action 对象函数动作


    **GestureAction**
    
    using UnityEngine;
    
    /// <summary>
    /// GestureAction performs custom actions based on 
    /// which gesture is being performed.
    /// </summary>
    public class GestureAction : MonoBehaviour
    {
        private Vector3 manipulationPreviousPosition;
    
        void PerformManipulationStart(Vector3 position)
        {
            manipulationPreviousPosition = position;
        }
    
        void PerformManipulationUpdate(Vector3 position)
        {
            if (GestureManager.Instance.IsManipulating)
            {
                Vector3 moveVector = Vector3.zero;
                //Calculate the moveVector as position - manipulationPreviousPosition.
                moveVector = position - manipulationPreviousPosition;
    
                //Update the manipulationPreviousPosition with the current position.
                manipulationPreviousPosition = position;
    
                // Increment this transform's position by the moveVector.
                transform.position += moveVector;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Hololens开发手记 - 移动全息对象(Manipulati

          本文链接:https://www.haomeiwen.com/subject/exaupttx.html