AR Plane Manager(平面追踪对象管理器)

简介: 平面管理器是一种可跟踪的管理器。平面管理器为环境中每个检测到的平面创建游戏对象。平面是由位姿、尺寸和边界点表示的平面。边界点是凸的(每个检测出来的边界角都是大于90°)。环境中可以被检测为平面的特征示例包括水平桌子、地板、工作台面和垂直墙壁。




负责管理平面以及管理检测出的这些平面,但不负责渲染平面,由其Plane Prefab属性指定的预制体负责

两个属性组件:

  1. Plane Prefab:平面预制体,不赋值的会自动实例化一个空对象
  2. Detection Mode:设置平面检测方式,如水平平面(Horizontal),垂直平面(Vertical),水平和垂直平面(Everything),不检测平面(Nothing)

可视化平面

要可视化平面,您需要创建一个 Prefab 或 GameObject,其中包含一个订阅 ARPlane 的 boundaryChanged 事件的组件。 ARFoundation 提供了一个 ARPlaneMeshVisualizer。该组件从边界顶点生成网格并将其分配给 MeshCollider、MeshFilter 和 LineRenderer(如果存在)。

要创建一个新的 GameObject,然后您可以使用它来创建您的 Prefab,请在您的 Scene 视图中单击鼠标右键,然后从出现的上下文菜单中选择 GameObject > XR > AR Default Plane

新建一个AR Default Plane对象作为预制体(默认平面预制体)

其中各属性的说明:

AR Plane:负责各类属性事宜,如是否在移除平面时销毁此实例化对象

AR Plane Mesh Visualizer:主要从边界特征点和其他特征点三角化生成一个平面网格

Mesh Renderer:使用Mesh Renderer采用合适材质渲染平面

Line Renderer:负责渲染平面可视化后的边界连线

演示视频:默认浅黄色的平面,黑色的边界线

https://www.bilibili.com/video/BV1pZ4y1f7Ru?spm_id_from=333.999.0.0

创建 AR Default Plane 后,将其分配给 ARPlaneManager 的 Plane Prefab 字段。您可以直接使用它,也可以通过将AR Default Plane 拖到 Assets 文件夹中来创建 Prefab。默认平面如下所示:

个性化渲染平面

我下载的是官方的demo

  1. 首先将AR Default Plane对象下的Line Renderer组件移除
  2. 编写一个c#脚本ARFeatheredPlaneMeshVisualizer,并将其作为组件添加到AR Default Plane对象上

usingSystem.Collections.Generic;

usingUnityEngine;

usingUnityEngine.XR.ARFoundation;

 

/// <summary>

/// This plane visualizer demonstrates the use of a feathering effect

/// at the edge of the detected plane, which reduces the visual impression

/// of a hard edge.

/// </summary>

[RequireComponent(typeof(ARPlaneMeshVisualizer), typeof(MeshRenderer), typeof(ARPlane))]

publicclassARFeatheredPlaneMeshVisualizer : MonoBehaviour

