Hololens Spatial Mapping功能实现
HoloToolkit项目是一组开发包,是微软基于unity内置的底层API封装的一套工具集合,帮助我们快速使用Unity集成开发hololens应用。
本文主要通过源码研究其中Spatial Mapping的实现,学会如何使用实现自己的三维空间重建。
0x00 组件结构
Spatial Mapping目录下有很多内容,其中Prefabs目录里有我们可以直接使用的预置组件,本文关注的重点是Scripts目录的脚本。组件目录结构如下:
本文重点研究SpatialMappingObserver.cs和SpatialMappingSource.cs,这是当前组件的核心内容。
0x01 SpatialMappingObserver.cs
源码地址:https://github.com/Microsoft/HoloToolkit-Unity/blob/master/Assets/HoloToolkit/SpatialMapping/Scripts/SpatialMappingObserver.cs
我们先分析其属性,如下:
[代码]:
01
|
//每立方米网格三角形数量,控制mesh质量
|
02
|
public float TrianglesPerCubicMeter = 500f;
|
03
|
04
|
//当前Observer检测的空间范围
|
05
|
public Vector3 Extents = Vector3.one * 10.0f;
|
06
|
07
|
//刷新时间间隔
|
08
|
public float TimeBetweenUpdates = 3.5f;
|
09
|
10
|
//用于扫描空间平面的核心组件
|
11
|
private SurfaceObserver observer;
|
12
|
13
|
//存储已构建的空间网格对象
|
14
|
private Diction<a href= "http://www.52vr.com/armr/" style= "font-weight: bold;color: ;" target= "_blank" >AR</a>y< int , gameobject= "" > surfaces = new Dictionary< int , gameobject= "" >();
|
15
|
16
|
//SurfaceData队列,用于生成空间mesh
|
17
|
private Queue<surfacedata> surfaceWorkQueue = new Queue<surfacedata>();
|
18
|
19
|
//为了避免同一时刻生成太多mesh,保证同一时刻只生成一个mesh,这个变量用于判断当前时刻是否有mesh正在创建
|
20
|
private bool surfaceWorkOutstanding = false ;
|
21
|
22
|
//用于追踪Observer对象上次更新时间
|
23
|
private float updateTime;
|
24
|
25
|
//表示当前扫描状态,Running和Stopped两种状态
|
26
|
public ObserverStates ObserverState { get ; private set ; }</surfacedata></surfacedata></ int ,></ int ,>
|
再分析其程序逻辑及流程:
- Awake()方法最先被执行,这里对SurfaceObserver对象进行了初始化。
[代码]:
1
|
private void Awake()
|
2
|
{
|
3
|
observer = new SurfaceObserver();
|
4
|
ObserverState = ObserverStates.Stopped;
|
5
|
}
|
- 接下来是Start()方法,里面设定了扫描的空间范围。
[代码]:
1
|
private void Start()
|
2
|
{
|
3
|
observer.SetVolumeAsAxisAlignedBox(Vector3.zero, Extents);
|
4
|
}
|
- Update()方法中则会根据当前状态来调用API请求空间表面信息或者生成mesh对象
[代码]:
01
|
private void Update()
|
02
|
{
|
03
|
|
04
|
if (ObserverState == ObserverStates.Running)
|
05
|
{
|
06
|
// 如果当前没有再生成mesh,且SurfaceData中有需要生成mesh的对象
|
07
|
if (surfaceWorkOutstanding == false && surfaceWorkQueue.Count > 0)
|
08
|
{
|
09
|
|
10
|
SurfaceData surfaceData = surfaceWorkQueue.Dequeue();
|
11
|
12
|
// 如果能成功请求到mesh对象,当前任务状态变为生成mesh中
|
13
|
surfaceWorkOutstanding = observer.RequestMeshAsync(surfaceData, SurfaceObserver_OnDataReady);
|
14
|
}
|
15
|
//如果当前没有任务运行且上次更新距现在大于时间间隔,则重新请求SurfaceData数据
|
16
|
else if (surfaceWorkOutstanding == false && (Time.time - updateTime) >= TimeBetweenUpdates)
|
17
|
{
|
18
|
observer.Update(SurfaceObserver_OnSurfaceChanged);
|
19
|
updateTime = Time.time;
|
20
|
}
|
21
|
}
|
22
|
}
|
- SurfaceObserver_OnDataReady()事件方法用于处理使用SurfaceData请求到的mesh对象信息,用于后续的使用,比如处理其材质效果等。
[代码]:
01
|
private void SurfaceObserver_OnDataReady(SurfaceData cookedData, bool outputWritten, float elapsedCookTimeSeconds)
|
02
|
{
|
03
|
GameObject surface;
|
04
|
if (surfaces.TryGetValue(cookedData.id.handle, out surface))
|
05
|
{
|
06
|
// 设置 renderer组件的材质.
|
07
|
MeshRenderer renderer = surface.GetComponent<meshrenderer>();
|
08
|
renderer.sharedMaterial = SpatialMappingManager.Instance.SurfaceMaterial;
|
09
|
//是否渲染mesh对象
|
10
|
renderer.enabled = SpatialMappingManager.Instance.DrawVisualMeshes;
|
11
|
12
|
if (SpatialMappingManager.Instance.CastShadows == false )
|
13
|
{
|
14
|
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
15
|
}
|
16
|
}
|
17
|
18
|
surfaceWorkOutstanding = false ;
|
19
|
}</meshrenderer>
|
- SurfaceObserver_OnSurfaceChanged()事件方法用于处理SurfaceObserver获取到的空间表面数据,用于后续的请求mesh对象操作。
[代码]:
01
|
private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime)
|
02
|
{
|
03
|
// 判断当前扫描状态
|
04
|
if (ObserverState != ObserverStates.Running)
|
05
|
{
|
06
|
return ;
|
07
|
}
|
08
|
09
|
GameObject surface;
|
10
|
11
|
switch (changeType)
|
12
|
{
|
13
|
|
14
|
case SurfaceChange.Added:
|
15
|
case SurfaceChange.Updated:
|
16
|
// 检测当前表面是否已被扫描过
|
17
|
if (!surfaces.TryGetValue(id.handle, out surface))
|
18
|
{
|
19
|
// 创建一个和当前表面关联的mesh对象
|
20
|
surface = AddSurfaceObject( null , string .Format( "Surface-{0}" , id.handle), transform);
|
21
|
22
|
surface.AddComponent<worldanchor>();
|
23
|
24
|
// 将surface对象加入已知空间表面字典
|
25
|
surfaces.Add(id.handle, surface);
|
26
|
}
|
27
|
28
|
// 请求生成或更新对应的mesh对象
|
29
|
QueueSurfaceDataRequest(id, surface);
|
30
|
break ;
|
31
|
32
|
case SurfaceChange.Removed:
|
33
|
// 移除关联的mesh对象
|
34
|
if (surfaces.TryGetValue(id.handle, out surface))
|
35
|
{
|
36
|
surfaces.Remove(id.handle);
|
37
|
Destroy(surface);
|
38
|
}
|
39
|
break ;
|
40
|
}
|
41
|
}</worldanchor>
|
Hololens Spatial Mapping功能实现相关推荐
- Unity中实现Hololens的三维空间映射Spatial mapping
hololens最出色的功能就是他对环境的空间扫描和重建功能,在unity的Hololens示例中,有完整的三维重建代码,本文主要讨论如何在Unity项目中集成空间映射功能.Unity内置了对空间映射 ...
- [洪流学堂]Hololens开发高级篇5:空间映射(Spatial mapping)
本教程基于Unity2017.2及Visual Studio 2017 本教程编写时间:2017年12月16日 本文内容提要 空间映射让holograms了解周围环境,将真实世界和虚拟世界更好地结合在 ...
- Hololens 开发笔记(2)——Spatial Mapping
原文链接:Hololens 开发笔记(11)--Spatial Mapping_Jitwxs的博客-CSDN博客 Hololens 作为一款混合现实设备,其与传统 VR/AR 设备最大的区别是,能够和 ...
- Hololens官方教程精简版 - 07. Spatial mapping(空间映射)
前言 注意:本文已更新到5.5.1f1版本 个人建议,学习Holograms 230之前,一定完成<Hololens官方教程精简版 - 02. Introduction with Device& ...
- SAP ABAP实用技巧介绍系列之 使用simple transformation的mapping功能
Created by Jerry Wang, last modified on Jun 25, 2014 Simple transformation如下: 当node VALTO_DATE的value ...
- HoloLens开发与性能优化实践
HoloLens中国版终于于5月底在中国上市,同时国内的技术社区经过一年的成长也有了很大的扩张,越来越多的开发者开始进入了HoloLens开发领域,尝试着使用混合现实(Mixed Reality)技术 ...
- [洪流学堂]Hololens开发入门篇3:使用基本功能开发一个小应用
本文首发于"洪流学堂"公众号. 洪流学堂,让你快人几步 本教程基于Unity2017.2及Visual Studio 2017 本教程编写时间:2017年12月4日 本文内容提要 ...
- HoloLens开发之远程视频AR标注功能开发
HoloLens2系统自带的软件中包含的官方开发的Dynamics 365 Remote Assist软件,想必大部分用户及开发者看过官方的宣传视频,通过移动端和HoloLens视频通话进行远程协作, ...
- HoloLens开发手记 - Unity development overview 使用Unity开发概述
Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必 ...
最新文章
- 自学python的网站-python有哪些学习网站
- 五边形创意画_绝了,自己做吊灯,创意满满!不仅好看还省钱!
- 炫界 (978) -(建工发现应用克隆漏)_湖南建工装配式建筑迈入“加速度”
- python从数分到数编(part1)--基础
- linux系统启动流程及常见问题的解决
- 可视化:动态气泡图,拿走不谢!
- 对服务与工厂感到困惑
- 如何调用showapiRequest解决图片验证码识别?
- 网站创业项目商业计划书的写法
- 下载百度网盘资源不限速的两种方法
- Lotka–Volterra equation Competitive Lotka–Volterra equations
- 新款苹果手机_售价千元!苹果今日推出新款手机壳,买吗
- msi 微星b350 tomahawk主板 刷bios教程
- python嵌入式系统开发_图解嵌入式系统开发之语言篇:初识Python
- 淘宝教育视频加速观看(在淘宝教育上看学习视频,需要加速,在谷歌浏览器上安装视频加速插件)
- Python项目--批量下载小姐姐壁纸
- userdel删除用户时候提示:userdel: user xx is currently logged in
- nba2k14mod android,nba2k14安卓mod
- 计算机二级C语言操作题怎么做?注意事项(难点易错点总结笔记)
- XiaoHu日志 11/22~12/3