AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
PlaneFindingTest.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using UnityEngine;
5 using System.Collections.Generic;
6 
7 namespace HoloToolkit.Unity.SpatialMapping.Tests
8 {
14  public class PlaneFindingTest : MonoBehaviour
15  {
16  [Range(0, 45)]
17  public float SnapToGravityThreshold = 0.0f;
18 
19  [Range(0, 10)]
20  public float MinArea = 1.0f;
21 
22  public bool VisualizeSubPlanes = false;
23 
24  private List<PlaneFinding.MeshData> meshData = new List<PlaneFinding.MeshData>();
25  private BoundedPlane[] planes;
26 
27  private void Update()
28  {
29  // Grab the necessary mesh data from the current set of surfaces that we want to run
30  // PlaneFinding against. This must be done on the main UI thread.
31  meshData.Clear();
32  foreach (MeshFilter mesh in GetComponentsInChildren<MeshFilter>())
33  {
34  meshData.Add(new PlaneFinding.MeshData(mesh));
35  }
36 
37  // Now call FindPlanes(). NOTE: In a real application, this MUST be executed on a
38  // background thread (i.e.: via ThreadPool.QueueUserWorkItem) so that it doesn't stall the
39  // rendering thread while running plane finding. Maintaining a solid 60fps is crucial
40  // to a good user experience.
41  planes = (VisualizeSubPlanes) ?
42  PlaneFinding.FindSubPlanes(meshData, SnapToGravityThreshold) :
43  PlaneFinding.FindPlanes(meshData, SnapToGravityThreshold, MinArea);
44  }
45 
46  private static Color[] colors = new Color[] { Color.blue, Color.cyan, Color.green, Color.magenta, Color.red, Color.white, Color.yellow };
47  private void OnDrawGizmos()
48  {
49  if (planes != null)
50  {
51  for (int i = 0; i < planes.Length; ++i)
52  {
53  Vector3 center = planes[i].Bounds.Center;
54  Quaternion rotation = planes[i].Bounds.Rotation;
55  Vector3 extents = planes[i].Bounds.Extents;
56  Vector3 normal = planes[i].Plane.normal;
57  center -= planes[i].Plane.GetDistanceToPoint(center) * normal;
58 
59  Vector3[] corners = new Vector3[4] {
60  center + rotation * new Vector3(+extents.x, +extents.y, 0),
61  center + rotation * new Vector3(-extents.x, +extents.y, 0),
62  center + rotation * new Vector3(-extents.x, -extents.y, 0),
63  center + rotation * new Vector3(+extents.x, -extents.y, 0)
64  };
65 
66  Color color = colors[i % colors.Length];
67 
68  Gizmos.color = color;
69  Gizmos.DrawLine(corners[0], corners[1]);
70  Gizmos.DrawLine(corners[0], corners[2]);
71  Gizmos.DrawLine(corners[0], corners[3]);
72  Gizmos.DrawLine(corners[1], corners[2]);
73  Gizmos.DrawLine(corners[1], corners[3]);
74  Gizmos.DrawLine(corners[2], corners[3]);
75  Gizmos.DrawLine(center, center + normal * 0.4f);
76  }
77  }
78  }
79 
80 #if UNITY_EDITOR
81  // This relies on helper functionality from the UnityEditor.Handles class, so make it UNITY_EDITOR only
82  private void OnDrawGizmosSelected()
83  {
84  if (planes != null)
85  {
86  Ray cameraForward = new Ray(Camera.current.transform.position, Camera.current.transform.forward);
87 
88  // Draw planes
89  for (int i = 0; i < planes.Length; ++i)
90  {
91  Vector3 center = planes[i].Bounds.Center;
92  Quaternion rotation = planes[i].Bounds.Rotation;
93  Vector3 extents = planes[i].Bounds.Extents;
94  Vector3 normal = planes[i].Plane.normal;
95  center -= planes[i].Plane.GetDistanceToPoint(center) * normal;
96 
97  Vector3[] corners = new Vector3[4] {
98  center + rotation * new Vector3(+extents.x, +extents.y, 0),
99  center + rotation * new Vector3(-extents.x, +extents.y, 0),
100  center + rotation * new Vector3(-extents.x, -extents.y, 0),
101  center + rotation * new Vector3(+extents.x, -extents.y, 0)
102  };
103 
104  Color color = colors[i % colors.Length];
105 
106  // Draw the same plane lines using the Handles class which ignores the depth buffer
107  UnityEditor.Handles.color = color;
108  UnityEditor.Handles.DrawLine(corners[0], corners[1]);
109  UnityEditor.Handles.DrawLine(corners[0], corners[2]);
110  UnityEditor.Handles.DrawLine(corners[0], corners[3]);
111  UnityEditor.Handles.DrawLine(corners[1], corners[2]);
112  UnityEditor.Handles.DrawLine(corners[1], corners[3]);
113  UnityEditor.Handles.DrawLine(corners[2], corners[3]);
114 #if UNITY_2017_3_OR_NEWER
115  UnityEditor.Handles.ArrowHandleCap(0, center, Quaternion.FromToRotation(Vector3.forward, normal), 0.4f, EventType.Ignore);
116 #else
117  UnityEditor.Handles.ArrowHandleCap(0, center, Quaternion.FromToRotation(Vector3.forward, normal), 0.4f, EventType.ignore);
118 #endif
119 
120  // If this plane is currently in the center of the camera's field of view, highlight it by drawing a
121  // solid rectangle, and display the important details about this plane.
122  float planeHitDistance;
123  if (planes[i].Plane.Raycast(cameraForward, out planeHitDistance))
124  {
125  Vector3 hitPoint = Quaternion.Inverse(rotation) * (cameraForward.GetPoint(planeHitDistance) - center);
126  if (Mathf.Abs(hitPoint.x) <= extents.x && Mathf.Abs(hitPoint.y) <= extents.y)
127  {
128  color.a = 0.1f;
129  UnityEditor.Handles.DrawSolidRectangleWithOutline(corners, color, Color.clear);
130 
131  string text = string.Format("Area: {0} Bounds: {1}\nPlane: N{2}, D({3})",
132  planes[i].Area.ToString("F1"),
133  ((Vector2)extents).ToString("F2"),
134  normal.ToString("F3"),
135  planes[i].Plane.distance.ToString("F3"));
136 
137  UnityEditor.Handles.Label(center, text, GUI.skin.textField);
138  }
139  }
140  }
141  }
142  }
143 #endif
144  }
145 }
static BoundedPlane [] FindSubPlanes(List< MeshData > meshes, float snapToGravityThreshold=0.0f)
Finds small planar patches that are contained within individual meshes. The output of this API can th...
Definition: PlaneFinding.cs:87
static BoundedPlane [] FindPlanes(List< MeshData > meshes, float snapToGravityThreshold=0.0f, float minArea=0.0f)
Convenience wrapper that executes FindSubPlanes followed by MergeSubPlanes via a single call into nat...
PlaneFinding is an expensive task that should not be run from Unity&#39;s main thread as it will stall th...
Definition: PlaneFinding.cs:56
Attach this component to a GameObject that contains some meshes (i.e.: the FakeSpatialMappingMesh.fbx). When running in the Unity editor, the planes are then visualized via editor gizmos. You can then play with the API parameters in real-time to see how the impact the plane finding algorithm.