设为首页收藏本站

微软Hololens全息现实网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

一键登录:

查看: 1036|回复: 1

Hololens官方教程精简版 - 07. Spatial mapping(空间映射)

  [复制链接]
发表于 2017-12-5 22:21:39 | 显示全部楼层 |阅读模式

本帖最后由 HoloLens全息现实网 于 2017-12-5 22:23 编辑 前言注意:本文已更新到5.5.1f1版本个人建议,学习Holograms 230之前,一定完成《Hololens官方教程精简版 - 02. Introduction with Device》的学习。本篇集中学习空间映射功能,完成以下目标:Chapter 1 - 空间扫描目标完成空间扫描替换三角...

本帖最后由 HoloLens全息现实网 于 2017-12-5 22:23 编辑

前言
注意:本文已更新到5.5.1f1版本
个人建议,学习Holograms 230之前,一定完成《Hololens官方教程精简版 - 02. Introduction with Device》的学习。
本篇集中学习空间映射功能,完成以下目标:
Chapter 1 - 空间扫描目标
  • 完成空间扫描
  • 替换三角面材质
实践
完成空间扫描
  • 请按照第一篇的教程,完成项目的创建。
  • 新建文件夹:”Assets/_Scenes/Holograms 230/”
  • 新建场景:”Assets/_Scenes/Holograms 230/Holograms 230.unity
  • 打开场景,删除默认的Main Camera
  • 将”Assets/HoloToolkit/Input/Prefabs/HololensCamera.prefab”添加到Hierarchy根级
  • 将”Assets/HoloToolkit/Input/Prefabs/InputManager.prefab”添加到Hierarchy根级
  • 将”Assets/HoloToolkit/Input/Prefabs/Cursor/DefaultCursor.prefab”添加到Hierarchy根级
  • 将”Assets/HoloToolkit/SpatialMapping/Prefabs/SpatialMapping.prefab”添加到Hierarchy根级
本节完成!
使用Hololens远程连接Unity进行调试,等待“一段时间”(这个一段时间,第一次可能很长……)。将会看到Hololens根据空间扫描结果,绘制了很多三角面。
替换三角面材质
  • 点击SpatialMapping
  • 找到Inspector面板中的Surface Material,替换为SpatialUnderstandingSurface
本节完成!
再次测试,会发现三角面的材质被替换。
Chapter 2 - 扫描结果处理目标
扫描结束后,用手势点击,将扫描结果转换为地板模型
实践
  • Hierarchy面板根级,新建空对象,重命名为:Controller
  • 点击Controller,在Inspector面板中点击Add Component,加入:Surface Meshes To Planes组件
  • 点击Surface Meshes To Planes组件属性Surface Plane Prefab右侧的圆钮,选择:SurfacePlane
  • 同第2步相同的方法,为Controller添加Remove Surface Vertices
  • 新建文件夹:”Assets/_Scenes/Holograms 230/Scripts/”
  • 新建脚本文件:”Assets/_Scenes/Holograms 230/Scripts/Controller230.cs“,并附加到Controller
  • 编辑脚本如下:
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using HoloToolkit.Unity;

    4. public class Controller230 : Singleton<Controller230> {

    5.     [Tooltip("扫描过多少秒开始转换")]
    6.     public float scanTime = 30.0f;

    7.     [Tooltip("扫描时使用的材质")]
    8.     public Material defaultMaterial;

    9.     [Tooltip("停止扫描所使用的材质")]
    10.     public Material secondaryMaterial;

    11.     [Tooltip("最小Plane实体数量")]
    12.     public uint minimumPlanes = 10;

    13.     /// <summary>
    14.     /// 判断是否正在处理Mesh
    15.     /// </summary>
    16.     private bool meshesProcessed = false;

    17.     private void Start()
    18.     {
    19.         // 设置空间扫描器的材质为默认材质
    20.         SpatialMappingManager.Instance.SetSurfaceMaterial(defaultMaterial);

    21.         // 网格转Plane实体完成后的事件监听
    22.         SurfaceMeshesToPlanes.Instance.MakePlanesComplete += SurfaceMeshesToPlanes_MakePlanesComplete;
    23.     }

    24.     private void Update()
    25.     {
    26.         if (!meshesProcessed)
    27.         {
    28.             if ((Time.time - SpatialMappingManager.Instance.StartTime) < scanTime)
    29.             {
    30.                 // 还未到指定扫描耗时,则跳过
    31.             }
    32.             else
    33.             {
    34.                 // 停止扫描器
    35.                 if (SpatialMappingManager.Instance.IsObserverRunning())
    36.                 {
    37.                     SpatialMappingManager.Instance.StopObserver();
    38.                 }

    39.                 // 开始将网格转换为Plane
    40.                 CreatePlanes();

    41.                 meshesProcessed = true;
    42.             }
    43.         }
    44.     }

    45.     private void SurfaceMeshesToPlanes_MakePlanesComplete(object source, System.EventArgs args)
    46.     {
    47.         // 获取转换后得到的Plane实体对象
    48.         List<GameObject> planes = new List<GameObject>();
    49.         planes = SurfaceMeshesToPlanes.Instance.GetActivePlanes(PlaneTypes.Wall | PlaneTypes.Floor | PlaneTypes.Table);

    50.         // 如果大于我们设置的最小Plane识别值,则对Plane做进一步处理
    51.         if (planes.Count >= minimumPlanes)
    52.         {
    53.             // 将与Plane实体重叠的顶点删除
    54.             RemoveVertices(SurfaceMeshesToPlanes.Instance.ActivePlanes);

    55.             // 扫描结束后,切换第二个材质,本例中使用了“剔除材质(使用了一个剔除Shader)”,即除了Plane外,其他的三角面将被隐藏
    56.             SpatialMappingManager.Instance.SetSurfaceMaterial(secondaryMaterial);
    57.         }
    58.         else
    59.         {
    60.             // 未达到最小Plane识别数,继续扫描
    61.             SpatialMappingManager.Instance.StartObserver();

    62.             meshesProcessed = false;
    63.         }
    64.     }

    65.     /// <summary>
    66.     /// 扫描网格转Plane实体
    67.     /// </summary>
    68.     private void CreatePlanes()
    69.     {
    70.         SurfaceMeshesToPlanes surfaceToPlanes = SurfaceMeshesToPlanes.Instance;
    71.         if (surfaceToPlanes != null && surfaceToPlanes.enabled)
    72.         {
    73.             surfaceToPlanes.MakePlanes();
    74.         }
    75.     }

    76.     /// <summary>
    77.     /// 移除与指定对象组重叠的顶点
    78.     /// </summary>
    79.     private void RemoveVertices(IEnumerable<GameObject> boundingObjects)
    80.     {
    81.         RemoveSurfaceVertices removeVerts = RemoveSurfaceVertices.Instance;
    82.         if (removeVerts != null && removeVerts.enabled)
    83.         {
    84.             removeVerts.RemoveSurfaceVerticesWithinBounds(boundingObjects);
    85.         }
    86.     }

    87.     protected override void OnDestroy()
    88.     {
    89.         if (SurfaceMeshesToPlanes.Instance != null)
    90.         {
    91.             SurfaceMeshesToPlanes.Instance.MakePlanesComplete -= SurfaceMeshesToPlanes_MakePlanesComplete;
    92.         }

    93.         base.OnDestroy();
    94.     }
    95. }
    复制代码

  • 意:5.5.1f1版本中,名称空间有所变化,大家可自行引入
  • 如下图设置各个组件:
    47.png

