本帖主要描写扫描场景的功能实现,以及一些需要注意的问题。跟上层贴有所关联,想要更多了解请移步链接。

场景中有几个重要的预设需要添加。目录如下:

其中:

SparseSpatialMap 用于扫描空间成成点云信息,点云可以将空间数据以点的信息保存下来 SparseSpatialMapController
WorldRoot 点云的空间位置的基本参照 WorldRootController
EasyAR_SparseSpatialMapWorker 点云保存上传等一些操作的入口 ARSession/SparseSpatialMapWorkerFrameFilter

场景中,我用Text来debug一些信息,可以显示当前的进度。

操作流程:进入场景开始扫描云点,然后点击保存之后弹出窗口,开始编辑地图名字,编辑完成后,点击上传。

然后创建SceneMaster来对场景进行管理。添加脚本BuildMapController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using easyar;
using System;
using SpatialMap_SparseSpatialMap;
using UnityEngine.SceneManagement;public class BuildMapController : MonoBehaviour
{//稀疏空间地图相关对象private ARSession session;private SparseSpatialMapWorkerFrameFilter mapWorker;private SparseSpatialMapController map;/// <summary>/// 保存按钮/// </summary>private Button btnSave; //保存按钮private Button btnUpload;  //输入名字后上传private GameObject SavePanel;/// <summary>/// 显示文本/// </summary>private Text text;private InputField inputField;private void Awake(){//稀疏空间地图初始session = FindObjectOfType<ARSession>();mapWorker = FindObjectOfType<SparseSpatialMapWorkerFrameFilter>();map = FindObjectOfType<SparseSpatialMapController>();SavePanel = GameObject.Find("MapName");inputField = SavePanel.transform.Find("Panel/InputField").GetComponent<InputField>();btnUpload = SavePanel.transform.Find("Panel/Btn_Upload").GetComponent<Button>();btnSave = GameObject.Find("Canvas/Map/Btn_SaveMap").GetComponent<Button>();//显示文本text = GameObject.Find("Canvas/Map/Text").GetComponent<Text>();}void Start(){map.MapWorker = mapWorker;//注册追踪状态变化事件session.WorldRootController.TrackingStatusChanged += OnTrackingStatusChanged;SavePanel.SetActive(false);//初始化保存按钮btnSave.onClick.AddListener(OpenUploadPanel);btnUpload.onClick.AddListener(Save);btnSave.interactable = false;if (session.WorldRootController.TrackingStatus == MotionTrackingStatus.Tracking){btnSave.interactable = true;}else{btnSave.interactable = false;}}/// <summary>/// 保存地图方法/// </summary>private void OpenUploadPanel(){btnSave.interactable = false;SavePanel.SetActive(true);}string mapName = "";private void Save(){//注册地图保存结果反馈事件mapWorker.BuilderMapController.MapHost += SaveMapHostBack;//mapWorker.BuilderMapController.MapLoad += LoadMapHostBack;//保存地图try{if (!inputField.text.Equals(string.Empty)){mapName = "Map" + inputField.text;}else{mapName = "Map" + DateTime.Now.ToString("YYYY-MM-DD-HH-mm-ss");}//保存地图mapWorker.BuilderMapController.Host(mapName, null);text.text = "开始保存地图,请稍等。";}catch (Exception ex){btnSave.interactable = true;text.text = "保存出错:" + ex.Message;}}/// <summary>/// 保存地图反馈/// </summary>/// <param name="mapInfo">地图信息</param>/// <param name="isSuccess">成功标识</param>/// <param name="error">错误信息</param>private void SaveMapHostBack(SparseSpatialMapController.SparseSpatialMapInfo mapInfo, bool isSuccess, string error){if (isSuccess){SavePanel.SetActive(false);PlayerPrefs.SetString("MapID", mapInfo.ID);PlayerPrefs.SetString("MapName", mapInfo.Name);text.text = "地图保存成功。\r\nMapID:" + mapInfo.ID + "\r\nMapName:" + mapInfo.Name;MapMetaManager.Save(new MapMeta(mapInfo, new List<MapMeta.PropInfo>()), MapMetaManager.FileNameType.Name);Invoke("BackMain", 3);}else{btnSave.interactable = true;text.text = "地图保存出错:" + error;}}public void BackMain(){SceneManager.LoadScene("MainMapScene");}/// <summary>/// 摄像机状态变化/// </summary>/// <param name="status">状态</param>private void OnTrackingStatusChanged(MotionTrackingStatus status){if (status == MotionTrackingStatus.Tracking){btnSave.interactable = true;text.text = "进入跟踪状态。";}else{btnSave.interactable = false;text.text = "退出跟踪状态。" + status.ToString();}}
}

