Hololens 开发笔记(5)——Gaze

编程入门 行业动态 更新时间:2024-10-07 02:32:20

Hololens 开发<a href=https://www.elefans.com/category/jswz/34/1770047.html style=笔记(5)——Gaze"/>

Hololens 开发笔记(5)——Gaze

在前面我们粗略了解了 Hololens,包括 Hello WorldMRTKWindows Device Portal坐标系统

下面开始 Hololens 基础部分的学习,包括 GazeGesureVoiceAudio Souce 等。本篇文章来学习 Hololens 的基础开发之凝视操作。

源码地址:

创建一个新的 Unity 项目 GazeDemo,导入 MRTK 工具包,并将项目应用为 MR 项目。

删除掉默认的相机,添加 MRTK 的 HoloLensCamera 到 Hierarchy 中。添加 MRTK 中的 CursorWithFeedback 到 Hierarchy 中。

一、凝视操作

从 MRTK 中拖拽 InputManager 到 Hierarchy 中。这是一个十分重要的 Manager,它将管理我们的凝视等输入事件。

设置 InputManager 的 SimpleSinglePointerSelector 脚本的 Cursor 属性为添加的 CursorWithFeedback。

随后添加一个 Cube 到 Hierarchy 中,来实现凝视 Cube 5 秒将其隐藏掉的效果。

新建脚本 CubeCommand,并将其添加到 Cube 上。

using UnityEngine;
using HoloToolkit.Unity.InputModule;
using System;public class CubeCommand : MonoBehaviour, IFocusable {// 延迟多少秒后触发public double duration = 5.0;private DateTime? startDate;void Update () {if (startDate.HasValue){TimeSpan span = DateTime.Now - startDate.Value;if (span.TotalSeconds > duration){HideCube();}}}void HideCube(){startDate = null;gameObject.GetComponent<MeshRenderer>().enabled = false;}public void OnFocusEnter(){startDate = DateTime.Now;}public void OnFocusExit(){startDate = null;if (!gameObject.GetComponent<MeshRenderer>().enabled){gameObject.GetComponent<MeshRenderer>().enabled = true;}}
}

运行程序,当我们将 Cursor 停留 Cube 5秒后,Cube 消失,当我们移开 Cursor 时,Cube 恢复。

总结下代码:

  1. 导包:using HoloToolkit.Unity.InputModule;
  2. 实现接口 IFocusable,当 Cursor 进入物体时,调用 OnFocusEnter() 方法,当 Cursor 移出物体时,调用 OnFocusExit() 方法。
  3. Update() 方法中计算凝视的时长,当达到 duration 时,将物体隐藏。

二、Directional indicator

假如我们为 Cube 添加了方向指示器(Directional indicator),当我们的视野中看不见该 Cube 时,方向指示器会指示出它的位置。实现步骤如下:

  1. 为 Cube 添加 MRTK 包中的 DirectionIndicator.cs 脚本。
  2. 选中该脚本,设置 Cursor 属性为 Hierarchy 中的 CursorWithFeedback;设置DirectionIndicatorObject 属性为 MRTK 包中的 HeadsUpDirectionIndicatorPointer

具体属性含义如下:

属性名含义
Cursor该物体在场景中被当作光标,方向指示器会显示在这个物体旁边
DirectionIndicatorObject方向指示器物体,该物体会一直指向附加该脚本的对象。
DirectionIndicatorColor方向指示器的颜色(方向指示器材质里的Shader必须要有“_TintColor”属性,否则颜色不会变)
VisibilitySafeFactor范围[-0.3,0.3] ,当物体在摄像机视锥的某个百分比范围中,方向指示器才会显示。(例如此值为0时,当物体完全离开摄像机视锥之后方向指示器才会显示;此值为0.1时,物体在视锥范围的90%之外,方向指示器才会显示;此值为-0.1时,物体在视锥范围的110%之外 ,方向指示器才会显示)
MetersFromCursor方向指示器从原中心到它面向方向(forward)的一个偏移值。

