AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SurfacePlane.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 System;
5 using UnityEngine;
6 
7 namespace HoloToolkit.Unity.SpatialMapping
8 {
12  [Flags]
13  public enum PlaneTypes
14  {
15  Wall = 0x1,
16  Floor = 0x2,
17  Ceiling = 0x4,
18  Table = 0x8,
19  Unknown = 0x10
20  }
21 
27  public class SurfacePlane : MonoBehaviour
28  {
29  [Tooltip("Thickness to make each plane.")]
30  [Range(0.0f, 1.0f)]
31  public float PlaneThickness = 0.01f;
32 
33  [Tooltip("Threshold for acceptable normals (the closer to 1, the stricter the standard). Used when determining plane type.")]
34  [Range(0.0f, 1.0f)]
35  public float UpNormalThreshold = 0.9f;
36 
37  [Tooltip("Buffer to use when determining if a horizontal plane near the floor should be considered part of the floor.")]
38  [Range(0.0f, 1.0f)]
39  public float FloorBuffer = 0.1f;
40 
41  [Tooltip("Buffer to use when determining if a horizontal plane near the ceiling should be considered part of the ceiling.")]
42  [Range(0.0f, 1.0f)]
43  public float CeilingBuffer = 0.1f;
44 
45  [Tooltip("Material to use when rendering Wall planes.")]
46  public Material WallMaterial;
47 
48  [Tooltip("Material to use when rendering floor planes.")]
49  public Material FloorMaterial;
50 
51  [Tooltip("Material to use when rendering ceiling planes.")]
52  public Material CeilingMaterial;
53 
54  [Tooltip("Material to use when rendering table planes.")]
55  public Material TableMaterial;
56 
57  [Tooltip("Material to use when rendering planes of the unknown type.")]
58  public Material UnknownMaterial;
59 
60  [Tooltip("Type of plane that the object has been classified as.")]
61  public PlaneTypes PlaneType = PlaneTypes.Unknown;
62 
66  private BoundedPlane plane = new BoundedPlane();
67 
71  public BoundedPlane Plane
72  {
73  get
74  {
75  return plane;
76  }
77  set
78  {
79  plane = value;
80  UpdateSurfacePlane();
81  }
82  }
83 
87  public Vector3 SurfaceNormal { get; private set; }
88 
92  public bool IsVisible
93  {
94  get
95  {
96  return gameObject.GetComponent<Renderer>().enabled;
97  }
98  set
99  {
100  if (IsVisible != value)
101  {
102  gameObject.GetComponent<Renderer>().enabled = value;
103  }
104  }
105  }
106 
107  private void Awake()
108  {
109  plane = new BoundedPlane(transform);
110  }
111 
112  private void Start()
113  {
114  UpdateSurfacePlane();
115  }
116 
122  private void UpdateSurfacePlane()
123  {
124  SetPlaneGeometry();
125  SetPlaneType();
126  SetPlaneMaterialByType();
127  }
128 
132  private void SetPlaneGeometry()
133  {
134  // Set the SurfacePlane object to have the same extents as the BoundingPlane object.
135  gameObject.transform.position = plane.Bounds.Center;
136  gameObject.transform.rotation = plane.Bounds.Rotation;
137  Vector3 extents = plane.Bounds.Extents * 2;
138  gameObject.transform.localScale = new Vector3(extents.x, extents.y, PlaneThickness);
139  }
140 
144  private void SetPlaneType()
145  {
146  SurfaceNormal = plane.Plane.normal;
147  float floorYPosition = SurfaceMeshesToPlanes.Instance.FloorYPosition;
148  float ceilingYPosition = SurfaceMeshesToPlanes.Instance.CeilingYPosition;
149 
150  // Determine what type of plane this is.
151  // Use the upNormalThreshold to help determine if we have a horizontal or vertical surface.
152  if (SurfaceNormal.y >= UpNormalThreshold)
153  {
154  // If we have a horizontal surface with a normal pointing up, classify it as a floor.
155  PlaneType = PlaneTypes.Floor;
156 
157  if (gameObject.transform.position.y > (floorYPosition + FloorBuffer))
158  {
159  // If the plane is too high to be considered part of the floor, classify it as a table.
160  PlaneType = PlaneTypes.Table;
161  }
162  }
163  else if (SurfaceNormal.y <= -(UpNormalThreshold))
164  {
165  // If we have a horizontal surface with a normal pointing down, classify it as a ceiling.
166  PlaneType = PlaneTypes.Ceiling;
167 
168  if (gameObject.transform.position.y < (ceilingYPosition - CeilingBuffer))
169  {
170  // If the plane is not high enough to be considered part of the ceiling, classify it as a table.
171  PlaneType = PlaneTypes.Table;
172  }
173  }
174  else if (Mathf.Abs(SurfaceNormal.y) <= (1 - UpNormalThreshold))
175  {
176  // If the plane is vertical, then classify it as a wall.
177  PlaneType = PlaneTypes.Wall;
178  }
179  else
180  {
181  // The plane has a strange angle, classify it as 'unknown'.
182  PlaneType = PlaneTypes.Unknown;
183  }
184  }
185 
189  private void SetPlaneMaterialByType()
190  {
191  Renderer renderer = gameObject.GetComponent<Renderer>();
192 
193  switch (PlaneType)
194  {
195  case PlaneTypes.Floor:
196  if (FloorMaterial != null)
197  {
198  renderer.material = FloorMaterial;
199  }
200  break;
201  case PlaneTypes.Table:
202  if (TableMaterial != null)
203  {
204  renderer.material = TableMaterial;
205  }
206  break;
207  case PlaneTypes.Ceiling:
208  if (CeilingMaterial != null)
209  {
210  renderer.material = CeilingMaterial;
211  }
212  break;
213  case PlaneTypes.Wall:
214  if (WallMaterial != null)
215  {
216  renderer.material = WallMaterial;
217  }
218  break;
219  default:
220  if (UnknownMaterial != null)
221  {
222  renderer.material = UnknownMaterial;
223  }
224  break;
225  }
226  }
227  }
228 }
The SurfacePlane class is used by SurfaceMeshesToPlanes to create different types of planes (walls...
Definition: SurfacePlane.cs:27
static T Instance
Returns the Singleton instance of the classes type. If no instance is found, then we search for an in...
Definition: Singleton.cs:26
PlaneTypes
All possible plane types that a SurfacePlane can be.
Definition: SurfacePlane.cs:13
SurfaceMeshesToPlanes will find and create planes based on the meshes returned by the SpatialMappingM...