代码相关:

在Awake获取到三个主要的脚本,然后在start中完成初始化。

1.将 mapWorker 填充进 mapController 中的MapWorker属性中。这一步也可以在场景中直接拖拽也行。

2.在session.WorldRootController.TrackingStatusChanged 注册事件。

 ///注册追踪状态变化事件session.WorldRootController.TrackingStatusChanged += OnTrackingStatusChanged;

这个事件的用处是可以监听当前的追踪状态。拿到追踪状态就可做一些事情。例如我用来提示,也可以用来操作一些游戏对象的状态等,或者弹出UI提醒用户做一些操作等。

 private void OnTrackingStatusChanged(MotionTrackingStatus status){if (status == MotionTrackingStatus.Tracking){btnSave.interactable = true;text.text = "进入跟踪状态。";}else{btnSave.interactable = false;text.text = "退出跟踪状态。" + status.ToString();}}

3.扫描场景。扫描的过程中,随着点云数量的增加,手机会变的逐渐卡顿,最大的场景支持100平方米,其实也不大,就10*10的地块。实际使用下来一般50平方左右的空间最舒服。

4.点击保存按钮弹出框框,编辑名字后点击上传。

 string mapName = "";private void Save(){//注册地图保存结果反馈事件mapWorker.BuilderMapController.MapHost += SaveMapHostBack;//mapWorker.BuilderMapController.MapLoad += LoadMapHostBack;//保存地图try{if (!inputField.text.Equals(string.Empty)){mapName = "Map" + inputField.text;}else{mapName = "Map" + DateTime.Now.ToString("YYYY-MM-DD-HH-mm-ss");}//保存地图mapWorker.BuilderMapController.Host(mapName, null);text.text = "开始保存地图,请稍等。";}catch (Exception ex){btnSave.interactable = true;text.text = "保存出错:" + ex.Message;}}

首先注册一个保存地图后的回调。该回调在完成上传后调用,不管成功与否。

 mapWorker.BuilderMapController.MapHost += SaveMapHostBack;

然后 调用 host 方法来上传地图。

  //保存地图mapWorker.BuilderMapController.Host(mapName, null);

然后是对回调信息的处理。处理很简单,就是将这个地图的ID和名字用 PlayerPrefs 存到本地,这个东西自己的觉得方便就用了。大家可以用自己喜欢的方法Json或者其他本地化的方法实现。

    /// <summary>/// 保存地图回调/// </summary>/// <param name="mapInfo">地图信息</param>/// <param name="isSuccess">成功标识</param>/// <param name="error">错误信息</param>private void SaveMapHostBack(SparseSpatialMapController.SparseSpatialMapInfo mapInfo, bool isSuccess, string error){if (isSuccess){SavePanel.SetActive(false);PlayerPrefs.SetString("MapID", mapInfo.ID);PlayerPrefs.SetString("MapName", mapInfo.Name);text.text = "地图保存成功。\r\nMapID:" + mapInfo.ID + "\r\nMapName:" + mapInfo.Name;MapMetaManager.Save(new MapMeta(mapInfo, new List<MapMeta.PropInfo>()), MapMetaManager.FileNameType.Name);Invoke("BackMain", 3);}else{btnSave.interactable = true;text.text = "地图保存出错:" + error;}}

然后是 MapMetaManager 这个脚本。这个脚本用来处理点云信息。将meta 信息存储到本地先,用来下一步场景编辑时使用。

//================================================================================================================================
//
//  Copyright (c) 2015-2020 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
//  EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
//  and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;
namespace SpatialMap_SparseSpatialMap
{public class MapMetaManager{public enum FileNameType{ID, Name}private static readonly string root = Application.persistentDataPath + "/SparseSpatialMap";public static List<MapMeta> LoadAll(){//Debug.Log(root);var metas = new List<MapMeta>();var dirRoot = GetRootPath();try{foreach (var path in Directory.GetFiles(dirRoot, "*.meta")){try{metas.Add(JsonUtility.FromJson<MapMeta>(File.ReadAllText(path)));}catch (System.Exception e){Debug.LogError(e.Message);}}}catch (System.Exception e){Debug.LogError(e.Message);}return metas;}public static bool Save(MapMeta meta, FileNameType fileNameType = FileNameType.ID){try{switch (fileNameType){case FileNameType.ID:File.WriteAllText(GetPath(meta.Map.ID), JsonUtility.ToJson(meta, true));break;case FileNameType.Name:File.WriteAllText(GetPath(meta.Map.Name), JsonUtility.ToJson(meta, true));break;}}catch (System.Exception e){Debug.LogError(e.Message);return false;}return true;}public static bool Save(PointData data){try{File.WriteAllText(GetPathTxt(data.mapName + "_PointCloud"), JsonConvert.SerializeObject(data));}catch (System.Exception e){Debug.LogError(e.Message);return false;}return true;}public static List<PointData> Load_PointCloud<PointData>(){var dirRoot = GetRootPath();var datas = new List<PointData>();try{foreach (var path in Directory.GetFiles(dirRoot, "*.txt")){try{//Debug.Log(path); datas.Add(JsonConvert.DeserializeObject<PointData>(File.ReadAllText(path)));}catch (System.Exception e){Debug.LogError(e.Message);}}}catch (System.Exception e){Debug.LogError(e.Message);}return datas;}public static bool Delete(MapMeta meta){if (!File.Exists(GetPath(meta.Map.ID))){return false;}try{File.Delete(GetPath(meta.Map.ID));}catch (System.Exception e){Debug.LogError(e.Message);return false;}return true;}private static string GetRootPath(){var path = root;if (!File.Exists(path)){Directory.CreateDirectory(path);}return path;}private static string GetPath(string id){return GetRootPath() + "/" + id + ".meta";}private static string GetPathTxt(string id){return GetRootPath() + "/" + id + ".txt";}}
}

【Unity-学习-014】EasyAR4.0稀疏空间地图 扫描场景功能相关推荐

  1. 【Unity-学习-013】EasyAR4.0稀疏空间地图 在Unity中编辑扫描的场景

    之前遇到一个实验性的项目,用空间地图做场景识别,然后和游客互动拍照的需求.第一感觉就想到了 EasyAR4.0主推的空间地图功能.对于EasyAR的详细信息,请直接移步官网.那里有详细的介绍和简单的入 ...

  2. 0基础学习VR全景平台篇第34篇:场景功能-沙盘功能

    本期为大家带来蛙色VR平台,场景功能-沙盘功能的操作讲解. 功能位置示意 一.本功能将用在哪里? 沙盘功能,可将区域的平面图.卫星图.手绘图等上传或直接使用高德地图信息,嵌入在VR全景作品中呈现出来: ...

  3. 0基础学习VR全景平台篇第36篇:场景功能-导览

    大家好,欢迎观看蛙色VR官方系列--后台使用课程! 本期为大家带来蛙色VR平台,场景管理-导览功能操作. 功能位置示意 一.本功能将用在哪里? 导览,指给VR漫游作品预先设置好路线,并且可以自定义路线 ...

  4. 《Unity3D平台AR开发快速上手--基于EasyAR4.0》随书资源和相关说明

    新手<Unity3D平台AR开发快速上手–基于EasyAR4.0>上市了,现在京东和淘宝都有卖.书分为2个部分,第一部分是EasyAR4.0基础内容和使用,第二部分是利用EasyAR的稀疏 ...

  5. Unity学习之Human fall flat创意工坊地图制作

    Unity学习笔记之Human fall flat 主要参考<人类一败涂地>官方教程 Unity版本 详细教程获取 开始工程导入 素材包介绍 界面介绍 工具简介 常用组件简介 多人游戏组件 ...

  6. 利用unity与EasyAR4.0创建AR导航

    室内定位技术是全球发展的热点,不同于室外定位有成熟的GPS作为技术支撑,室内定位由于环境的复杂性,目前还没有一种成熟的技术完全满足室内定位导航的需要. 运用Easy AR内的稀疏空间定位建立空间地图, ...

  7. Unity学习记录——空间与运动

    Unity学习记录--空间与运动 前言 ​ 本文是中山大学软件工程学院2020级3d游戏编程与设计的作业3 编程题 1. 模拟太阳系 ​ 首先向unity中Assets添加所找的贴图素材Solar T ...

  8. 【Unity】Entities 1.0 学习(一):Aspect

    Unity在 2022年下半年(我印象是9月份左右)推出了 Entities 1.0 ,可以在 2022.2.0b8 以上的版本使用.当时我粗略地看了一下,但是没有深入学习.最近空闲时间稍多,就认真来 ...

  9. 数据可视化清新版【chart.js】学习笔记8.0—极地图(Polar Area)

    Polar Area--(极地图) 极地面积图类似于饼图,但每个线段具有相同的角度 - 线段的半径因值而异.当我们想要显示类似于饼图的比较数据,同时也要显示上下文的值的范围时通常使用这种类型的图表. ...

最新文章

  1. Vulkan Tutorial 12 Fixed functions
  2. 人工智能的影响调查_调查报告|文科大学生群体对于人工智能影响 就业的认知程度:基于访谈的质性研究...
  3. java makedir用法_Java Files.makeDir方法代码示例
  4. 《研磨设计模式》读后感一
  5. tp5中在where中使用in
  6. 杀毒软件全免费遭厂家“抵制”
  7. 自然语言处理 —— 2.4 嵌入矩阵
  8. flutter 泛型_flutter用NestedScrollView的项目必须知道的坑
  9. [buaa-SE-2017]个人作业-Week1
  10. 简单几步把Spring Boot 项目部署到 K8S,步骤来了!
  11. 拓端tecdat|R语言逻辑回归和泊松回归模型对发生交通事故概率建模
  12. ASP.NET事件回传机制
  13. 微信表情包 php,教你用PS给你的室友做一套动态微信豪华表情包
  14. java case 字符_Java中Switch Case使用字符串
  15. KGB知识图谱在企业活动中能够实现那些运用
  16. 刚开始使用push遇到的小问题
  17. 实现笔记本键盘如何上锁和解锁
  18. 电脑自动开机是什么原因
  19. 4.2.1 积分法(一)——第一类换元积分法
  20. efm8系列单片机c语言编程,EFM8单片机用Keil编程,头文件怎么写?

热门文章

  1. WGestures - 鼠标手势工具软件,高手必备效率神器!
  2. Jmeter——Jmeter限制网速进行测试
  3. Linux安装omnet++
  4. 电工 电路的暂态分析
  5. 经典电路(一)“桥式整流电路”
  6. 也谈软件公司的企业文化
  7. 用word域创建公式、图表、参考文献自动编号及交叉引用
  8. sa蛋OpenCV参数说明
  9. wps:如表:自动编号
  10. 校友录(alumni record)项目部署的最详细说明