运行程序,你会发现一个巨大的三角箭头指示着 Cube 的方向:

MRTK 默认提供的 DirectionIndicatorObject 实在是太丑了。我这里使用 MR Input 210: Gaze Chapter 4 - Directional indicator 中提供的方向指示器,效果如下:

三、Billboarding

如果为 Cube 添加了广告牌(Billboarding)效果,他就会永远的面朝你,即使你尝试走到它的后面(应用在 Cube 上没啥意义,可以使用 Text 来测试)。

为一个 gameObject 添加广告牌效果十分简单,只要为其添加 MRTK 包下的 Billboard.cs 脚本,并设置它的 PivotAxis 属性为 Y 即可,即绕着 Y 轴实现广告牌。

四、Tag-Along

不知道你还记不记得 Hololens 的 Bloom 手势呼出主菜单的效果,主菜单是跟随你移动并且使终面朝你。这就是广告牌 + 平滑追踪的联合实现。

为要平滑追踪(Tag-Along)的物体添加 MRTK 包下的 Tagalong.cs 脚本即可。

这里我添加了一个 3D Text,并为其添加了广告牌和平滑追踪的效果,运行效果如下:

五、Cursor 底层实现

代码来源于:MR Basics 101: Complete project with device: Chapter 2 - Gaze

我们可以看下 Cursor 的效果是如何实现的,创建一个 Cursor ,它其实就是一个圆圈,为它附加脚本 WorldCursor

using UnityEngine;public class WorldCursor : MonoBehaviour
{private MeshRenderer meshRenderer;// Use this for initializationvoid Start(){// Grab the mesh renderer that's on the same object as this script.meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>();}// Update is called once per framevoid Update(){// Do a raycast into the world based on the user's// head position and orientation.var headPosition = Camera.main.transform.position;var gazeDirection = Camera.main.transform.forward;RaycastHit hitInfo;if (Physics.Raycast(headPosition, gazeDirection, out hitInfo)){// If the raycast hit a hologram...// Display the cursor mesh.meshRenderer.enabled = true;// Move the cursor to the point where the raycast hit.this.transform.position = hitInfo.point;// Rotate the cursor to hug the surface of the hologram.this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);}else{// If the raycast did not hit a hologram, hide the cursor mesh.meshRenderer.enabled = false;}}
}

Unity 是没有明确的 Gaze 的 API,在 Hololens 中,是通过射线检测来实现的。当视线接触到了碰撞物时,展示出一个⭕;当视线没有接触到碰撞物时,隐藏⭕。

(1)获取其及其子对象中的 MeshRenderer

meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>();
  • GetComponent():获取对象中指定类型的控件(脚本)
  • GetComponentInChildren():获取对象的子对象中指定类型的控件,如果父对象中有,优先获取父对象的
  • GetComponents()、GetComponentsInChildren():返回数组

Mesh Filter(网格过滤器)用于从资源中读取网格信息(Mesh) ,读取信息之后可以传递给 Mesh Renderer(网格渲染器 ),将接受到的网格信息渲染出来。

(2)获取主相机的位置和朝向

var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;

(3)调用射线检测函数,从 headPosition 射向 gazeDirection ,当碰撞到物体时,返回true,并将碰撞信息放入 hitInfo 。

Physics.Raycast(headPosition, gazeDirection, out hitInfo)

(4)如果碰撞到物体,显示 meshRenderer,并将位置移动到碰撞的位置。将⭕旋转,从(0,1,0)到碰撞点的法线。

meshRenderer.enabled = true;
this.transform.position = hitInfo.point;
this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);

(5)如果没有碰撞到物体,隐藏 meshRenderer。

更多推荐

Hololens 开发笔记(5)——Gaze

本文发布于:2024-02-14 07:23:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1762326.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:笔记   Hololens   Gaze

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!