diff --git a/Submodules/Examples b/Submodules/Examples
index 737e55647..ee58d6124 160000
--- a/Submodules/Examples
+++ b/Submodules/Examples
@@ -1 +1 @@
-Subproject commit 737e556476ca7a4e037bc8f852c852f478f258cb
+Subproject commit ee58d612407dd64dbe174776f7fd9513f4e63558
diff --git a/Submodules/WindowsMixedReality b/Submodules/WindowsMixedReality
index b22ebf919..0205b89ae 160000
--- a/Submodules/WindowsMixedReality
+++ b/Submodules/WindowsMixedReality
@@ -1 +1 @@
-Subproject commit b22ebf919587513e6a144cc6be7c7f2fcb85cbe0
+Subproject commit 0205b89aecd034342c7e08bc805b1caa26c324d8
diff --git a/XRTK-Core/Packages/com.xrtk.core/Editor/Profiles/MixedRealityBoundaryVisualizationProfileInspector.cs b/XRTK-Core/Packages/com.xrtk.core/Editor/Profiles/MixedRealityBoundaryVisualizationProfileInspector.cs
index cb6061bf1..034a4bba9 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Editor/Profiles/MixedRealityBoundaryVisualizationProfileInspector.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Editor/Profiles/MixedRealityBoundaryVisualizationProfileInspector.cs
@@ -9,66 +9,46 @@
namespace XRTK.Editor.Profiles
{
[CustomEditor(typeof(MixedRealityBoundaryVisualizationProfile))]
- public class MixedRealityBoundaryVisualizationProfileInspector : BaseMixedRealityProfileInspector
+ public class MixedRealityBoundaryVisualizationProfileInspector : MixedRealityServiceProfileInspector
{
+ private SerializedProperty showBoundary;
private SerializedProperty boundaryHeight;
+ private SerializedProperty physicsLayer;
+ private SerializedProperty boundaryMaterial;
+
private SerializedProperty showFloor;
private SerializedProperty floorMaterial;
- private SerializedProperty floorScale;
- private SerializedProperty floorPhysicsLayer;
-
- private SerializedProperty showPlayArea;
- private SerializedProperty playAreaMaterial;
- private SerializedProperty playAreaPhysicsLayer;
- private SerializedProperty showTrackedArea;
- private SerializedProperty trackedAreaMaterial;
- private SerializedProperty trackedAreaPhysicsLayer;
+ private SerializedProperty showWalls;
+ private SerializedProperty wallMaterial;
- private SerializedProperty showBoundaryWalls;
- private SerializedProperty boundaryWallMaterial;
- private SerializedProperty boundaryWallsPhysicsLayer;
+ private SerializedProperty showCeiling;
+ private SerializedProperty ceilingMaterial;
- private SerializedProperty showBoundaryCeiling;
- private SerializedProperty boundaryCeilingMaterial;
- private SerializedProperty ceilingPhysicsLayer;
-
- private readonly GUIContent showContent = new GUIContent("Show");
- private readonly GUIContent scaleContent = new GUIContent("Scale");
- private readonly GUIContent materialContent = new GUIContent("Material");
private readonly GUIContent generalSettingsFoldoutHeader = new GUIContent("General Settings");
private readonly GUIContent floorSettingsFoldoutHeader = new GUIContent("Floor Settings");
- private readonly GUIContent playAreaSettingsFoldoutHeader = new GUIContent("Play Area Settings");
- private readonly GUIContent trackedAreaSettingsFoldoutHeader = new GUIContent("Tracked Area Settings");
- private readonly GUIContent boundaryWallSettingsFoldoutHeader = new GUIContent("Boundary Wall Settings");
- private readonly GUIContent boundaryCeilingSettingsFoldoutHeader = new GUIContent("Boundary Ceiling Settings");
+ private readonly GUIContent wallSettingsFoldoutHeader = new GUIContent("Wall Settings");
+ private readonly GUIContent ceilingSettingsFoldoutHeader = new GUIContent("Ceiling Settings");
+ private readonly GUIContent materialContent = new GUIContent("Material Override", "Use a different material than the global boundary material?");
+ private readonly GUIContent showContent = new GUIContent("Force Show", "Force the boundary component to be displayed.\n\nNote: This can be toggled on/off at runtime.");
protected override void OnEnable()
{
base.OnEnable();
+ showBoundary = serializedObject.FindProperty(nameof(showBoundary));
boundaryHeight = serializedObject.FindProperty(nameof(boundaryHeight));
+ boundaryMaterial = serializedObject.FindProperty(nameof(boundaryMaterial));
+ physicsLayer = serializedObject.FindProperty(nameof(physicsLayer));
showFloor = serializedObject.FindProperty(nameof(showFloor));
floorMaterial = serializedObject.FindProperty(nameof(floorMaterial));
- floorScale = serializedObject.FindProperty(nameof(floorScale));
- floorPhysicsLayer = serializedObject.FindProperty(nameof(floorPhysicsLayer));
-
- showPlayArea = serializedObject.FindProperty(nameof(showPlayArea));
- playAreaMaterial = serializedObject.FindProperty(nameof(playAreaMaterial));
- playAreaPhysicsLayer = serializedObject.FindProperty(nameof(playAreaPhysicsLayer));
- showTrackedArea = serializedObject.FindProperty(nameof(showTrackedArea));
- trackedAreaMaterial = serializedObject.FindProperty(nameof(trackedAreaMaterial));
- trackedAreaPhysicsLayer = serializedObject.FindProperty(nameof(trackedAreaPhysicsLayer));
+ showWalls = serializedObject.FindProperty(nameof(showWalls));
+ wallMaterial = serializedObject.FindProperty(nameof(wallMaterial));
- showBoundaryWalls = serializedObject.FindProperty(nameof(showBoundaryWalls));
- boundaryWallMaterial = serializedObject.FindProperty(nameof(boundaryWallMaterial));
- boundaryWallsPhysicsLayer = serializedObject.FindProperty(nameof(boundaryWallsPhysicsLayer));
-
- showBoundaryCeiling = serializedObject.FindProperty(nameof(showBoundaryCeiling));
- boundaryCeilingMaterial = serializedObject.FindProperty(nameof(boundaryCeilingMaterial));
- ceilingPhysicsLayer = serializedObject.FindProperty(nameof(ceilingPhysicsLayer));
+ showCeiling = serializedObject.FindProperty(nameof(showCeiling));
+ ceilingMaterial = serializedObject.FindProperty(nameof(ceilingMaterial));
}
public override void OnInspectorGUI()
@@ -77,65 +57,50 @@ public override void OnInspectorGUI()
serializedObject.Update();
- boundaryHeight.FoldoutWithBoldLabelPropertyField(generalSettingsFoldoutHeader);
-
- EditorGUILayout.Space();
-
- if (showFloor.FoldoutWithBoldLabelPropertyField(floorSettingsFoldoutHeader, showContent))
+ if (showBoundary.FoldoutWithBoldLabelPropertyField(generalSettingsFoldoutHeader, showContent))
{
EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(floorMaterial, materialContent);
- var prevWideMode = EditorGUIUtility.wideMode;
- EditorGUIUtility.wideMode = true;
- EditorGUILayout.PropertyField(floorScale, scaleContent, GUILayout.ExpandWidth(true));
- EditorGUIUtility.wideMode = prevWideMode;
- EditorGUILayout.PropertyField(floorPhysicsLayer);
- EditorGUI.indentLevel--;
- }
+ EditorGUILayout.PropertyField(boundaryHeight);
+ EditorGUILayout.PropertyField(boundaryMaterial, materialContent);
+ EditorGUILayout.PropertyField(physicsLayer);
- EditorGUILayout.Space();
+ EditorGUILayout.Space();
- if (showPlayArea.FoldoutWithBoldLabelPropertyField(playAreaSettingsFoldoutHeader, showContent))
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(playAreaMaterial, materialContent);
- EditorGUILayout.PropertyField(playAreaPhysicsLayer);
- EditorGUI.indentLevel--;
- }
+ if (showFloor.FoldoutWithBoldLabelPropertyField(floorSettingsFoldoutHeader, showContent))
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(floorMaterial, materialContent);
+ EditorGUI.indentLevel--;
+ }
- EditorGUILayout.Space();
+ EditorGUILayout.Space();
- if (showTrackedArea.FoldoutWithBoldLabelPropertyField(trackedAreaSettingsFoldoutHeader, showContent))
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(trackedAreaMaterial, materialContent);
- EditorGUILayout.PropertyField(trackedAreaPhysicsLayer);
- EditorGUI.indentLevel--;
- }
+ EditorGUILayout.Space();
- EditorGUILayout.Space();
+ if (showWalls.FoldoutWithBoldLabelPropertyField(wallSettingsFoldoutHeader, showContent))
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(wallMaterial, materialContent);
+ EditorGUI.indentLevel--;
+ }
- if (showBoundaryWalls.FoldoutWithBoldLabelPropertyField(boundaryWallSettingsFoldoutHeader, showContent))
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(boundaryWallMaterial, materialContent);
- EditorGUILayout.PropertyField(boundaryWallsPhysicsLayer);
- EditorGUI.indentLevel--;
- }
+ EditorGUILayout.Space();
- EditorGUILayout.Space();
+ if (showCeiling.FoldoutWithBoldLabelPropertyField(ceilingSettingsFoldoutHeader, showContent))
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(ceilingMaterial, materialContent);
+ EditorGUI.indentLevel--;
+ }
- if (showBoundaryCeiling.FoldoutWithBoldLabelPropertyField(boundaryCeilingSettingsFoldoutHeader, showContent))
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(boundaryCeilingMaterial, materialContent);
- EditorGUILayout.PropertyField(ceilingPhysicsLayer);
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
+
+ base.OnInspectorGUI();
}
}
}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/Edge.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/Edge.cs
index 3de094827..afbcc96bc 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/Edge.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/Edge.cs
@@ -40,6 +40,7 @@ public Edge(Vector2 pointA, Vector2 pointB)
public Edge(Vector3 pointA, Vector3 pointB) :
// Use the X and Z parameters as our edges are height agnostic.
this(new Vector2(pointA.x, pointA.z), new Vector2(pointB.x, pointB.z))
- { }
+ {
+ }
}
}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/InscribedRectangle.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/InscribedRectangle.cs
index 5eea05a9d..7241f546c 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/InscribedRectangle.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/InscribedRectangle.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System;
@@ -18,23 +18,23 @@ public class InscribedRectangle
///
/// Total number of starting points randomly generated within the boundary.
///
- private const int randomPointCount = 30;
+ private const int RANDOM_POINT_COUNT = 30;
///
/// The total amount of height, in meters, we want to gain with each binary search
/// change before we decide that it's good enough.
///
- private const float minimumHeightGain = 0.01f;
+ private const float MINIMUM_HEIGHT_GAIN = 0.01f;
///
/// Angles to use for fitting the rectangle within the boundary.
///
- private static readonly float[] fitAngles = { 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165 };
+ private static readonly float[] FitAngles = { 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165 };
///
/// Aspect ratios used when fitting rectangles within the boundary.
///
- private static readonly float[] aspectRatios =
+ private static readonly float[] AspectRatios =
{
1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f,
5.0f, 5.5f, 6, 6.5f, 7, 7.5f, 8.0f, 8.5f, 9.0f,
@@ -70,6 +70,11 @@ public class InscribedRectangle
///
public bool IsValid => EdgeUtilities.IsValidPoint(Center);
+ ///
+ /// The defined edges of the described rectangle.
+ ///
+ public Edge[] Edges { get; }
+
///
/// Finds a large inscribed rectangle. Tries to be maximal but this is
/// best effort. The algorithm used was inspired by the blog post
@@ -95,16 +100,18 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
return;
}
+ Edges = geometryEdges;
+
// Clear previous rectangle
Center = EdgeUtilities.InvalidPoint;
Width = 0;
Height = 0;
Angle = 0;
- float minX = EdgeUtilities.maxWidth;
- float minY = EdgeUtilities.maxWidth;
- float maxX = -EdgeUtilities.maxWidth;
- float maxY = -EdgeUtilities.maxWidth;
+ float minX = EdgeUtilities.MaxWidth;
+ float minY = EdgeUtilities.MaxWidth;
+ float maxX = -EdgeUtilities.MaxWidth;
+ float maxY = -EdgeUtilities.MaxWidth;
// Find min x, min y, max x, max y
for (int i = 0; i < geometryEdges.Length; i++)
@@ -134,7 +141,7 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
}
// Generate random points until we have randomPointCount starting points
- var startingPoints = new Vector2[randomPointCount];
+ var startingPoints = new Vector2[RANDOM_POINT_COUNT];
var random = new Random(randomSeed);
for (int i = 0; i < startingPoints.Length; i++)
@@ -151,11 +158,11 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
startingPoints[i] = candidatePoint;
}
- for (int angleIndex = 0; angleIndex < fitAngles.Length; angleIndex++)
+ for (int angleIndex = 0; angleIndex < FitAngles.Length; angleIndex++)
{
for (int pointIndex = 0; pointIndex < startingPoints.Length; pointIndex++)
{
- float angleRadians = MathUtilities.DegreesToRadians(fitAngles[angleIndex]);
+ float angleRadians = MathUtilities.DegreesToRadians(FitAngles[angleIndex]);
// Find the collision point of a cross through the given point at the given angle.
// Note, we are ignoring the return value as we are checking each point's validity
@@ -190,7 +197,7 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
out newHeight))
{
Center = verticalMidpoint;
- Angle = fitAngles[angleIndex];
+ Angle = FitAngles[angleIndex];
Width = newWidth;
Height = newHeight;
}
@@ -215,7 +222,7 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
out newHeight))
{
Center = horizontalMidpoint;
- Angle = fitAngles[angleIndex];
+ Angle = FitAngles[angleIndex];
Width = newWidth;
Height = newHeight;
}
@@ -238,7 +245,7 @@ public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
/// True if all of the required collision points are located, false otherwise.
/// If a point is unable to be found, the appropriate out parameter will be set to .
///
- private bool FindSurroundingCollisionPoints(
+ private static bool FindSurroundingCollisionPoints(
Edge[] geometryEdges,
Vector2 point,
float angleRadians,
@@ -260,7 +267,7 @@ private bool FindSurroundingCollisionPoints(
}
// Define values that are outside of the maximum boundary size.
- float largeValue = EdgeUtilities.maxWidth;
+ float largeValue = EdgeUtilities.MaxWidth;
float smallValue = -largeValue;
// Find the top and bottom collision points by creating a large line segment that goes through the point to MAX and MIN values on Y
@@ -353,17 +360,11 @@ public bool IsInsideBoundary(Vector2 point)
throw new InvalidOperationException("A point cannot be within an invalid rectangle.");
}
- point -= Center;
- point = point.RotatePoint(MathUtilities.DegreesToRadians(-Angle));
-
- var inWidth = Mathf.Abs(point.x) <= (Width * 0.5f);
- var inHeight = Mathf.Abs(point.y) <= (Height * 0.5f);
-
- return (inWidth && inHeight);
+ return EdgeUtilities.IsInsideBoundary(Edges, point);
}
///
- /// Check to see if a rectangle centered at the specified point and oriented at
+ /// Check to see if a rectangle centered at the specified point and oriented at
/// the specified angle will fit within the geometry.
///
/// The boundary geometry.
@@ -372,7 +373,7 @@ public bool IsInsideBoundary(Vector2 point)
/// The width of the rectangle.
/// The height of the rectangle.
///
- private bool CheckRectangleFit(Edge[] geometryEdges, Vector2 centerPoint, float angleRadians, float width, float height)
+ private static bool CheckRectangleFit(Edge[] geometryEdges, Vector2 centerPoint, float angleRadians, float width, float height)
{
float halfWidth = width * 0.5f;
float halfHeight = height * 0.5f;
@@ -425,7 +426,7 @@ private bool CheckRectangleFit(Edge[] geometryEdges, Vector2 centerPoint, float
/// True if a rectangle with an area greater than or equal to minArea was able to be fit
/// within the geometry at centerPoint.
///
- private bool TryFixMaximumRectangle(
+ private static bool TryFixMaximumRectangle(
Edge[] geometryEdges,
Vector2 centerPoint,
float angleRadians,
@@ -467,19 +468,19 @@ private bool TryFixMaximumRectangle(
// For each aspect ratio we do a binary search to find the maximum rectangle that fits,
// though once we start increasing our area by minimumHeightGain we call it good enough.
- for (int i = 0; i < aspectRatios.Length; i++)
+ for (int i = 0; i < AspectRatios.Length; i++)
{
// The height is limited by the width. If a height would make our width exceed maxWidth, it can't be used
- float searchHeightUpperBound = Mathf.Max(maxHeight, maxWidth / aspectRatios[i]);
+ float searchHeightUpperBound = Mathf.Max(maxHeight, maxWidth / AspectRatios[i]);
// Set to the min height that will out perform our previous area at the given aspect ratio. This is 0 the first time.
// Derived from biggestAreaSoFar=height*(height*aspectRatio)
- float searchHeightLowerBound = Mathf.Sqrt(Mathf.Max((width * height), minArea) / aspectRatios[i]);
+ float searchHeightLowerBound = Mathf.Sqrt(Mathf.Max((width * height), minArea) / AspectRatios[i]);
// If the lowest value needed to outperform the previous best is greater than our max,
// this aspect ratio can't outperform what we've already calculated.
if (searchHeightLowerBound > searchHeightUpperBound ||
- searchHeightLowerBound * aspectRatios[i] > maxWidth)
+ searchHeightLowerBound * AspectRatios[i] > maxWidth)
{
continue;
}
@@ -492,16 +493,16 @@ private bool TryFixMaximumRectangle(
if (CheckRectangleFit(geometryEdges,
centerPoint,
angleRadians,
- aspectRatios[i] * currentTestingHeight,
+ AspectRatios[i] * currentTestingHeight,
currentTestingHeight))
{
// Binary search up-ward
// If the rectangle will fit, increase the lower bounds of our binary search
searchHeightLowerBound = currentTestingHeight;
- width = currentTestingHeight * aspectRatios[i];
+ width = currentTestingHeight * AspectRatios[i];
height = currentTestingHeight;
- aspectRatio = aspectRatios[i];
+ aspectRatio = AspectRatios[i];
currentTestingHeight = (searchHeightUpperBound + currentTestingHeight) * 0.5f;
}
else
@@ -511,7 +512,7 @@ private bool TryFixMaximumRectangle(
currentTestingHeight = (currentTestingHeight + searchHeightLowerBound) * 0.5f;
}
}
- while ((searchHeightUpperBound - searchHeightLowerBound) > minimumHeightGain);
+ while ((searchHeightUpperBound - searchHeightLowerBound) > MINIMUM_HEIGHT_GAIN);
}
return (aspectRatio > 0.0f);
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/MixedRealityBoundaryVisualizationProfile.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/MixedRealityBoundaryVisualizationProfile.cs
index bb04072f9..e9aafe60c 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/MixedRealityBoundaryVisualizationProfile.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/MixedRealityBoundaryVisualizationProfile.cs
@@ -1,9 +1,10 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using UnityEngine;
using XRTK.Attributes;
using XRTK.Definitions.Utilities;
+using XRTK.Interfaces.BoundarySystem;
namespace XRTK.Definitions.BoundarySystem
{
@@ -11,188 +12,116 @@ namespace XRTK.Definitions.BoundarySystem
/// Configuration profile settings for setting up boundary visualizations.
///
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Boundary Visualization Profile", fileName = "MixedRealityBoundaryVisualizationProfile", order = (int)CreateProfileMenuItemIndices.BoundaryVisualization)]
- public class MixedRealityBoundaryVisualizationProfile : BaseMixedRealityProfile
+ public class MixedRealityBoundaryVisualizationProfile : BaseMixedRealityServiceProfile
{
- [SerializeField]
- [Tooltip("The approximate height of the play space, in meters.")]
- private float boundaryHeight = 3.0f;
-
- ///
- /// The developer defined height of the boundary, in meters.
- ///
- ///
- /// The BoundaryHeight property is used to create a three dimensional volume for the play space.
- ///
- public float BoundaryHeight => boundaryHeight;
-
- #region Floor settings
+ #region General Settings
[SerializeField]
- [Tooltip("Should the floor be displayed in the scene?")]
- private bool showFloor = true;
+ [Tooltip("Force the boundary to always be displayed in the scene?")]
+ private bool showBoundary = false;
///
- /// Should the boundary system display the floor?
- ///
- public bool ShowFloor => showFloor;
-
- // todo: consider allowing optional custom prefab
-
- [SerializeField]
- [Tooltip("The material to use when displaying the floor.")]
- private Material floorMaterial = null;
-
- ///
- /// The material to use for the floor when created by the boundary system.
- ///
- public Material FloorMaterial => floorMaterial;
-
- [PhysicsLayer]
- [SerializeField]
- [Tooltip("The physics layer to assign to the generated floor.")]
- private int floorPhysicsLayer = 0;
-
- ///
- /// The physics layer to assign to the generated floor.
- ///
- public int FloorPhysicsLayer => floorPhysicsLayer;
-
- [SerializeField]
- [Tooltip("The dimensions of the floor, in meters.")]
- private Vector2 floorScale = new Vector2(10f, 10f);
-
- ///
- /// The size at which to display the rectangular floor plane .
+ /// Should the boundary system display the play area?
///
- public Vector2 FloorScale => floorScale;
-
- #endregion Floor settings
-
- #region Play area settings
+ public bool ShowBoundary => showBoundary;
+ [Min(1f)]
[SerializeField]
- [Tooltip("Should the play area be displayed in the scene?")]
- private bool showPlayArea = true;
+ [Tooltip("The height of the boundary, in meters.")]
+ private float boundaryHeight = 3.0f;
///
- /// Should the boundary system display the play area?
+ /// The developer defined height of the boundary, in meters.
///
- public bool ShowPlayArea => showPlayArea;
+ ///
+ /// The BoundaryHeight property is used to create a three dimensional volume for the play space.
+ ///
+ public float BoundaryHeight => boundaryHeight;
[SerializeField]
- [Tooltip("The material to use when displaying the play area.")]
- private Material playAreaMaterial = null;
+ [Tooltip("The material to use when displaying the boundary.")]
+ private Material boundaryMaterial = null;
///
/// The material to use for the rectangular play area .
///
- public Material PlayAreaMaterial => playAreaMaterial;
+ public Material BoundaryMaterial => boundaryMaterial;
[PhysicsLayer]
[SerializeField]
- [Tooltip("The physics layer to assign to the generated play area.")]
- private int playAreaPhysicsLayer = 2;
+ [Tooltip("The physics layer to assign to all the generated boundary GameObjects.")]
+ private int physicsLayer = 2;
///
- /// The physics layer to assign to the generated play area.
+ /// The physics layer to assign to all the generated boundary s.
///
- public int PlayAreaPhysicsLayer => playAreaPhysicsLayer;
+ public int PhysicsLayer => physicsLayer;
- #endregion Play area settings
+ #endregion General Settings
- #region Tracked area settings
+ #region Floor settings
[SerializeField]
- [Tooltip("Should the tracked area be displayed in the scene?")]
- private bool showTrackedArea = true;
+ [Tooltip("Force the boundary system display the floor?")]
+ private bool showFloor = true;
///
- /// Should the boundary system display the tracked area?
+ /// Force the boundary system display the floor?
///
- public bool ShowTrackedArea => showTrackedArea;
+ public bool ShowFloor => showFloor;
[SerializeField]
- [Tooltip("The material to use when displaying the tracked area.")]
- private Material trackedAreaMaterial = null;
-
- ///
- /// The material to use for the boundary geometry .
- ///
- public Material TrackedAreaMaterial => trackedAreaMaterial;
-
- [PhysicsLayer]
- [SerializeField]
- [Tooltip("The physics layer to assign to the generated tracked area.")]
- private int trackedAreaPhysicsLayer = 2;
+ [Tooltip("The material to use when displaying the floor.\n\nNote: if none is set, boundary material is used.")]
+ private Material floorMaterial = null;
///
- /// The physics layer to assign to the generated tracked area.
+ /// The material to use for the floor when created by the boundary system.
///
- public int TrackedAreaPhysicsLayer => trackedAreaPhysicsLayer;
+ public Material FloorMaterial => floorMaterial;
- #endregion Tracked area settings
+ #endregion Floor settings
#region Boundary wall settings
[SerializeField]
- [Tooltip("Should the boundary walls be displayed in the scene?")]
- private bool showBoundaryWalls = false;
+ [Tooltip("Force the boundary walls be displayed?")]
+ private bool showWalls = false;
///
- /// Should the boundary system display the boundary geometry walls?
+ /// Force the boundary walls be displayed?
///
- public bool ShowBoundaryWalls => showBoundaryWalls;
+ public bool ShowWalls => showWalls;
[SerializeField]
- [Tooltip("The material to use when displaying the boundary walls.")]
- private Material boundaryWallMaterial = null;
+ [Tooltip("The material to use when displaying the boundary walls.\n\nNote: if none is set, boundary material is used.")]
+ private Material wallMaterial = null;
///
/// The material to use for displaying the boundary geometry walls.
///
- public Material BoundaryWallMaterial => boundaryWallMaterial;
-
- [PhysicsLayer]
- [SerializeField]
- [Tooltip("The physics layer to assign to the generated boundary walls.")]
- private int boundaryWallsPhysicsLayer = 2;
-
- ///
- /// The physics layer to assign to the generated boundary walls.
- ///
- public int BoundaryWallsPhysicsLayer => boundaryWallsPhysicsLayer;
+ public Material WallMaterial => wallMaterial;
#endregion Boundary wall settings
#region Boundary ceiling settings
[SerializeField]
- [Tooltip("Should the boundary ceiling be displayed in the scene?")]
- private bool showBoundaryCeiling = false;
+ [Tooltip("Force the boundary ceiling be displayed?")]
+ private bool showCeiling = false;
///
- /// Should the boundary system display the boundary ceiling?
+ /// Force the boundary ceiling be displayed?
///
- public bool ShowBoundaryCeiling => showBoundaryCeiling;
+ public bool ShowCeiling => showCeiling;
[SerializeField]
- [Tooltip("The material to use when displaying the boundary ceiling.")]
- private Material boundaryCeilingMaterial = null;
+ [Tooltip("The material to use when displaying the boundary ceiling.\n\nNote: if none is set, boundary material is used.")]
+ private Material ceilingMaterial = null;
///
/// The material to use for displaying the boundary ceiling.
///
- public Material BoundaryCeilingMaterial => boundaryCeilingMaterial;
-
- [PhysicsLayer]
- [SerializeField]
- [Tooltip("The physics layer to assign to the generated boundary ceiling.")]
- private int ceilingPhysicsLayer = 2;
-
- ///
- /// The physics layer to assign to the generated boundary ceiling.
- ///
- public int CeilingPhysicsLayer => ceilingPhysicsLayer;
+ public Material CeilingMaterial => ceilingMaterial;
#endregion Boundary ceiling settings
}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs
new file mode 100644
index 000000000..83f352081
--- /dev/null
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs
@@ -0,0 +1,25 @@
+// Copyright (c) XRTK. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+namespace XRTK.Definitions.BoundarySystem
+{
+ public enum ProximityAlert
+ {
+ ///
+ /// The tracked object is safely within the boundary.
+ ///
+ Clear = 0,
+ ///
+ /// The tracked object's bounds have touching the boundary.
+ ///
+ Touch,
+ ///
+ /// The tracked object has crossed outside the boundary.
+ ///
+ Exit,
+ ///
+ /// The tracked object has crossed inside the boundary.
+ ///
+ Enter,
+ }
+}
\ No newline at end of file
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs.meta
similarity index 86%
rename from XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs.meta
rename to XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs.meta
index 7202ebdb1..f5ff9ec27 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs.meta
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/BoundarySystem/ProximityAlert.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 09b8ecda83744cb4bbde06155ec420fb
+guid: d8300f51e51c4b5fba9a37db81bc54ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary.meta
deleted file mode 100644
index 4c39f8367..000000000
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 11a169014c2b414f97e09b0748e63437
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs
deleted file mode 100644
index 47cf0e252..000000000
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See LICENSE in the project root for license information.
-
-using UnityEngine.EventSystems;
-using XRTK.Interfaces.BoundarySystem;
-
-namespace XRTK.EventDatum.Boundary
-{
- ///
- /// The data describing the boundary system event.
- ///
- public class BoundaryEventData : GenericBaseEventData
- {
- ///
- /// Is the floor being visualized by the boundary system.
- ///
- public bool IsFloorVisualized { get; private set; }
-
- ///
- /// Is the play area being visualized by the boundary system.
- ///
- public bool IsPlayAreaVisualized { get; private set; }
-
- ///
- /// Is the tracked area being visualized by the boundary system.
- ///
- public bool IsTrackedAreaVisualized { get; private set; }
-
- ///
- /// Are the boundary walls being visualized by the boundary system.
- ///
- public bool AreBoundaryWallsVisualized { get; private set; }
-
- ///
- /// Is the ceiling being visualized by the boundary system.
- ///
- ///
- /// The boundary system defines the ceiling as a plane set at above the floor.
- ///
- public bool IsCeilingVisualized { get; private set; }
-
- ///
- /// Constructor.
- ///
- ///
- public BoundaryEventData(EventSystem eventSystem) : base(eventSystem) { }
-
- public void Initialize(
- IMixedRealityBoundarySystem boundarySystem,
- bool isFloorVisualized,
- bool isPlayAreaVisualized,
- bool isTrackedAreaVisualized,
- bool areBoundaryWallsVisualized,
- bool isCeilingVisualized)
- {
- base.BaseInitialize(boundarySystem);
- IsFloorVisualized = isFloorVisualized;
- IsPlayAreaVisualized = isPlayAreaVisualized;
- IsTrackedAreaVisualized = isTrackedAreaVisualized;
- AreBoundaryWallsVisualized = areBoundaryWallsVisualized;
- IsCeilingVisualized = isCeilingVisualized;
- }
- }
-}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/BoundsExtensions.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/BoundsExtensions.cs
index 6e3d000c2..c9b1f3c96 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/BoundsExtensions.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/BoundsExtensions.cs
@@ -65,6 +65,7 @@ public static class BoundsExtensions
private static readonly Vector3[] rectTransformCorners = new Vector3[4];
#region Public Static Functions
+
///
/// Returns an instance of the 'Bounds' class which is invalid. An invalid 'Bounds' instance
/// is one which has its size vector set to 'float.MaxValue' for all 3 components. The center
@@ -208,7 +209,7 @@ public static void GetFacePositions(this Bounds bounds, Transform transform, ref
}
///
- /// Gets all the corner points and mid points from Renderer's Bounds
+ /// Gets all the corner points and mid points from Bounds
///
///
///
@@ -259,7 +260,7 @@ public static void GetCornerAndMidPointPositions(this Bounds bounds, Transform t
}
///
- /// Gets all the corner points and mid points from Renderer's Bounds, ignoring the z axis
+ /// Gets all the corner points and mid points from Bounds, ignoring the z axis
///
///
///
@@ -335,7 +336,7 @@ public static void GetCornerAndMidPointPositions2D(this Bounds bounds, Transform
/// gameObject that boundingBox bounds.
/// array reference that gets filled with points
/// layerMask to simplify search
- /// The colliders for this gameObject and it's children
+ /// The colliders to use for calculating the bounds of this gameObject
public static void GetColliderBoundsPoints(GameObject target, ref List boundsPoints, LayerMask ignoreLayers, Collider[] colliders = null)
{
if (colliders == null)
@@ -402,7 +403,7 @@ public static void GetColliderBoundsPoints(GameObject target, ref List
/// gameObject that bounding box bounds
/// array reference that gets filled with points
/// layerMask to simplify search
- /// The renderers for this gameObject and it's children
+ /// The renderers to use for calculating the bounds of this gameObject
public static void GetRenderBoundsPoints(GameObject target, ref List boundsPoints, LayerMask ignoreLayers, Renderer[] renderers = null)
{
if (renderers == null)
@@ -419,7 +420,7 @@ public static void GetRenderBoundsPoints(GameObject target, ref List bo
continue;
}
- var bounds = rendererObj.transform.GetRenderBounds();
+ var bounds = rendererObj.transform.GetRenderBounds(ref renderers);
bounds.GetCornerPositions(ref corners);
boundsPoints.AddRange(corners);
@@ -432,9 +433,13 @@ public static void GetRenderBoundsPoints(GameObject target, ref List bo
/// gameObject that bounding box bounds
/// array reference that gets filled with points
/// layerMask to simplify search
- public static void GetMeshFilterBoundsPoints(GameObject target, ref List boundsPoints, LayerMask ignoreLayers)
+ /// The mesh filters to use for calculating the bounds of this gameObject
+ public static void GetMeshFilterBoundsPoints(GameObject target, ref List boundsPoints, LayerMask ignoreLayers, MeshFilter[] meshFilters = null)
{
- var meshFilters = target.GetComponentsInChildren();
+ if (meshFilters == null)
+ {
+ meshFilters = target.GetComponentsInChildren();
+ }
for (int i = 0; i < meshFilters.Length; i++)
{
@@ -501,9 +506,11 @@ public static Bounds Transform(this Bounds bounds, Matrix4x4 transformMatrix)
var newSizeZ = (Mathf.Abs(rotatedExtentsRight.z) + Mathf.Abs(rotatedExtentsUp.z) + Mathf.Abs(rotatedExtentsLook.z)) * 2.0f;
// Construct the transformed 'Bounds' instance
- var transformedBounds = new Bounds();
- transformedBounds.center = transformMatrix.MultiplyPoint(bounds.center);
- transformedBounds.size = new Vector3(newSizeX, newSizeY, newSizeZ);
+ var transformedBounds = new Bounds
+ {
+ center = transformMatrix.MultiplyPoint(bounds.center),
+ size = new Vector3(newSizeX, newSizeY, newSizeZ)
+ };
// Return the instance to the caller
return transformedBounds;
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/CameraExtensions.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/CameraExtensions.cs
index 67d24d17d..3c1aa8f75 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/CameraExtensions.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/CameraExtensions.cs
@@ -66,22 +66,12 @@ public static float GetDistanceForFrustumHeight(this Camera camera, float frustu
/// Is the inside the s frustum?
///
///
- ///
+ ///
///
- public static bool IsInFrustum(this Camera camera, Transform transform)
+ public static bool IsInFrustum(this Camera camera, Bounds bounds)
{
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
- return GeometryUtility.TestPlanesAABB(planes, transform.GetRenderBounds());
- }
-
- ///
- /// Is the inside the s frustum?
- ///
- ///
- ///
- public static bool IsInFrustum(this Camera camera, GameObject gameObject)
- {
- return IsInFrustum(camera, gameObject.transform);
+ return GeometryUtility.TestPlanesAABB(planes, bounds);
}
}
}
\ No newline at end of file
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/TransformExtensions.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/TransformExtensions.cs
index 2168d51f1..acc06a122 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/TransformExtensions.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Extensions/TransformExtensions.cs
@@ -148,12 +148,12 @@ public static Bounds GetColliderBounds(this Transform transform, ref Collider[]
/// Transform of root GameObject the renderers are attached to.
///
///
- /// True, by default, this will sync the rotation to calculate the axis aligned orientation.
+ /// True, by default, this will sync the rotation to calculate the axis aligned orientation.
///
/// Optional cached renderer collection.
/// The total bounds of all renderers attached to this GameObject.
/// If no renderers attached, returns a bounds of center and extents 0
- public static Bounds GetRenderBounds(this Transform transform, bool syncTransform = true, Renderer[] renderers = null)
+ public static Bounds GetRenderBounds(this Transform transform, ref Renderer[] renderers, bool syncTransform = true)
{
// Store current rotation then zero out the rotation so that the bounds
// are computed when the object is in its 'axis aligned orientation'.
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs
new file mode 100644
index 000000000..71e7cd531
--- /dev/null
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs
@@ -0,0 +1,31 @@
+// Copyright (c) XRTK. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace XRTK.Interfaces.BoundarySystem
+{
+ ///
+ /// Mixed Reality Toolkit boundary data provider definition, used to instantiate and manage low level api access specific devices, SDKs, and libraries.
+ ///
+ public interface IMixedRealityBoundaryDataProvider : IMixedRealityDataProvider
+ {
+ ///
+ /// Is the platform's boundary visible?
+ ///
+ bool IsPlatformBoundaryVisible { get; set; }
+
+ ///
+ /// The the platform's boundary configured?
+ ///
+ bool IsPlatformConfigured { get; }
+
+ ///
+ /// Try to get the boundary geometry from the library api.
+ ///
+ /// The list of points associated with the boundary geometry.
+ /// True, if valid geometry was successfully returned, otherwise false.
+ bool TryGetBoundaryGeometry(ref List geometry);
+ }
+}
\ No newline at end of file
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs.meta
similarity index 86%
rename from XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs.meta
rename to XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs.meta
index 5c38e07c2..52abb161c 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/EventDatum/Boundary/BoundaryEventData.cs.meta
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryDataProvider.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 7a5b295dec324d82bee9bd51d54b793e
+guid: abe61e338f3c45b79517a9fe2eb81155
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs
deleted file mode 100644
index 16973b57a..000000000
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundaryHandler.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See LICENSE in the project root for license information.
-
-using UnityEngine.EventSystems;
-using XRTK.EventDatum.Boundary;
-
-namespace XRTK.Interfaces.BoundarySystem
-{
- public interface IMixedRealityBoundaryHandler : IEventSystemHandler
- {
- ///
- /// Raised when the boundary visualization has changed.
- ///
- ///
- void OnBoundaryVisualizationChanged(BoundaryEventData eventData);
- }
-}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundarySystem.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundarySystem.cs
index 76e2687be..a16a3d754 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundarySystem.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/BoundarySystem/IMixedRealityBoundarySystem.cs
@@ -1,140 +1,99 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
+using System;
+using System.Collections.Generic;
using UnityEngine;
-using UnityEngine.Experimental.XR;
using XRTK.Definitions.BoundarySystem;
-using XRTK.Interfaces.Events;
namespace XRTK.Interfaces.BoundarySystem
{
///
- /// Manager interface for a Boundary system in the Mixed Reality Toolkit
- /// All replacement systems for providing Boundary functionality should derive from this interface
+ /// The interface for a Boundary system in the Mixed Reality Toolkit
+ /// All systems for providing Boundary functionality should derive from this interface
///
- public interface IMixedRealityBoundarySystem : IMixedRealityEventSystem, IMixedRealityEventSource
+ public interface IMixedRealityBoundarySystem : IMixedRealitySystem
{
///
- /// The height of the play space, in meters.
- ///
- ///
- /// This is used to create a three dimensional boundary volume.
- ///
- float BoundaryHeight { get; set; }
-
- ///
- /// Enable / disable floor rendering.
- ///
- bool ShowFloor { get; set; }
-
- ///
- /// The size at which to display the rectangular floor plane .
- ///
- Vector2 FloorScale { get; }
-
- ///
- /// The material to use for the floor when created by the boundary system.
- ///
- Material FloorMaterial { get; }
-
- ///
- /// The physics layer that the generated floor is assigned to.
- ///
- int FloorPhysicsLayer { get; set; }
-
- ///
- /// Enable / disable play area rendering.
- ///
- bool ShowPlayArea { get; set; }
-
- ///
- /// The material to use for the rectangular play area .
- ///
- Material PlayAreaMaterial { get; }
-
- ///
- /// The physics layer that the generated play area is assigned to.
+ /// Event raised when a tracked object nears, or crosses the boundary.
///
- int PlayAreaPhysicsLayer { get; set; }
+ event Action BoundaryProximityAlert;
///
- /// Enable / disable tracked area rendering.
+ /// The list of currently tracked objects that will raise s.
///
- bool ShowTrackedArea { get; set; }
+ IReadOnlyList TrackedObjects { get; }
///
- /// The material to use for the boundary geometry .
+ /// The assigned to this system.
///
- Material TrackedAreaMaterial { get; }
-
- ///
- /// The physics layer that the generated tracked area is assigned to.
- ///
- int TrackedAreaPhysicsLayer { get; set; }
+ ///
+ /// Typically with systems, there can be multiple data providers, but in this case there should only ever be one.
+ ///
+ IMixedRealityBoundaryDataProvider BoundaryDataProvider { get; }
///
- /// Enable / disable boundary wall rendering.
+ /// Is the platform or the boundary system's rendered boundary geometry visible?
///
- bool ShowBoundaryWalls { get; set; }
+ ///
+ /// This can enables or disables both the platform's and boundary systems rendered geometry, but the platform can always override their rendering state.
+ ///
+ bool IsVisible { get; set; }
///
- /// The material to use for displaying the boundary geometry walls.
+ /// Has the boundary been properly configured by the user?
///
- Material BoundaryWallMaterial { get; }
+ bool IsConfigured { get; }
///
- /// The physics layer that the generated boundary walls are assigned to.
+ /// Enable or disable the generated boundary geometry.
///
- int BoundaryWallsPhysicsLayer { get; set; }
+ ///
+ /// This cannot or ever will disable or override the platform's built-in boundary systems.
+ ///
+ bool ShowBoundary { get; set; }
///
- /// Enable / disable ceiling rendering.
+ /// The height of the play space, in meters.
///
///
- /// The ceiling is defined as a positioned above the floor.
+ /// This is used to create a three dimensional boundary volume.
///
- bool ShowBoundaryCeiling { get; set; }
+ float BoundaryHeight { get; set; }
///
- /// The material to use for displaying the boundary ceiling.
+ /// Enable or disable floor geometry.
///
- Material BoundaryCeilingMaterial { get; }
+ bool ShowFloor { get; set; }
///
- /// The physics layer that the generated boundary ceiling is assigned to.
+ /// Enable or disable boundary wall geometry.
///
- int CeilingPhysicsLayer { get; set; }
+ bool ShowWalls { get; set; }
///
- /// Two dimensional representation of the geometry of the boundary, as provided
- /// by the platform.
+ /// Enable or disable boundary ceiling geometry.
///
///
- /// BoundaryGeometry should be treated as the outline of the player's space, placed
- /// on the floor.
+ /// The ceiling is defined as a positioned above the floor.
///
- Edge[] Bounds { get; }
+ bool ShowCeiling { get; set; }
///
- /// Indicates the height of the floor, in relation to the coordinate system origin.
+ /// Two dimensional representation of the geometry of the boundary, as provided by the platform.
///
///
- /// If a floor has been located, FloorHeight.HasValue will be true, otherwise it will be false.
+ /// BoundaryGeometry should be treated as the outline of the player's space, placed on the floor.
///
- float? FloorHeight { get; }
+ Edge[] BoundaryBounds { get; }
///
- /// Determines if a location is within the specified area of the boundary space.
+ /// Determines if a is within the area of the boundary space.
///
- /// The location to be checked.
- /// The type of boundary space being checked.
- /// True if the location is within the specified area of the boundary space.
- ///
- /// Use:
- /// Boundary.Type.PlayArea for the inscribed volume
- /// Boundary.Type.TrackedArea for the area defined by the boundary edges.
- ///
- bool Contains(Vector3 location, Boundary.Type boundaryType = Boundary.Type.TrackedArea);
+ /// The position to be checked.
+ /// Is this position using local or worldspace coordinate space?
+ /// True if the location is within the area of the boundary space, otherwise false.
+ bool IsInsideBoundary(Vector3 position, Space referenceSpace = Space.World);
///
/// Returns the description of the inscribed rectangular bounds.
@@ -147,33 +106,13 @@ public interface IMixedRealityBoundarySystem : IMixedRealityEventSystem, IMixedR
bool TryGetRectangularBoundsParams(out Vector2 center, out float angle, out float width, out float height);
///
- /// Gets the that represents the user's floor.
- ///
- /// The floor visualization object or null if one does not exist.
- GameObject GetFloorVisualization();
-
- ///
- /// Gets the that represents the user's play area.
- ///
- /// The play area visualization object or null if one does not exist.
- GameObject GetPlayAreaVisualization();
-
- ///
- /// Gets the that represents the user's tracked area.
- ///
- /// The tracked area visualization object or null if one does not exist.
- GameObject GetTrackedAreaVisualization();
-
- ///
- /// Gets the that represents the user's boundary walls.
+ /// Registers the of a to be tracked for s.
///
- /// The boundary wall visualization object or null if one does not exist.
- GameObject GetBoundaryWallVisualization();
+ void RegisterTrackedObject(GameObject gameObject);
///
- /// Gets the that represents the upper surface of the user's boundary.
+ /// Unregisters the of a from s.
///
- /// The boundary ceiling visualization object or null if one does not exist.
- GameObject GetBoundaryCeilingVisualization();
+ void UnregisterTrackedObject(GameObject gameObject);
}
}
\ No newline at end of file
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/BoundarySystem/MixedRealityBoundarySystem.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/BoundarySystem/MixedRealityBoundarySystem.cs
index 78b8900f7..4680c6b90 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/BoundarySystem/MixedRealityBoundarySystem.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/BoundarySystem/MixedRealityBoundarySystem.cs
@@ -1,14 +1,12 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
-using System.Collections;
+using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
using UnityEngine;
-using UnityEngine.EventSystems;
-using UnityEngine.Experimental.XR;
-using UnityEngine.XR;
using XRTK.Definitions.BoundarySystem;
-using XRTK.EventDatum.Boundary;
using XRTK.Extensions;
using XRTK.Interfaces.BoundarySystem;
using XRTK.Utilities;
@@ -18,8 +16,8 @@ namespace XRTK.Services.BoundarySystem
///
/// The Boundary system controls the presentation and display of the users boundary in a scene.
///
- [System.Runtime.InteropServices.Guid("FE458876-CC0F-4B6F-9459-544DDF6A9263")]
- public class MixedRealityBoundarySystem : BaseEventSystem, IMixedRealityBoundarySystem
+ [Guid("FE458876-CC0F-4B6F-9459-544DDF6A9263")]
+ public class MixedRealityBoundarySystem : BaseSystem, IMixedRealityBoundarySystem
{
///
/// Constructor.
@@ -28,194 +26,36 @@ public class MixedRealityBoundarySystem : BaseEventSystem, IMixedRealityBoundary
public MixedRealityBoundarySystem(MixedRealityBoundaryVisualizationProfile profile)
: base(profile)
{
- showFloor = profile.ShowFloor;
- floorPhysicsLayer = profile.FloorPhysicsLayer;
- FloorScale = profile.FloorScale;
- FloorMaterial = profile.FloorMaterial;
- showPlayArea = profile.ShowPlayArea;
- PlayAreaMaterial = profile.PlayAreaMaterial;
- playAreaPhysicsLayer = profile.PlayAreaPhysicsLayer;
+ showBoundary = profile.ShowBoundary;
BoundaryHeight = profile.BoundaryHeight;
- showTrackedArea = profile.ShowTrackedArea;
- TrackedAreaMaterial = profile.TrackedAreaMaterial;
- trackedAreaPhysicsLayer = profile.TrackedAreaPhysicsLayer;
- showBoundaryWalls = profile.ShowBoundaryWalls;
- BoundaryWallMaterial = profile.BoundaryWallMaterial;
- boundaryWallsPhysicsLayer = profile.BoundaryWallsPhysicsLayer;
- showCeiling = profile.ShowBoundaryCeiling;
- BoundaryCeilingMaterial = profile.BoundaryCeilingMaterial;
- ceilingPhysicsLayer = profile.CeilingPhysicsLayer;
- }
-
- #region IMixedRealityService Implementation
-
- private BoundaryEventData boundaryEventData = null;
-
- ///
- public override void Initialize()
- {
- base.Initialize();
-
- if (!Application.isPlaying)
- {
- return;
- }
-
- boundaryEventData = new BoundaryEventData(EventSystem.current);
- }
-
- ///
- public override void Enable()
- {
- base.Enable();
-
- if (!Application.isPlaying)
- {
- return;
- }
-
- CalculateBoundaryBounds();
- Boundary.visible = true;
-
- if (ShowFloor)
- {
- GetFloorVisualization();
- }
+ BoundaryMaterial = profile.BoundaryMaterial;
+ boundaryPhysicsLayer = profile.PhysicsLayer;
- if (ShowPlayArea)
- {
- GetPlayAreaVisualization();
- }
-
- if (ShowTrackedArea)
- {
- GetTrackedAreaVisualization();
- }
-
- if (ShowBoundaryWalls)
- {
- GetBoundaryWallVisualization();
- }
-
- if (ShowBoundaryWalls)
- {
- GetBoundaryCeilingVisualization();
- }
-
- RaiseBoundaryVisualizationChanged();
- }
-
- ///
- public override void Disable()
- {
- base.Disable();
-
- if (!Application.isPlaying)
- {
- return;
- }
-
- showFloor = false;
- showPlayArea = false;
- showTrackedArea = false;
- showBoundaryWalls = false;
- showCeiling = false;
- Boundary.visible = false;
- }
-
- ///
- public override void Destroy()
- {
- base.Destroy();
- // Destroys the parent and all the child objects
- boundaryVisualizationParent.Destroy();
- RaiseBoundaryVisualizationChanged();
- }
-
- ///
- /// Raises an event to indicate that the visualization of the boundary has been changed by the boundary system.
- ///
- private void RaiseBoundaryVisualizationChanged()
- {
- if (!Application.isPlaying) { return; }
- boundaryEventData.Initialize(this, ShowFloor, ShowPlayArea, ShowTrackedArea, ShowBoundaryWalls, ShowBoundaryCeiling);
- HandleEvent(boundaryEventData, OnVisualizationChanged);
- }
-
- ///
- /// Event sent whenever the boundary visualization changes.
- ///
- private static readonly ExecuteEvents.EventFunction OnVisualizationChanged =
- delegate (IMixedRealityBoundaryHandler handler, BaseEventData eventData)
- {
- var boundaryEventData = ExecuteEvents.ValidateEventData(eventData);
- handler.OnBoundaryVisualizationChanged(boundaryEventData);
- };
-
- #endregion IMixedRealityService Implementation
-
- #region IMixedRealtyEventSystem Implementation
-
- ///
- public override void HandleEvent(BaseEventData eventData, ExecuteEvents.EventFunction eventHandler)
- {
- base.HandleEvent(eventData, eventHandler);
- }
-
- ///
- /// Registers the to listen for boundary events.
- ///
- ///
- public override void Register(GameObject listener)
- {
- base.Register(listener);
- }
-
- ///
- /// UnRegisters the to listen for boundary events.
- /// ///
- ///
- public override void Unregister(GameObject listener)
- {
- base.Unregister(listener);
- }
-
- #endregion
-
- #region IMixedRealityEventSource Implementation
-
- ///
- bool IEqualityComparer.Equals(object x, object y)
- {
- // There shouldn't be other Boundary Managers to compare to.
- return false;
- }
-
- ///
- public int GetHashCode(object obj)
- {
- return Mathf.Abs(SourceName.GetHashCode());
+ showFloor = profile.ShowFloor;
+ FloorMaterial = profile.FloorMaterial.IsNull()
+ ? profile.BoundaryMaterial
+ : profile.FloorMaterial;
+
+ showWalls = profile.ShowWalls;
+ WallMaterial = profile.WallMaterial.IsNull()
+ ? profile.BoundaryMaterial
+ : profile.WallMaterial;
+
+ showCeiling = profile.ShowCeiling;
+ CeilingMaterial = profile.CeilingMaterial.IsNull()
+ ? profile.BoundaryMaterial
+ : profile.CeilingMaterial;
}
- ///
- public uint SourceId { get; } = 0;
-
- ///
- public string SourceName { get; } = "Mixed Reality Boundary System";
-
- #endregion IMixedRealityEventSource Implementation
-
- #region IMixedRealityBoundarySystem Implementation
-
///
/// Layer used to tell the (non-floor) boundary objects to not accept raycasts
///
- private const int DefaultIgnoreRaycastLayer = 2;
+ private const int DEFAULT_IGNORE_RAYCAST_LAYER = 2;
///
/// The thickness of three dimensional generated boundary objects.
///
- private const float BoundaryObjectThickness = 0.005f;
+ private const float BOUNDARY_OBJECT_THICKNESS = 0.005f;
///
/// A small offset to avoid render conflicts, primarily with the floor.
@@ -223,358 +63,515 @@ public int GetHashCode(object obj)
///
/// This offset is used to avoid consuming multiple physics layers.
///
- private const float BoundaryObjectRenderOffset = 0.001f;
+ private const float BOUNDARY_OBJECT_RENDER_OFFSET = 0.001f;
- private GameObject boundaryVisualizationParent;
+ private readonly Dictionary trackedObjects = new Dictionary(3);
- ///
- /// Parent which will encapsulate all of the teleportable boundary visualizations.
- ///
- private GameObject BoundaryVisualizationParent
+ private InscribedRectangle rectangularBounds;
+
+ private GameObject boundaryVisualizationRoot = null;
+
+ private GameObject BoundarySystemVisualizationRoot
{
get
{
- if (!boundaryVisualizationParent.IsNull())
+ if (!boundaryVisualizationRoot.IsNull())
{
- return boundaryVisualizationParent;
+ return boundaryVisualizationRoot;
}
- var visualizationParent = new GameObject("Boundary System Visualizations");
+ boundaryVisualizationRoot = new GameObject(nameof(BoundarySystemVisualizationRoot));
var playspaceTransform = MixedRealityToolkit.CameraSystem != null
? MixedRealityToolkit.CameraSystem.MainCameraRig.PlayspaceTransform
: CameraCache.Main.transform.parent;
- visualizationParent.transform.SetParent(playspaceTransform, false);
- return boundaryVisualizationParent = visualizationParent;
+ boundaryVisualizationRoot.transform.SetParent(playspaceTransform, false);
+
+ return boundaryVisualizationRoot;
}
}
- ///
- public float BoundaryHeight { get; set; }
-
- private bool showFloor;
+ private GameObject boundaryVisualization = null;
- ///
- public bool ShowFloor
+ private GameObject BoundaryVisualization
{
- get => showFloor;
- set
+ get
{
- if (showFloor == value) { return; }
-
- showFloor = value;
-
- if (value && (currentFloorObject.IsNull()))
+ if (!boundaryVisualization.IsNull())
{
- GetFloorVisualization();
+ return boundaryVisualization;
}
- if (!currentFloorObject.IsNull())
+ // If we do not have boundary edges, we cannot render them.
+ if (BoundaryBounds.Length == 0)
{
- currentFloorObject.SetActive(value);
+ return null;
}
- RaiseBoundaryVisualizationChanged();
- }
- }
+ // Get the rectangular bounds.
+ if (!TryGetRectangularBoundsParams(out var center, out var angle, out var width, out var height))
+ {
+ // No rectangular bounds, therefore cannot create the play area.
+ return null;
+ }
- ///
- public Vector2 FloorScale { get; }
+ // Render the rectangular bounds.
+ if (!EdgeUtilities.IsValidPoint(center))
+ {
+ // Invalid rectangle / play area not found
+ return null;
+ }
- ///
- public Material FloorMaterial { get; }
+ boundaryVisualization = GameObject.CreatePrimitive(PrimitiveType.Quad);
+ boundaryVisualization.name = nameof(BoundaryVisualization);
+ boundaryVisualization.layer = boundaryPhysicsLayer;
+ boundaryVisualization.transform.Translate(new Vector3(center.x, BOUNDARY_OBJECT_RENDER_OFFSET, center.y));
+ boundaryVisualization.transform.Rotate(new Vector3(90f, -angle, 0.0f));
+ boundaryVisualization.transform.localScale = new Vector3(width, height, 1.0f);
+ boundaryVisualization.GetComponent().sharedMaterial = BoundaryMaterial;
+ boundaryVisualization.transform.SetParent(BoundarySystemVisualizationRoot.transform, false);
- private bool showPlayArea;
+ boundaryVisualization.AddComponent();
- private int floorPhysicsLayer;
+ // Get the line vertices
+ var lineVertices = new List();
- ///
- public int FloorPhysicsLayer
- {
- get
- {
- if (!currentFloorObject.IsNull())
+ for (int i = 0; i < BoundaryBounds.Length; i++)
{
- floorPhysicsLayer = currentFloorObject.layer;
+ lineVertices.Add(new Vector3(BoundaryBounds[i].PointA.x, 0f, BoundaryBounds[i].PointA.y));
}
- return floorPhysicsLayer;
- }
- set
- {
- floorPhysicsLayer = value;
+ // Add the first vertex again to ensure the loop closes.
+ lineVertices.Add(lineVertices[0]);
- if (!currentFloorObject.IsNull())
- {
- currentFloorObject.layer = floorPhysicsLayer;
- }
+ // Configure the renderer properties.
+ const float lineWidth = 0.01f;
+ var lineRenderer = boundaryVisualization.GetComponent();
+ lineRenderer.sharedMaterial = BoundaryMaterial;
+ lineRenderer.useWorldSpace = false;
+ lineRenderer.startWidth = lineWidth;
+ lineRenderer.endWidth = lineWidth;
+ lineRenderer.positionCount = lineVertices.Count;
+ lineRenderer.SetPositions(lineVertices.ToArray());
+
+ boundaryVisualization.SetActive(showBoundary);
+
+ return boundaryVisualization;
}
}
- ///
- public bool ShowPlayArea
+ private GameObject floorVisualization = null;
+
+ private GameObject FloorVisualization
{
- get => showPlayArea;
- set
+ get
{
- if (showPlayArea == value) { return; }
-
- showPlayArea = value;
-
- if (value && currentPlayAreaObject.IsNull())
+ if (!floorVisualization.IsNull())
{
- GetPlayAreaVisualization();
+ return floorVisualization;
}
- if (!currentPlayAreaObject.IsNull())
- {
- currentPlayAreaObject.SetActive(value);
- }
+ var position = MixedRealityToolkit.CameraSystem != null
+ ? MixedRealityToolkit.CameraSystem.MainCameraRig.PlayspaceTransform.position
+ : CameraCache.Main.transform.parent.position;
- RaiseBoundaryVisualizationChanged();
+ // Render the floor.
+ floorVisualization = GameObject.CreatePrimitive(PrimitiveType.Cube);
+ floorVisualization.name = nameof(FloorVisualization);
+ floorVisualization.transform.Translate(new Vector3(
+ position.x,
+ position.y - (floorVisualization.transform.localScale.y * 0.5f),
+ position.z));
+ floorVisualization.layer = boundaryPhysicsLayer;
+ floorVisualization.GetComponent().sharedMaterial = FloorMaterial;
+ floorVisualization.transform.SetParent(BoundarySystemVisualizationRoot.transform, false);
+ floorVisualization.SetActive(showFloor);
+
+ return floorVisualization;
}
}
- private bool showTrackedArea;
+ private GameObject wallVisualization = null;
- ///
- public int PlayAreaPhysicsLayer
+ private GameObject WallVisualization
{
get
{
- if (!currentPlayAreaObject.IsNull())
+ if (!wallVisualization.IsNull())
{
- playAreaPhysicsLayer = currentPlayAreaObject.layer;
+ return wallVisualization;
}
- return playAreaPhysicsLayer;
- }
- set
- {
- playAreaPhysicsLayer = value;
+ if (BoundaryBounds.Length == 0)
+ {
+ // If we do not have boundary edges, we cannot render walls.
+ return null;
+ }
+
+ wallVisualization = new GameObject(nameof(WallVisualization))
+ {
+ layer = boundaryPhysicsLayer
+ };
- if (!currentPlayAreaObject.IsNull())
+ for (int i = 0; i < BoundaryBounds.Length; i++)
{
- currentPlayAreaObject.layer = playAreaPhysicsLayer;
+ var wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
+ wall.name = $"Wall_{i}";
+ wall.GetComponent().sharedMaterial = WallMaterial;
+ wall.transform.localScale = new Vector3((BoundaryBounds[i].PointB - BoundaryBounds[i].PointA).magnitude, BoundaryHeight, BOUNDARY_OBJECT_THICKNESS);
+ wall.layer = boundaryPhysicsLayer;
+
+ // Position and rotate the wall.
+ var midpoint = Vector2.Lerp(BoundaryBounds[i].PointA, BoundaryBounds[i].PointB, 0.5f);
+ wall.transform.SetParent(wallVisualization.transform, false);
+ wall.transform.position = new Vector3(midpoint.x, (BoundaryHeight * 0.5f), midpoint.y);
+ var rotationAngle = MathUtilities.GetAngleBetween(BoundaryBounds[i].PointB, BoundaryBounds[i].PointA);
+ wall.transform.rotation = Quaternion.Euler(0.0f, -rotationAngle, 0.0f);
}
+
+ wallVisualization.transform.SetParent(BoundarySystemVisualizationRoot.transform, false);
+
+ return wallVisualization;
}
}
- private int playAreaPhysicsLayer;
-
- ///
- public Material PlayAreaMaterial { get; }
+ private GameObject ceilingVisualization = null;
- ///
- public bool ShowTrackedArea
+ private GameObject CeilingVisualization
{
- get => showTrackedArea;
- set
+ get
{
- if (showTrackedArea == value) { return; }
- showTrackedArea = value;
+ if (!ceilingVisualization.IsNull())
+ {
+ return ceilingVisualization;
+ }
- if (value && currentTrackedAreaObject.IsNull())
+ if (BoundaryBounds.Length == 0)
{
- GetTrackedAreaVisualization();
+ // If we do not have boundary edges, we cannot render a ceiling.
+ return null;
}
- if (!currentTrackedAreaObject.IsNull())
+ // Get the smallest rectangle that contains the entire boundary.
+ var boundaryBoundingBox = new Bounds();
+
+ for (int i = 0; i < BoundaryBounds.Length; i++)
{
- currentTrackedAreaObject.SetActive(value);
+ // The boundary geometry is a closed loop. As such, we can encapsulate only PointA of each Edge.
+ boundaryBoundingBox.Encapsulate(new Vector3(BoundaryBounds[i].PointA.x, BoundaryHeight * 0.5f, BoundaryBounds[i].PointA.y));
}
- RaiseBoundaryVisualizationChanged();
+ ceilingVisualization = GameObject.CreatePrimitive(PrimitiveType.Cube);
+ ceilingVisualization.name = nameof(CeilingVisualization);
+ ceilingVisualization.layer = DEFAULT_IGNORE_RAYCAST_LAYER;
+ ceilingVisualization.transform.localScale = new Vector3(boundaryBoundingBox.size.x, BOUNDARY_OBJECT_THICKNESS, boundaryBoundingBox.size.z);
+ ceilingVisualization.transform.Translate(new Vector3(
+ boundaryBoundingBox.center.x,
+ BoundaryHeight + (ceilingVisualization.transform.localScale.y * 0.5f),
+ boundaryBoundingBox.center.z));
+ ceilingVisualization.GetComponent().sharedMaterial = CeilingMaterial;
+ ceilingVisualization.layer = boundaryPhysicsLayer;
+ ceilingVisualization.transform.SetParent(BoundarySystemVisualizationRoot.transform, false);
+
+ return ceilingVisualization;
}
}
- private bool showBoundaryWalls = false;
-
- private int trackedAreaPhysicsLayer;
+ #region IMixedRealityService Implementation
///
- public int TrackedAreaPhysicsLayer
+ public override void Enable()
{
- get
+ base.Enable();
+
+ BoundaryDataProvider = MixedRealityToolkit.GetService();
+
+ if (!Application.isPlaying || BoundaryDataProvider == null) { return; }
+
+ // Reset the bounds
+ BoundaryBounds = new Edge[0];
+ rectangularBounds = null;
+
+ // Get the boundary geometry.
+ var boundaryGeometry = new List(0);
+ var boundaryEdges = new List(0);
+
+ if (BoundaryDataProvider.TryGetBoundaryGeometry(ref boundaryGeometry) && boundaryGeometry.Count > 0)
{
- if (!currentTrackedAreaObject.IsNull())
+ for (int i = 0; i < boundaryGeometry.Count; i++)
{
- trackedAreaPhysicsLayer = currentTrackedAreaObject.layer;
+ var pointA = boundaryGeometry[i];
+ var pointB = boundaryGeometry[(i + 1) % boundaryGeometry.Count];
+ boundaryEdges.Add(new Edge(pointA, pointB));
}
- return trackedAreaPhysicsLayer;
+ BoundaryBounds = boundaryEdges.ToArray();
+ // We always use the same seed so that from run to run, the inscribed bounds are consistent.
+ rectangularBounds = new InscribedRectangle(BoundaryBounds, Mathf.Abs("Mixed Reality Toolkit".GetHashCode()));
}
- set
+ else
{
- trackedAreaPhysicsLayer = value;
-
- if (!currentTrackedAreaObject.IsNull())
- {
- currentTrackedAreaObject.layer = trackedAreaPhysicsLayer;
- }
+ Debug.LogWarning("No Boundary Geometry found");
}
- }
- ///
- public Material TrackedAreaMaterial { get; }
+ BoundarySystemVisualizationRoot.SetActive(true);
+ }
///
- public bool ShowBoundaryWalls
+ public override void Update()
{
- get => showBoundaryWalls;
- set
- {
- if (showBoundaryWalls == value) { return; }
+ base.Update();
+
+ if (!Application.isPlaying || BoundaryDataProvider == null) { return; }
- showBoundaryWalls = value;
+ foreach (var trackedObjectStatus in trackedObjects)
+ {
+ var trackedBounds = trackedObjectStatus.Key;
+ var status = trackedObjectStatus.Value;
+ var isAnyCornerInsideBoundary = false;
+ var isCornersFullyInsideBoundary = true;
- if (value && currentBoundaryWallObject.IsNull())
+ for (int i = 0; i < trackedBounds.BoundsCornerPoints.Length; i++)
{
- GetBoundaryWallVisualization();
+ var result = IsInsideBoundary(trackedBounds.BoundsCornerPoints[i]);
+ isAnyCornerInsideBoundary |= result;
+ isCornersFullyInsideBoundary &= result;
}
- if (!currentBoundaryWallObject.IsNull())
+ switch (status)
{
- currentBoundaryWallObject.SetActive(value);
+ case ProximityAlert.Clear:
+ if (isAnyCornerInsideBoundary && !isCornersFullyInsideBoundary)
+ {
+ status = ProximityAlert.Touch;
+ }
+
+ // In case object moves faster than updates can track it's ejection or
+ // if the object was already outside of the boundary.
+ if (!isCornersFullyInsideBoundary)
+ {
+ status = ProximityAlert.Exit;
+ }
+
+ break;
+ case ProximityAlert.Touch:
+ if (isCornersFullyInsideBoundary)
+ {
+ status = ProximityAlert.Clear;
+ }
+
+ if (!isAnyCornerInsideBoundary)
+ {
+ status = ProximityAlert.Exit;
+ }
+
+ break;
+ case ProximityAlert.Exit:
+ // Left and re-entered the boundary
+ if (isAnyCornerInsideBoundary)
+ {
+ status = ProximityAlert.Enter;
+ }
+
+ break;
+ case ProximityAlert.Enter:
+ if (isAnyCornerInsideBoundary)
+ {
+ status = isCornersFullyInsideBoundary
+ ? ProximityAlert.Clear
+ : ProximityAlert.Touch;
+ }
+ else
+ {
+ status = ProximityAlert.Exit;
+ }
+
+ break;
}
- RaiseBoundaryVisualizationChanged();
+ if (status != trackedObjectStatus.Value)
+ {
+ trackedObjects[trackedBounds] = status;
+ BoundaryProximityAlert?.Invoke(trackedBounds.gameObject, status);
+ }
}
}
- private bool showCeiling = false;
+ ///
+ public override void Disable()
+ {
+ base.Disable();
- private int boundaryWallsPhysicsLayer;
+ if (!Application.isPlaying || BoundaryDataProvider == null) { return; }
+
+ if (!boundaryVisualizationRoot.IsNull())
+ {
+ boundaryVisualizationRoot.SetActive(false);
+ }
+ }
///
- public int BoundaryWallsPhysicsLayer
+ public override void Destroy()
{
- get
+ base.Destroy();
+
+ if (!Application.isPlaying || BoundaryDataProvider == null) { return; }
+
+ // Destroys the parent and all the child objects
+ boundaryVisualizationRoot.Destroy();
+ }
+
+ #endregion IMixedRealityService Implementation
+
+ #region Implementation of IMixedRealityBoundarySystem
+
+ ///
+ public event Action BoundaryProximityAlert;
+
+ ///
+ public IReadOnlyList TrackedObjects => trackedObjects.Keys.Select(cache => cache.gameObject).ToList();
+
+ ///
+ public IMixedRealityBoundaryDataProvider BoundaryDataProvider { get; private set; }
+
+ ///
+ public bool IsVisible
+ {
+ get => BoundaryDataProvider != null && BoundaryDataProvider.IsPlatformBoundaryVisible ||
+ BoundarySystemVisualizationRoot.activeInHierarchy &&
+ (ShowBoundary ||
+ ShowFloor ||
+ ShowWalls ||
+ ShowCeiling);
+ set
{
- if (!currentBoundaryWallObject.IsNull())
+ if (BoundaryDataProvider != null)
{
- boundaryWallsPhysicsLayer = currentBoundaryWallObject.layer;
+ BoundaryDataProvider.IsPlatformBoundaryVisible = value;
}
- return boundaryWallsPhysicsLayer;
+ BoundarySystemVisualizationRoot.SetActive(value);
}
+ }
+
+ private bool showBoundary;
+
+ ///
+ public bool ShowBoundary
+ {
+ get => showBoundary;
set
{
- boundaryWallsPhysicsLayer = value;
+ showBoundary = value;
- if (!currentBoundaryWallObject.IsNull())
+ if (!BoundaryVisualization.IsNull())
{
- currentBoundaryWallObject.layer = boundaryWallsPhysicsLayer;
+ BoundaryVisualization.SetActive(value);
}
}
}
- ///
- public Material BoundaryWallMaterial { get; }
+ ///
+ public bool IsConfigured => BoundaryDataProvider?.IsPlatformConfigured ?? false;
- ///
- public bool ShowBoundaryCeiling
+ ///
+ public float BoundaryHeight { get; set; }
+
+ private readonly int boundaryPhysicsLayer;
+
+ private bool showFloor;
+
+ ///
+ public bool ShowFloor
{
- get => showCeiling;
+ get => showFloor;
set
{
- if (showCeiling == value) { return; }
-
- showCeiling = value;
-
- if (value && currentCeilingObject.IsNull())
- {
- GetBoundaryCeilingVisualization();
- }
+ showFloor = value;
- if (!currentCeilingObject.IsNull())
+ if (!FloorVisualization.IsNull())
{
- currentCeilingObject.SetActive(value);
+ FloorVisualization.SetActive(value);
}
-
- RaiseBoundaryVisualizationChanged();
}
}
- private int ceilingPhysicsLayer;
+ private Material FloorMaterial { get; }
- ///
- public int CeilingPhysicsLayer
+ private Material BoundaryMaterial { get; }
+
+ private bool showWalls = false;
+
+ ///
+ public bool ShowWalls
{
- get
+ get => showWalls;
+ set
{
- if (!currentCeilingObject.IsNull())
+ showWalls = value;
+
+ if (!WallVisualization.IsNull())
{
- ceilingPhysicsLayer = currentCeilingObject.layer;
+ WallVisualization.SetActive(value);
}
-
- return ceilingPhysicsLayer;
}
+ }
+
+ private Material WallMaterial { get; }
+
+ private bool showCeiling = false;
+
+ ///
+ public bool ShowCeiling
+ {
+ get => showCeiling;
set
{
- ceilingPhysicsLayer = value;
+ showCeiling = value;
- if (!currentCeilingObject.IsNull())
+ if (!CeilingVisualization.IsNull())
{
- currentFloorObject.layer = ceilingPhysicsLayer;
+ CeilingVisualization.SetActive(value);
}
}
}
- ///
- public Material BoundaryCeilingMaterial { get; }
-
- ///
- public Edge[] Bounds { get; private set; } = new Edge[0];
+ private Material CeilingMaterial { get; }
- ///
- public float? FloorHeight { get; private set; }
+ ///
+ public Edge[] BoundaryBounds { get; private set; } = new Edge[0];
- ///
- public bool Contains(Vector3 location, Boundary.Type boundaryType = Boundary.Type.TrackedArea)
+ ///
+ public bool IsInsideBoundary(Vector3 position, Space referenceSpace = Space.World)
{
- if (!EdgeUtilities.IsValidPoint(location))
+ if (!EdgeUtilities.IsValidPoint(position))
{
// Invalid location.
return false;
}
- if (!FloorHeight.HasValue)
- {
- // No floor.
- return false;
- }
-
// Handle the user teleporting (boundary moves with them).
var playspaceTransform = MixedRealityToolkit.CameraSystem != null
? MixedRealityToolkit.CameraSystem.MainCameraRig.PlayspaceTransform
: CameraCache.Main.transform.parent;
- location = playspaceTransform.InverseTransformPoint(location);
- if (FloorHeight.Value > location.y ||
- BoundaryHeight < location.y)
+ if (referenceSpace == Space.World)
+ {
+ position = playspaceTransform.InverseTransformPoint(position);
+ }
+
+ if (position.y < 0 ||
+ position.y > BoundaryHeight)
{
// Location below the floor or above the boundary height.
return false;
}
// Boundary coordinates are always "on the floor"
- var point = new Vector2(location.x, location.z);
-
- switch (boundaryType)
- {
- case Boundary.Type.PlayArea when rectangularBounds != null:
- // Check the inscribed rectangle.
- return rectangularBounds.IsInsideBoundary(point);
- case Boundary.Type.TrackedArea:
- // Check the geometry
- return EdgeUtilities.IsInsideBoundary(Bounds, point);
- default:
- // Not in either boundary type.
- return false;
- }
+ var point = new Vector2(position.x, position.z);
+ return EdgeUtilities.IsInsideBoundary(BoundaryBounds, point);
}
- ///
+ ///
public bool TryGetRectangularBoundsParams(out Vector2 center, out float angle, out float width, out float height)
{
if (rectangularBounds == null || !rectangularBounds.IsValid)
@@ -600,298 +597,29 @@ public bool TryGetRectangularBoundsParams(out Vector2 center, out float angle, o
return true;
}
- ///
- public GameObject GetFloorVisualization()
- {
- if (!Application.isPlaying) { return null; }
-
- if (!currentFloorObject.IsNull())
- {
- return currentFloorObject;
- }
-
- if (!FloorHeight.HasValue)
- {
- // We were unable to locate the floor.
- return null;
- }
-
- var floorScale = FloorScale;
- var position = MixedRealityToolkit.CameraSystem != null
- ? MixedRealityToolkit.CameraSystem.MainCameraRig.PlayspaceTransform.position
- : CameraCache.Main.transform.parent.position;
-
- // Render the floor.
- currentFloorObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
- currentFloorObject.name = "Boundary System Floor";
- currentFloorObject.transform.localScale = new Vector3(floorScale.x, BoundaryObjectThickness, floorScale.y);
- currentFloorObject.transform.Translate(new Vector3(
- position.x,
- FloorHeight.Value - (currentFloorObject.transform.localScale.y * 0.5f),
- position.z));
- currentFloorObject.layer = FloorPhysicsLayer;
- currentFloorObject.GetComponent().sharedMaterial = FloorMaterial;
-
- currentFloorObject.transform.parent = BoundaryVisualizationParent.transform;
-
- return currentFloorObject;
- }
-
- ///
- public GameObject GetPlayAreaVisualization()
- {
- if (!Application.isPlaying) { return null; }
-
- if (!currentPlayAreaObject.IsNull())
- {
- return currentPlayAreaObject;
- }
-
- // Get the rectangular bounds.
-
- if (!TryGetRectangularBoundsParams(out var center, out var angle, out var width, out var height))
- {
- // No rectangular bounds, therefore cannot create the play area.
- return null;
- }
-
- // Render the rectangular bounds.
- if (!EdgeUtilities.IsValidPoint(center))
- {
- // Invalid rectangle / play area not found
- return null;
- }
-
- currentPlayAreaObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
- currentPlayAreaObject.name = "Play Area";
- currentPlayAreaObject.layer = PlayAreaPhysicsLayer;
- currentPlayAreaObject.transform.Translate(new Vector3(center.x, BoundaryObjectRenderOffset, center.y));
- currentPlayAreaObject.transform.Rotate(new Vector3(90f, -angle, 0.0f));
- currentPlayAreaObject.transform.localScale = new Vector3(width, height, 1.0f);
- currentPlayAreaObject.GetComponent().sharedMaterial = PlayAreaMaterial;
-
- currentPlayAreaObject.transform.parent = BoundaryVisualizationParent.transform;
-
- return currentPlayAreaObject;
- }
-
- ///
- public GameObject GetTrackedAreaVisualization()
- {
- if (!Application.isPlaying) { return null; }
-
- if (!currentTrackedAreaObject.IsNull())
- {
- return currentTrackedAreaObject;
- }
-
- if (Bounds.Length == 0)
- {
- // If we do not have boundary edges, we cannot render them.
- return null;
- }
-
- // Get the line vertices
- var lineVertices = new List();
-
- for (int i = 0; i < Bounds.Length; i++)
- {
- lineVertices.Add(new Vector3(Bounds[i].PointA.x, 0f, Bounds[i].PointA.y));
- }
-
- // Add the first vertex again to ensure the loop closes.
- lineVertices.Add(lineVertices[0]);
-
- // We use an empty object and attach a line renderer.
- currentTrackedAreaObject = new GameObject("Tracked Area")
- {
- layer = DefaultIgnoreRaycastLayer
- };
-
- var position = MixedRealityToolkit.CameraSystem != null
- ? MixedRealityToolkit.CameraSystem.MainCameraRig.PlayspaceTransform.position
- : CameraCache.Main.transform.parent.position;
-
- currentTrackedAreaObject.AddComponent();
- currentTrackedAreaObject.transform.Translate(
- new Vector3(position.x, BoundaryObjectRenderOffset, position.z));
- currentPlayAreaObject.layer = TrackedAreaPhysicsLayer;
-
- // Configure the renderer properties.
- const float lineWidth = 0.01f;
- var lineRenderer = currentTrackedAreaObject.GetComponent();
- lineRenderer.sharedMaterial = TrackedAreaMaterial;
- lineRenderer.useWorldSpace = false;
- lineRenderer.startWidth = lineWidth;
- lineRenderer.endWidth = lineWidth;
- lineRenderer.positionCount = lineVertices.Count;
- lineRenderer.SetPositions(lineVertices.ToArray());
-
- currentTrackedAreaObject.transform.parent = BoundaryVisualizationParent.transform;
-
- return currentTrackedAreaObject;
- }
-
- ///
- public GameObject GetBoundaryWallVisualization()
- {
- if (!Application.isPlaying) { return null; }
-
- if (!currentBoundaryWallObject.IsNull())
- {
- return currentBoundaryWallObject;
- }
-
- if (!FloorHeight.HasValue)
- {
- // We need a floor on which to place the walls.
- return null;
- }
-
- if (Bounds.Length == 0)
- {
- // If we do not have boundary edges, we cannot render walls.
- return null;
- }
-
- currentBoundaryWallObject = new GameObject("Tracked Area Walls")
- {
- layer = BoundaryWallsPhysicsLayer
- };
-
- // Create and parent the child objects
- const float wallDepth = BoundaryObjectThickness;
-
- for (int i = 0; i < Bounds.Length; i++)
- {
- var wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
- wall.name = $"Wall_{i}";
- wall.GetComponent().sharedMaterial = BoundaryWallMaterial;
- wall.transform.localScale = new Vector3((Bounds[i].PointB - Bounds[i].PointA).magnitude, BoundaryHeight, wallDepth);
- wall.layer = DefaultIgnoreRaycastLayer;
-
- // Position and rotate the wall.
- var mid = Vector2.Lerp(Bounds[i].PointA, Bounds[i].PointB, 0.5f);
- wall.transform.position = new Vector3(mid.x, (BoundaryHeight * 0.5f), mid.y);
- var rotationAngle = MathUtilities.GetAngleBetween(Bounds[i].PointB, Bounds[i].PointA);
- wall.transform.rotation = Quaternion.Euler(0.0f, -rotationAngle, 0.0f);
-
- wall.transform.parent = currentBoundaryWallObject.transform;
- }
-
- currentBoundaryWallObject.transform.parent = BoundaryVisualizationParent.transform;
-
- return currentBoundaryWallObject;
- }
-
- ///
- public GameObject GetBoundaryCeilingVisualization()
+ ///
+ public void RegisterTrackedObject(GameObject gameObject)
{
- if (!Application.isPlaying) { return null; }
-
- if (!currentCeilingObject.IsNull())
- {
- return currentCeilingObject;
- }
+ var boundsCached = gameObject.EnsureComponent();
- if (Bounds.Length == 0)
+ if (!trackedObjects.TryGetValue(boundsCached, out _))
{
- // If we do not have boundary edges, we cannot render a ceiling.
- return null;
+ trackedObjects.Add(boundsCached, ProximityAlert.Clear);
}
-
- // Get the smallest rectangle that contains the entire boundary.
- var boundaryBoundingBox = new Bounds();
-
- for (int i = 0; i < Bounds.Length; i++)
- {
- // The boundary geometry is a closed loop. As such, we can encapsulate only PointA of each Edge.
- boundaryBoundingBox.Encapsulate(new Vector3(Bounds[i].PointA.x, BoundaryHeight * 0.5f, Bounds[i].PointA.y));
- }
-
- // Render the ceiling.
- const float ceilingDepth = BoundaryObjectThickness;
- currentCeilingObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
- currentCeilingObject.name = "Ceiling";
- currentCeilingObject.layer = DefaultIgnoreRaycastLayer;
- currentCeilingObject.transform.localScale = new Vector3(boundaryBoundingBox.size.x, ceilingDepth, boundaryBoundingBox.size.z);
- currentCeilingObject.transform.Translate(new Vector3(
- boundaryBoundingBox.center.x,
- BoundaryHeight + (currentCeilingObject.transform.localScale.y * 0.5f),
- boundaryBoundingBox.center.z));
- currentCeilingObject.GetComponent().sharedMaterial = BoundaryCeilingMaterial;
- currentCeilingObject.layer = CeilingPhysicsLayer;
- currentCeilingObject.transform.parent = BoundaryVisualizationParent.transform;
-
- return currentCeilingObject;
}
- #endregion IMixedRealityBoundarySystem Implementation
-
- ///
- /// The largest rectangle that is contained withing the play space geometry.
- ///
- private InscribedRectangle rectangularBounds;
-
- private GameObject currentFloorObject;
- private GameObject currentPlayAreaObject;
- private GameObject currentTrackedAreaObject;
- private GameObject currentBoundaryWallObject;
- private GameObject currentCeilingObject;
-
- ///
- /// Retrieves the boundary geometry and creates the boundary and inscribed play space volumes.
- ///
- private void CalculateBoundaryBounds()
+ ///
+ public void UnregisterTrackedObject(GameObject gameObject)
{
- // Reset the bounds
- Bounds = new Edge[0];
- FloorHeight = null;
- rectangularBounds = null;
-
- // Boundaries are supported for Room Scale experiences only.
- if (XRDevice.GetTrackingSpaceType() != TrackingSpaceType.RoomScale)
- {
- return;
- }
-
- // Get the boundary geometry.
- var boundaryGeometry = new List(0);
- var boundaryEdges = new List(0);
-
- if (Boundary.TryGetGeometry(boundaryGeometry, Boundary.Type.TrackedArea) && boundaryGeometry.Count > 0)
- {
- // FloorHeight starts out as null. Use a suitably high value for the floor to ensure
- // that we do not accidentally set it too low.
- var floorHeight = float.MaxValue;
-
- for (int i = 0; i < boundaryGeometry.Count; i++)
- {
- var pointA = boundaryGeometry[i];
- var pointB = boundaryGeometry[(i + 1) % boundaryGeometry.Count];
- boundaryEdges.Add(new Edge(pointA, pointB));
-
- floorHeight = Mathf.Min(floorHeight, boundaryGeometry[i].y);
- }
+ var boundsCache = gameObject.GetComponent();
+ if (boundsCache == null) { return; }
- FloorHeight = floorHeight;
- Bounds = boundaryEdges.ToArray();
- CreateInscribedBounds();
- }
- else if (XRSettings.enabled && Boundary.configured)
+ if (trackedObjects.TryGetValue(boundsCache, out _))
{
- Debug.LogWarning("Failed to calculate boundary bounds.");
+ trackedObjects.Remove(boundsCache);
}
}
- ///
- /// Creates the two dimensional volume described by the largest rectangle that
- /// is contained withing the play space geometry and the configured height.
- ///
- private void CreateInscribedBounds()
- {
- // We always use the same seed so that from run to run, the inscribed bounds are consistent.
- rectangularBounds = new InscribedRectangle(Bounds, Mathf.Abs("Mixed Reality Toolkit".GetHashCode()));
- }
+ #endregion Implementation of IMixedRealityBoundarySystem
}
}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/MixedRealityToolkit.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/MixedRealityToolkit.cs
index c029f2000..2d7f02012 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/MixedRealityToolkit.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/MixedRealityToolkit.cs
@@ -432,7 +432,11 @@ private void InitializeServiceLocator()
if (ActiveProfile.IsBoundarySystemEnabled)
{
- if (!TryCreateAndRegisterService(ActiveProfile.BoundarySystemSystemType, out _, ActiveProfile.BoundaryVisualizationProfile) || BoundarySystem == null)
+ if (TryCreateAndRegisterService(ActiveProfile.BoundarySystemSystemType, out var service, ActiveProfile.BoundaryVisualizationProfile) && BoundarySystem != null)
+ {
+ TryRegisterDataProviderConfigurations(ActiveProfile.BoundaryVisualizationProfile.RegisteredServiceConfigurations, service);
+ }
+ else
{
Debug.LogError("Failed to start the Boundary System!");
}
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs
new file mode 100644
index 000000000..6fd01e1ba
--- /dev/null
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs
@@ -0,0 +1,80 @@
+// Copyright (c) XRTK. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+using UnityEngine;
+using XRTK.Extensions;
+
+namespace XRTK.Utilities
+{
+ ///
+ /// used to cache s information about this
+ ///
+ public class BoundsCache : MonoBehaviour
+ {
+ private Bounds bounds = default;
+
+ ///
+ /// The bounds of the object
+ ///
+ public Bounds Bounds => bounds;
+
+ [SerializeField]
+ private bool useColliderData = true;
+
+ [SerializeField]
+ private Collider[] colliders = null;
+
+ ///
+ /// The collection of s for this object.
+ ///
+ public Collider[] Colliders => colliders;
+
+ [SerializeField]
+ private bool useRendererData = true;
+
+ [SerializeField]
+ private Renderer[] renderers = null;
+
+ ///
+ /// The collection of s for this object.
+ ///
+ public Renderer[] Renderers => renderers;
+
+ private Vector3[] boundsCornerPoints = new Vector3[0];
+
+ ///
+ /// The bounds corner points in world space.
+ ///
+ public Vector3[] BoundsCornerPoints => boundsCornerPoints;
+
+ private void Start()
+ {
+ if (useColliderData)
+ {
+ bounds.Encapsulate(transform.GetColliderBounds(ref colliders));
+ }
+
+ if (useRendererData)
+ {
+ bounds.Encapsulate(transform.GetRenderBounds(ref renderers));
+ }
+
+ if (!bounds.IsValid())
+ {
+ Debug.LogError($"Bounds calculation was invalid for {gameObject.name}!");
+ return;
+ }
+
+ bounds.GetCornerPositionsWorldSpace(transform, ref boundsCornerPoints);
+ }
+
+ private void Update()
+ {
+ if (bounds.IsValid())
+ {
+ // update the bounds corner points.
+ bounds.GetCornerPositionsWorldSpace(transform, ref boundsCornerPoints);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs.meta
new file mode 100644
index 000000000..140618d98
--- /dev/null
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/BoundsCache.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5dfa998c390f351408f9c9378d74bd44
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/EdgeUtilities.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/EdgeUtilities.cs
index ea2062466..5368472a3 100644
--- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/EdgeUtilities.cs
+++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Utilities/EdgeUtilities.cs
@@ -15,10 +15,10 @@ public static class EdgeUtilities
/// A value that should be larger than the maximum boundary width.
///
///
- /// This value is used to ensure that line segments are created
+ /// This value is used to ensure that line segments are created
/// that will intersect with a piece of the room boundary.
///
- internal static readonly float maxWidth = 10000f;
+ internal static readonly float MaxWidth = 10000f;
///
/// A value representing an invalid point.
@@ -26,12 +26,12 @@ public static class EdgeUtilities
public static readonly Vector2 InvalidPoint = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
///
- /// Determines if the specified point is within the provided geometry.
+ /// Determines if the specified point is within the provided .
///
/// The geometry for which we are checking the point.
/// The point being checked.
///
- /// True if the point falls within the geometry, false otherwise.
+ /// True if the point falls within the geometry, otherwise false.
///
public static bool IsInsideBoundary(Edge[] geometryEdges, Vector2 point)
{
@@ -40,9 +40,9 @@ public static bool IsInsideBoundary(Edge[] geometryEdges, Vector2 point)
return false;
}
- // Check if a ray to the right (X+) intersects with an
+ // Check if a ray to the right (X+) intersects with an
// odd number of edges (inside) or an even number of edges (outside)
- var rightEdge = new Edge(point, new Vector2(maxWidth, point.y));
+ var rightEdge = new Edge(point, new Vector2(MaxWidth, point.y));
int intersections = 0;
for (int i = 0; i < geometryEdges.Length; i++)