zoukankan      html  css  js  c++  java
  • HoloLens开发手记

    凝视是HoloLens首要输入方式,形式功能类似于桌面系统的光标,用于选择操作全息对象。然而在Unity中并没有明确的Gaze API或者组件。

    实现Gaze Implementing Gaze


     

    概念上来说,Gaze是通过用户头部两眼之间发出一条向前方的射线来实现的,射线可以识别它所碰撞的物体。在Unity中,使用Main Camera来表示用户头部的位置和朝向。准确的说,是指 UnityEngine.Camera.main.transform.forward 和 UnityEngine.Camera.main.transform.position.

    调用 Physics.RayCast 发出射线后可以得到 RaycastHit 结果,该结果包含了碰撞点的3D位置参数和碰撞对象。

    实现Gaze的例子

    void Update()
    {
           RaycastHit hitInfo;
           if (Physics.Raycast(
                   Camera.main.transform.position,
                   Camera.main.transform.forward,
                   out hitInfo,
                   20.0f,
                   Physics.DefaultRaycastLayers))
           {
               // 如果射线成功击中物体
               // hitInfo.point代表了射线碰撞的位置
               // hitInfo.collider.gameObject代表了射线注视的全息对象
           }
    }

    最佳做法

    在使用Gaze的时候,尽量避免每个物体都发出凝视射线,而是使用单例对象来管理凝视射线和其结果。

    可视化凝视 Visualizing Gaze


     

    就像PC使用鼠标来选中和交互图标一样,你可以为凝视也实现一个指针来更好的代表用户的凝视。

    可视化凝视的例子

    可以参考或直接使用HoloToolkit-Unity项目中的GazeManager.cs和预制的各种指针资源,包括Cursor.prefab 和 CursorWithFeedback.prefab 等。

    // Copyright (c) Microsoft Corporation. All rights reserved.
    // Licensed under the MIT License. See LICENSE in the project root for license information.
    
    using UnityEngine;
    using UnityEngine.VR.WSA;
    
    namespace HoloToolkit.Unity
    {
        /// <summary>
        /// GazeManager determines the location of the user's gaze, hit position and normals.
        /// </summary>
        public partial class GazeManager : Singleton<GazeManager>
        {
            [Tooltip("Maximum gaze distance, in meters, for calculating a hit.")]
            public float MaxGazeDistance = 15.0f;
    
            [Tooltip("Select the layers raycast should target.")]
            public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers;
    
            /// <summary>
            /// Physics.Raycast result is true if it hits a hologram.
            /// </summary>
            public bool Hit { get; private set; }
    
            /// <summary>
            /// HitInfo property gives access
            /// to RaycastHit public members.
            /// </summary>
            public RaycastHit HitInfo { get; private set; }
    
            /// <summary>
            /// Position of the intersection of the user's gaze and the holograms in the scene.
            /// </summary>
            public Vector3 Position { get; private set; }
    
            /// <summary>
            /// RaycastHit Normal direction.
            /// </summary>
            public Vector3 Normal { get; private set; }
    
            [Tooltip("Checking enables SetFocusPointForFrame to set the stabilization plane.")]
            public bool SetStabilizationPlane = true;
            [Tooltip("Lerp speed when moving focus point closer.")]
            public float LerpStabilizationPlanePowerCloser = 4.0f;
            [Tooltip("Lerp speed when moving focus point farther away.")]
            public float LerpStabilizationPlanePowerFarther = 7.0f;
    
            private Vector3 gazeOrigin;
            private Vector3 gazeDirection;
            private float lastHitDistance = 15.0f;
            private GameObject focusedObject;
    
            private void Update()
            {
                gazeOrigin = Camera.main.transform.position;
                gazeDirection = Camera.main.transform.forward;
    
                UpdateRaycast();
    
                UpdateStabilizationPlane();
            }
    
            /// <summary>
            /// Calculates the Raycast hit position and normal.
            /// </summary>
            private void UpdateRaycast()
            {
                // Get the raycast hit information from Unity's physics system.
                RaycastHit hitInfo;
                Hit = Physics.Raycast(gazeOrigin,
                               gazeDirection,
                               out hitInfo,
                               MaxGazeDistance,
                               RaycastLayerMask);
    
                GameObject oldFocusedObject = focusedObject;
                // Update the HitInfo property so other classes can use this hit information.
                HitInfo = hitInfo;
    
                if (Hit)
                {
                    // If the raycast hits a hologram, set the position and normal to match the intersection point.
                    Position = hitInfo.point;
                    Normal = hitInfo.normal;
                    lastHitDistance = hitInfo.distance;
                    focusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // If the raycast does not hit a hologram, default the position to last hit distance in front of the user,
                    // and the normal to face the user.
                    Position = gazeOrigin + (gazeDirection * lastHitDistance);
                    Normal = gazeDirection;
                    focusedObject = null;
                }
    
                // Check if the currently hit object has changed
                if (oldFocusedObject != focusedObject)
                {
                    if (oldFocusedObject != null)
                    {
                        oldFocusedObject.SendMessage("OnGazeLeave", SendMessageOptions.DontRequireReceiver);
                    }
                    if (focusedObject != null)
                    {
                        focusedObject.SendMessage("OnGazeEnter", SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
    
            /// <summary>
            /// Updates the focus point for every frame.
            /// </summary>
            private void UpdateStabilizationPlane()
            {
                if (SetStabilizationPlane)
                {
                    // Calculate the delta between camera's position and current hit position.
                    float focusPointDistance = (gazeOrigin - Position).magnitude;
                    float lerpPower = focusPointDistance > lastHitDistance
                        ? LerpStabilizationPlanePowerFarther
                        : LerpStabilizationPlanePowerCloser;
    
                    // Smoothly move the focus point from previous hit position to new position.
                    lastHitDistance = Mathf.Lerp(lastHitDistance, focusPointDistance, lerpPower * Time.deltaTime);
    
                    Vector3 newFocusPointPosition = gazeOrigin + (gazeDirection * lastHitDistance);
    
                    HolographicSettings.SetFocusPointForFrame(newFocusPointPosition, -gazeDirection);
                }
            }
        }
    }
  • 相关阅读:
    各种语言语法大全
    【mysql】SQL常用指令
    【JdbcTemplete】JdbcTemplete代码详解--模板方法详解
    【Spring-AOP-1】AOP相关概念
    【设计模式】命令行模式
    【设计模式】单件模式(Singleton)--各类单件模式的比较
    【设计模式】工厂方法模式(Factory Method)
    【设计模式】装饰者模式(Decorator)
    【并发编程】延时初始化
    【并发编程】AQS学习
  • 原文地址:https://www.cnblogs.com/mantgh/p/5489060.html
Copyright © 2011-2022 走看看