• Hololens开发笔记之Gaze凝视射线


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

    概念上来说,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的时候,尽量避免每个物体都发出凝视射线,而是使用单例对象来管理凝视射线和其结果。

    可视化凝视的具体例子


     

    可以直接使用HoloToolkit中的GazeManager.cs脚本来实现凝视射线。

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

    1、添加GazeManager.cs

    点击“ Create Empty” 创建一个空游戏对象,并将其命名为 Manager,为 Manager对象添加核心脚本组件GazeManager.cs

    // 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; }  
      
            /// <summary>  
            /// Object currently being focused on.  
            /// </summary>  
            public GameObject FocusedObject { 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 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>  
            /// Adds the stabilization plane modifier if it's enabled and if it doesn't exist yet.  
            /// </summary>  
            private void UpdateStabilizationPlane()  
            {  
                // We want to use the stabilization logic.  
                if (SetStabilizationPlane)  
                {  
                    // Check if it exists in the scene.  
                    if (StabilizationPlaneModifier.Instance == null)  
                    {  
                        // If not, add it to us.  
                        gameObject.AddComponent<StabilizationPlaneModifier>();  
                    }  
                }  
      
                if (StabilizationPlaneModifier.Instance)  
                {  
                    StabilizationPlaneModifier.Instance.SetStabilizationPlane = SetStabilizationPlane;  
                }  
            }  
        }  
    }  

    2、创建一个新的游戏对象Cube,用来测试凝视效果

    3、添加Cursor

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

    从 HoloToolkit/Input/Prefabs/ 目录下拖拽 Cursor Prefab 组件到场景中。这样当凝视在全息对象时,其表面会出现一个蓝色的光圈,表示当前凝视该对象,当射线离开该游戏对象时,Cursor变成一个点光源,以此来区分是否凝视游戏对象。

    可以查看到Cursor中存在两个光标对象,分别是凝视在对象上及离开光息对象时分别显示的光标

    CursorManager.cs

    // Copyright (c) Microsoft Corporation. All rights reserved.  
    // Licensed under the MIT License. See LICENSE in the project root for license information.  
      
    using HoloToolkit.Unity;  
    using UnityEngine;  
      
    /// <summary>  
    /// CursorManager class takes Cursor GameObjects.  
    /// One that is on Holograms and another off Holograms.  
    /// 1. Shows the appropriate Cursor when a Hologram is hit.  
    /// 2. Places the appropriate Cursor at the hit position.  
    /// 3. Matches the Cursor normal to the hit surface.  
    /// </summary>  
    public partial class CursorManager : Singleton<CursorManager>  
    {  
        //凝视射线在全息对象上时显示的光标对象  
        [Tooltip("Drag the Cursor object to show when it hits a hologram.")]  
        public GameObject CursorOnHolograms;  
        //凝视射线离开全息对象时显示的光标对象  
        [Tooltip("Drag the Cursor object to show when it does not hit a hologram.")]  
        public GameObject CursorOffHolograms;  
      
        [Tooltip("Distance, in meters, to offset the cursor from the collision point.")]  
        public float DistanceFromCollision = 0.01f;  
      
        void Awake()  
        {  
            //当未设定光标对象时直接返回  
            if (CursorOnHolograms == null || CursorOffHolograms == null)  
            {  
                return;  
            }  
              
            // Hide the Cursors to begin with.  
            CursorOnHolograms.SetActive(false);  
            CursorOffHolograms.SetActive(false);  
        }  
      
        void LateUpdate()  
        {  
            if (GazeManager.Instance == null || CursorOnHolograms == null || CursorOffHolograms == null)  
            {  
                return;  
            }  
            //当凝视射线在全息对象上及离开全息对象时,分别显示不同的光标对象,以此来进行区分  
            if (GazeManager.Instance.Hit)  
            {  
                CursorOnHolograms.SetActive(true);  
                CursorOffHolograms.SetActive(false);  
            }  
            else  
            {  
                CursorOffHolograms.SetActive(true);  
                CursorOnHolograms.SetActive(false);  
            }  
      
            //计算并安置光标  
            // Place the cursor at the calculated position.  
            this.gameObject.transform.position = GazeManager.Instance.Position + GazeManager.Instance.Normal * DistanceFromCollision;  
      
            // Orient the cursor to match the surface being gazed at.  
            gameObject.transform.up = GazeManager.Instance.Normal;  
        }  
    }  

    4、运行测试

    当凝视射线在Cube上时,出现蓝色的光圈,表示当前凝视的点在该位置

    当凝视射线离开Cube时,光标显示为一个点光源

  • 相关阅读:
    SQL调用另一台服务器的表及存储过程(SQL函数openrowset()的使用以及相关问题处理)
    解决SQL Server 阻止了对组件Ad Hoc Distributed Queries访问的方法
    sql server exec 参数的传递
    c#修改webservice 的地址和端口(修改配置文件)
    JS转换HTML转义符,编码及解码
    nginx使用ssl模块配置支持HTTPS访问,腾讯云申请免费证书
    thinkcmf 相关
    ThinkJS 开发node后端 使用 简介
    linux复制指定目录下的全部文件到另一个目录中
    谷歌地图,国内使用Google Maps JavaScript API,国外业务
  • 原文地址:https://www.cnblogs.com/unity3ds/p/5866136.html
Copyright © 2020-2023  润新知