{

   [Tooltip("The width of the texture feathering (in world units).")]

   [SerializeField]

   floatm_FeatheringWidth=0.2f;

 

   /// <summary>

   /// The width of the texture feathering (in world units).

   /// </summary>

   publicfloatfeatheringWidth

   {

       get { returnm_FeatheringWidth; }

       set { m_FeatheringWidth=value; }

   }

 

   voidAwake()

   {

       m_PlaneMeshVisualizer=GetComponent<ARPlaneMeshVisualizer>();

       m_FeatheredPlaneMaterial=GetComponent<MeshRenderer>().material;

       m_Plane=GetComponent<ARPlane>();

   }

 

   voidOnEnable()

   {

       m_Plane.boundaryChanged+=ARPlane_boundaryUpdated;

   }

 

   voidOnDisable()

   {

       m_Plane.boundaryChanged-=ARPlane_boundaryUpdated;

   }

 

   voidARPlane_boundaryUpdated(ARPlaneBoundaryChangedEventArgseventArgs)

   {

       GenerateBoundaryUVs(m_PlaneMeshVisualizer.mesh);

   }

 

   /// <summary>

   /// Generate UV2s to mark the boundary vertices and feathering UV coords.

   /// </summary>

   /// <remarks>

   /// The <c>ARPlaneMeshVisualizer</c> has a <c>meshUpdated</c> event that can be used to modify the generated

   /// mesh. In this case we'll add UV2s to mark the boundary vertices.

   /// This technique avoids having to generate extra vertices for the boundary. It works best when the plane is

   /// is fairly uniform.

   /// </remarks>

   /// <param name="mesh">The <c>Mesh</c> generated by <c>ARPlaneMeshVisualizer</c></param>

   voidGenerateBoundaryUVs(Meshmesh)

   {

       intvertexCount=mesh.vertexCount;

 

       // Reuse the list of UVs

       s_FeatheringUVs.Clear();

       if (s_FeatheringUVs.Capacity<vertexCount) { s_FeatheringUVs.Capacity=vertexCount; }

 

       mesh.GetVertices(s_Vertices);

 

       Vector3centerInPlaneSpace=s_Vertices[s_Vertices.Count-1];

       Vector3uv=newVector3(0, 0, 0);

       floatshortestUVMapping=float.MaxValue;

 

       // Assume the last vertex is the center vertex.

       for (inti=0; i<vertexCount-1; i++)

       {

           floatvertexDist=Vector3.Distance(s_Vertices[i], centerInPlaneSpace);

 

           // Remap the UV so that a UV of "1" marks the feathering boudary.

           // The ratio of featherBoundaryDistance/edgeDistance is the same as featherUV/edgeUV.

           // Rearrange to get the edge UV.

           floatuvMapping=vertexDist/Mathf.Max(vertexDist-featheringWidth, 0.001f);

           uv.x=uvMapping;

 

           // All the UV mappings will be different. In the shader we need to know the UV value we need to fade out by.

           // Choose the shortest UV to guarentee we fade out before the border.

           // This means the feathering widths will be slightly different, we again rely on a fairly uniform plane.

           if (shortestUVMapping>uvMapping) { shortestUVMapping=uvMapping; }

 

           s_FeatheringUVs.Add(uv);

       }

 

       m_FeatheredPlaneMaterial.SetFloat("_ShortestUVMapping", shortestUVMapping);

 

       // Add the center vertex UV

       uv.Set(0, 0, 0);

       s_FeatheringUVs.Add(uv);

 

       mesh.SetUVs(1, s_FeatheringUVs);

       mesh.UploadMeshData(false);

   }

 

   staticList<Vector3>s_FeatheringUVs=newList<Vector3>();

 

   staticList<Vector3>s_Vertices=newList<Vector3>();

 

   ARPlaneMeshVisualizerm_PlaneMeshVisualizer;

 

   ARPlanem_Plane;

 

   Materialm_FeatheredPlaneMaterial;

}

 

  1. 在project窗口的Assets下新建一个文件夹Shaders,在其中右键-》create-》shader-》Unlit Shader创建一个shader文件,并命名为FeatheredPlaneShader

Shader"Unlit/FeatheredPlaneShader"