本节完成!
设备远程连接Unity进行调试,等待片刻,空间扫描的网格会转换为地板
说明
  • Surface Meshes To Planes脚本
    将扫描的网格转换为实体,在其Inspector面板中,找到Draw Planes属性,可以设置需要转换的类型,本例中设置了只转换Floor(地板),见上图标注青色的部分。
  • Remove Surface Vertices脚本
    把与实体重合的网格删除
Chapter 3 - 放置物体目标
将物体放置到地板上
实践
  • 根级创建一个Cube,设置如下:
    46.png

  • Cube添加Tap To Place脚本
  • Controller添加World Anchor Manager脚本
本节完成!
点击Cube后,Cube会随视线移动,但只能贴合到已经创建的地板上。
再次点击Cube进行放置操作。同时,系统会记录下Cube的空间位置。下次启动时,Cube回还原到该位置。
说明
  • World Anchor Manager
    用来管理全息空间的物体锚点
    使用WorldAnchorManager.Instance.AttachAnchor(GameObject gameObjectToAnchor, string anchorName),即可为物体添加全息空间锚点信息,从而“固化”物体的空间位置(混合现实的显著特征之一)。
  • Tap To Place
    放置物体(包含空间模型的检测)。核心功能就两个:
    • 放置过程中,使用Raycast方法,实时设置物体的位置
    • 放置完成后,使用上面提到的AttachAnchor(...)来”固化”物体位置

Chapter 4 - 空间遮挡
本节主要通过射线判断摄像机和目标物体间有没有被其他物体遮挡,进而对物体进行进行类似隐藏的处理(当然,官方使用了自己的Shader来实现)。不作为精简版的内容。有兴趣的朋友可以自行研究。
小结
  • SpatialMapping.prefab
    空间扫描最核心的组件,内部使用Unity提供的SurfaceObserver工具进行空间扫描,从而获取到扫描数据。
  • Surface Meshes To Planes
    识别扫描数据的类型(墙、地、桌等),进而转换为对应的模型。内部使用PlaneFinding类对扫描数据进行分析。
  • PlaneFinding
    空间扫描物体的类型识别算法核心组件。涉及到大量的运算,生产环境中,禁止参与Unity的主线程运算。可参考Surface Meshes To Planes源码自行使用。
  • Remove Surface Vertices
    移除与指定物体列表相重叠的空间三角形。
  • World Anchor Manager
    空间锚点管理器,“固化”物体到空间的核心组件。







上一篇:Hololens官方教程精简版 - 06. Spatial sound(空间声音)
下一篇:Hololens官方教程精简版 - 08. Sharing holograms(共享全息影像)
发表于 2017-12-5 22:25:03 | 显示全部楼层
哎呀哦,很不错
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

注册验证邮件查收提醒:

由于各大邮箱政策原因,

如果没收到邮件提醒,

您的注册验证邮件可能

被投送到您邮箱的垃圾箱,

请注意查收验证哦


QQ|小黑屋|Hololens全息现实网 ( 京ICP备15026232号   点击这里给我发消息

GMT+8, 2018-10-18 17:07 , Processed in 0.543178 second(s), 30 queries .

Powered by Hololens全息现实网 X3.2

© 2001-2017 Hololens全息现实网

快速回复 返回顶部 返回列表