资源下载网站源码,做一个公众号要多少钱?,保定全员核酸检测,广州 竞价托管写在前面的话
本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏#xff0c;更多详细内容请阅读原文。 文章目录 平面检测属性可视化平面平面检测的开关控制显示与隐藏已检测平面 平面检测属性
AR中检测平面的原理#xff1a;AR Fou… 写在前面的话
本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏更多详细内容请阅读原文。 文章目录 平面检测属性可视化平面平面检测的开关控制显示与隐藏已检测平面 平面检测属性
AR中检测平面的原理AR Foundation对摄像机获取的图像进行分析处理分离图像中的特征点这些特征点往往是图像中明暗、强弱、颜色变化较大的点利用VIO和IMU跟踪这些特征点的三维空间信息在跟踪过程中对特征点信息进行处理并尝试用空间中位置相近或者符合一定规律的特征点构建平面如果成功就是检测出了平面。平面有位置、方向和边界信息AR Plane Manager负责检测平面以及管理这些检测出来的平面但它并不负责渲染平面。
在AR Plane Manager中我们可以设置平面检测的方式如水平平面Horizontal、垂直平面Vertical、水平平面垂直平面Everything或者不检测平面Nothing检测平面也是一个消耗性能的工作而根据应用需要选择合适的检测方式可以优化应用性能。
平面本身是一个Trackable对象因此在AR Session Origin上检测到的时候AR Plane Manager会实例化一个平面Prefab并挂载AR Plane组件。 可视化平面 AR Plane Manager只负责平面的检测并不负责平面的渲染。平面渲染通常在检测构建的Prefab上执行预制体上的脚本如上所示
红框中的顶点偏差阈值表示只有偏差值在阈值范围内的特征点才被归为同一平面因此阈值越小检测越精确。AR Plane Mesh Visualizer组件主要是从边界特征点与其他特征点三角化生成一个平面网格而这个网格由Mesh Renderer进行渲染。默认平面预制体还有一个Line Renderer用于渲染边缘。
书中示例了自定义Shader和渲染脚本以实现定制化的平面渲染。 平面检测的开关控制
15 public void TogglePlaneDetection()
16 {
17 m_ARPlaneManager.enabled !m_ARPlaneManager.enabled;
18 string planeDetectionMessage ;
19 if (m_ARPlaneManager.enabled)
20 {
21 planeDetectionMessage 禁用平面检测;
22 SetAllPlanesActive(true);
23 }
24 else
25 {
26 planeDetectionMessage 启用平面检测;
27 SetAllPlanesActive(false);
28 }34 void SetAllPlanesActive(bool value)
35 {
36 foreach (var plane in m_ARPlaneManager.trackables)
37 plane.gameObject.SetActive(value);
38 }
对书内的代码进行了小小的裁剪。对于平面而言我们可以通过设置平面物体的Active状态来控制平面的显示。还记得我们说平面是受Manager自动管理的因此如果我们手动销毁平面可能会引发异常。
显示与隐藏已检测平面
直接关闭平面检测的话那么程序后续也不会再检测新的平面。有时我们想要隐藏已检测平面的同时保留平面检测功能以便在显示平面检测时直接显示那些新检测的平面而不是重新开始检测。
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using UnityEngine.XR.ARFoundation;
5 using UnityEngine.UI;
6
7 public class PlaneDisplay : MonoBehaviour
8 {
9 public Text m_TogglePlaneDetectionText;
10 private ARPlaneManager m_ARPlaneManager;
11 private bool isShow true;
12 private ListARPlane mPlanes;
13 void Start()
14 {
15 m_ARPlaneManager GetComponentARPlaneManager();
16 mPlanes new ListARPlane();
17 m_ARPlaneManager.planesChanged OnPlaneChanged;
18 }
19 void OnDisable()
20 {
21 m_ARPlaneManager.planesChanged - OnPlaneChanged;
22 }
23 #region 显示与隐藏检测的平面
24 public void TogglePlaneDisplay()
25 {
26 string planeDisplayMessage ;
27 if (isShow)
28 {
29 planeDisplayMessage 隐藏平面;
30 }
31 else
32 {
33 planeDisplayMessage 显示平面;
34 }
35 for (int i mPlanes.Count - 1; i 0; i--)
36 {
37 if (mPlanes[i] null || mPlanes[i].gameObject null)
38 mPlanes.Remove(mPlanes[i]);
39 else
40 mPlanes[i].gameObject.SetActive(isShow);
41 }
42 if (m_TogglePlaneDetectionText ! null)
43 m_TogglePlaneDetectionText.text planeDisplayMessage;
44
45 isShow !isShow;
46 }
47
48 private void OnPlaneChanged(ARPlanesChangedEventArgs arg)
49 {
50 for (int i 0; i arg.added.Count; i)
51 {
52 mPlanes.Add(arg.added[i]);
53 arg.added[i].gameObject.SetActive(isShow);
54 }
55 }
56 #endregion
57 }上述代码实现了在不关闭平面检测时隐藏已检测平面的功能。原理就是对平面变化的委托添加一个OnPlaneChanged的处理事件并从附带的事件参数中获取检测到的平面信息保存在一个私有的ListARPlane中。由于PanelManager中对平面的检测由Manager进行自动管理因此附带参数Args会产生变化例如增加新的面更新已有的面删除过期的面。
所以我们切换平面检测状态的时候还需要检测参数Args回传的面是否依旧存在若不存在则应当移除。否则切换已经过期的面的状态会引发异常。
37 if (mPlanes[i] null || mPlanes[i].gameObject null)
38 mPlanes.Remove(mPlanes[i]);事件注册与撤销一定是成双成对的上述代码在Start()方法中进行了注册在OnDisable()方法中撤消了注册如果事件没有在适当的时机撤销会引发难已排查的错误。