{

   Properties

   {

       _MainTex("Texture", 2D) ="white" {}

       _TexTintColor("Texture Tint Color", Color) = (1,1,1,1)

       _PlaneColor("Plane Color", Color) = (1,1,1,1)

   }

       SubShader

       {

           Tags { "RenderType"="Transparent""Queue"="Transparent" }

           LOD100

           BlendSrcAlphaOneMinusSrcAlpha

           ZWriteOff

 

           Pass

           {

               CGPROGRAM

               #pragma vertex vert

               #pragma fragment frag

 

               #include "UnityCG.cginc"

 

               structappdata

               {

                   float4vertex : POSITION;

                   float2uv : TEXCOORD0;

                   float3uv2 : TEXCOORD1;

 

                   UNITY_VERTEX_INPUT_INSTANCE_ID

               };

 

               structv2f

               {

                   float4vertex : SV_POSITION;

                   float2uv : TEXCOORD0;

                   float3uv2 : TEXCOORD1;

 

                   UNITY_VERTEX_OUTPUT_STEREO

               };

 

               sampler2D_MainTex;

               float4_MainTex_ST;

               fixed4_TexTintColor;

               fixed4_PlaneColor;

               float_ShortestUVMapping;

 

               v2fvert(appdatav)

               {

                   v2fo;

 

                   UNITY_SETUP_INSTANCE_ID(v);

                   UNITY_INITIALIZE_OUTPUT(v2f, o);

                   UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

 

                   o.vertex=UnityObjectToClipPos(v.vertex);

                   o.uv=TRANSFORM_TEX(v.uv, _MainTex);

                   o.uv2=v.uv2;

                   returno;

               }

 

               fixed4frag(v2fi) : SV_Target

               {

                   UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

 

                   fixed4col=tex2D(_MainTex, i.uv) *_TexTintColor;

                   col=lerp(_PlaneColor, col, col.a);

                   // Fade out from as we pass the edge.

                   // uv2.x stores a mapped UV that will be "1" at the beginning of the feathering.

                   // We fade until we reach at the edge of the shortest UV mapping.

                   // This is the remmaped UV value at the vertex.

                   // We choose the shorted one so that ll edges will fade out completely.

                   // See ARFeatheredPlaneMeshVisualizer.cs for more details.

                   col.a*=1-smoothstep(1, _ShortestUVMapping, i.uv2.x);

                   returncol;

               }

               ENDCG

           }

       }

}

 

  1. 然后在Materials文件下创建一个新的材质,右键-》create-》material,并命名为Plane Mat,其下有一属性Shader,在其中搜索刚写好的shader脚本代码,添加进来

  2. 在project窗口的Assets下新建一个文件夹Textures,将一个png格式的渲染图片拖到此文件夹下,自动生成一个同名的(Texture 2D)文件

  3. 选中Plant Mat,在Inspector窗口下,有一个Texture属性,选择我们刚拖进来的png图片,其中Texture Tint Color为纹理显示的颜色,Plane Color为平面的颜色,再将这个材质拖动添加到AR Default Plane对象上去,


  4. 至此个性化渲染平面已经制作完成,总结一下:不同于默认的黄色平面,黑色边界线,自定义的平面效果可以设置Shader脚本渲染Texture图片纹理属性,并将Texture图片设置在一个新材质material上,material可以设置纹理颜色和平面背景颜色(一般是透明),最终在Android手机上跑一下效果:https://www.bilibili.com/video/BV16P4y1j7Po?spm_id_from=333.999.0.0
相关文章
|
定位技术 vr&ar
哈迷福利!这个小哥租下一座城堡,用AR和GPS做了张“活点地图”,实时追踪入侵者
哈迷福利!这个小哥租下一座城堡,用AR和GPS做了张“活点地图”,实时追踪入侵者
154 0
|
4月前
|
人工智能 编解码 5G
虚拟现实(VR)与增强现实(AR)的融合:开启全新交互时代
【6月更文挑战第17天】虚拟现实(VR)与增强现实(AR)融合成混合现实(MR),打造全新交互体验。MR结合VR的沉浸感和AR的现实增强,应用于教育、游戏、设计和营销,带来创新教学方式、沉浸式游戏体验和高效设计工具。尽管面临技术挑战,随着5G和AI的发展,MR有望引领未来交互的革命。
|
4月前
|
传感器 数据可视化 安全
【虚拟现实】二、主要的AR/VR硬件设备
【虚拟现实】二、主要的AR/VR硬件设备
66 3
|
2月前
|
vr&ar 图形学 开发者
步入未来科技前沿:全方位解读Unity在VR/AR开发中的应用技巧,带你轻松打造震撼人心的沉浸式虚拟现实与增强现实体验——附详细示例代码与实战指南
【8月更文挑战第31天】虚拟现实(VR)和增强现实(AR)技术正深刻改变生活,从教育、娱乐到医疗、工业,应用广泛。Unity作为强大的游戏开发引擎,适用于构建高质量的VR/AR应用,支持Oculus Rift、HTC Vive、Microsoft HoloLens、ARKit和ARCore等平台。本文将介绍如何使用Unity创建沉浸式虚拟体验,包括设置项目、添加相机、处理用户输入等,并通过具体示例代码展示实现过程。无论是完全沉浸式的VR体验,还是将数字内容叠加到现实世界的AR应用,Unity均提供了所需的一切工具。
69 0
|
2月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
36 0
|
3月前
|
传感器 人工智能 数据可视化
虚拟现实(VR)与增强现实(AR)的技术革新:塑造未来的沉浸式体验
【7月更文挑战第24天】VR和AR作为两种前沿的沉浸式技术,正以前所未有的速度改变着我们的世界。随着技术的不断革新和应用的不断拓展,我们有理由相信,未来的VR和AR将为我们带来更多令人惊叹的体验和技术革新。
|
4月前
|
vr&ar
AR和VR的光学结构分别是什么?
【6月更文挑战第25天】AR和VR的光学结构分别是什么?
96 5
下一篇
无影云桌面