Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
near pointer interactions using collision (#560)
Browse files Browse the repository at this point in the history
* near pointer interactions using collision

* revert

* Removed unused serialization

* updated sdk

* Feature/pni change requests (#577)

* Update ColliderExtensions.cs

* Update CollisionExtensions.cs

* updated submodules

* updated sdk

* updated sdk

Co-authored-by: Dino Fejzagic <dino.f@live.de>
  • Loading branch information
StephenHodgson and FejZa authored May 14, 2020
1 parent 89e91fa commit a7e68a6
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class MixedRealityInputSystemProfileInspector : MixedRealityServiceProfil
private SerializedProperty gazeCursorPrefab;

private SerializedProperty pointingExtent;
private SerializedProperty pointingRaycastLayerMasks;
private SerializedProperty pointerRaycastLayerMasks;
private SerializedProperty drawDebugPointingRays;
private SerializedProperty debugPointingRayColors;

Expand Down Expand Up @@ -55,7 +55,7 @@ protected override void OnEnable()
gazeCursorPrefab = serializedObject.FindProperty(nameof(gazeCursorPrefab));

pointingExtent = serializedObject.FindProperty(nameof(pointingExtent));
pointingRaycastLayerMasks = serializedObject.FindProperty(nameof(pointingRaycastLayerMasks));
pointerRaycastLayerMasks = serializedObject.FindProperty(nameof(pointerRaycastLayerMasks));
drawDebugPointingRays = serializedObject.FindProperty(nameof(drawDebugPointingRays));
debugPointingRayColors = serializedObject.FindProperty(nameof(debugPointingRayColors));

Expand Down Expand Up @@ -120,7 +120,7 @@ public override void OnInspectorGUI()
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(pointingExtent);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(pointingRaycastLayerMasks, true);
EditorGUILayout.PropertyField(pointerRaycastLayerMasks, true);
EditorGUILayout.Space();

EditorGUI.BeginChangeCheck();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using UnityEngine;
using UnityEngine.Serialization;
using XRTK.Attributes;
using XRTK.Definitions.Controllers.Hands;
using XRTK.Definitions.Utilities;
Expand Down Expand Up @@ -68,13 +69,14 @@ public SystemType GazeProviderType
public float PointingExtent => pointingExtent;

[SerializeField]
[Tooltip("The LayerMasks, in prioritized order, that are used to determine the GazeTarget when raycasting.")]
private LayerMask[] pointingRaycastLayerMasks = { UnityEngine.Physics.DefaultRaycastLayers };
[Tooltip("The Physics Layers, in prioritized order, that are used to determine the pointers target when raycasting.")]
[FormerlySerializedAs("pointingRaycastLayerMasks")]
private LayerMask[] pointerRaycastLayerMasks = { UnityEngine.Physics.DefaultRaycastLayers };

/// <summary>
/// The LayerMasks, in prioritized order, that are used to determine the GazeTarget when raycasting.
/// The Physics Layers, in prioritized order, that are used to determine the <see cref="IPointerResult.CurrentPointerTarget"/> when raycasting.
/// </summary>
public LayerMask[] PointingRaycastLayerMasks => pointingRaycastLayerMasks;
public LayerMask[] PointerRaycastLayerMasks => pointerRaycastLayerMasks;

[SerializeField]
private bool drawDebugPointingRays = false;
Expand Down Expand Up @@ -179,4 +181,4 @@ public MixedRealityGesturesProfile GesturesProfile

#endregion Profile Options
}
}
}
23 changes: 21 additions & 2 deletions Runtime/Extensions/ColliderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) XRTK. 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;
Expand All @@ -11,7 +11,7 @@ namespace XRTK.Extensions.XRTK.Extensions
public static class ColliderExtensions
{
/// <summary>
/// Gets all the corner points of the collider's bounds in world space.
/// Gets all the corner points of the colliders bounds in world space.
/// </summary>
/// <param name="collider"></param>
/// <param name="transform"></param>
Expand All @@ -38,5 +38,24 @@ public static void GetCornerPositionsWorldSpace(this Collider collider, Transfor
positions[i] = positions[i].RotateAroundPoint(bounds.center, transform.rotation);
}
}

/// <summary>
/// Checks if a collision is valid using a prioritized layer mask collection.
/// </summary>
/// <param name="collider"></param>
/// <param name="prioritizedLayerMasks"></param>
/// <returns>True, if the collision is valid.</returns>
public static bool IsValidCollision(this Collider collider, LayerMask[] prioritizedLayerMasks)
{
for (int i = 0; i < prioritizedLayerMasks.Length; i++)
{
if (collider.gameObject.layer.IsInLayerMask(prioritizedLayerMasks[i]))
{
return true;
}
}

return false;
}
}
}
21 changes: 21 additions & 0 deletions Runtime/Extensions/CollisionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using UnityEngine;

namespace XRTK.Extensions.XRTK.Extensions
{
public static class CollisionExtensions
{
/// <summary>
/// Checks if a collision is valid using a prioritized layer mask collection.
/// </summary>
/// <param name="collision"></param>
/// <param name="prioritizedLayerMasks"></param>
/// <returns>True, if the collision is valid.</returns>
public static bool IsValidCollision(this Collision collision, LayerMask[] prioritizedLayerMasks)
{
return collision.collider.IsValidCollision(prioritizedLayerMasks);
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Extensions/CollisionExtensions.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Runtime/Interfaces/InputSystem/IMixedRealityFocusProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public interface IMixedRealityFocusProvider : IMixedRealitySourceStateHandler, I
float GlobalPointingExtent { get; }

/// <summary>
/// The layer masks for the focus pointers to raycast against.
/// The Physics Layers, in prioritized order, that are used to determine the <see cref="IPointerResult.CurrentPointerTarget"/> when raycasting.
/// </summary>
LayerMask[] FocusLayerMasks { get; }
LayerMask[] GlobalPointerRaycastLayerMasks { get; }

/// <summary>
/// The Camera the <see cref="UnityEngine.EventSystems.EventSystem"/> uses to raycast against.
Expand Down
24 changes: 16 additions & 8 deletions Runtime/Interfaces/InputSystem/IMixedRealityPointer.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// 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 UnityEngine;
using XRTK.Definitions.InputSystem;
using XRTK.Definitions.Physics;
using XRTK.Interfaces.InputSystem.Handlers;
using XRTK.Interfaces.Physics;
Expand Down Expand Up @@ -52,7 +53,12 @@ public interface IMixedRealityPointer : IEqualityComparer
IMixedRealityTeleportHotSpot TeleportHotSpot { get; set; }

/// <summary>
/// Has the conditions for the interaction been satisfied to enable the interaction?
/// The <see cref="Collider"/> used for determining and raising near interactions.
/// </summary>
Collider NearInteractionCollider { get; }

/// <summary>
/// Has the conditions been satisfied to enable the interaction of this pointer?
/// </summary>
bool IsInteractionEnabled { get; }

Expand All @@ -67,23 +73,25 @@ public interface IMixedRealityPointer : IEqualityComparer
float DefaultPointerExtent { get; }

/// <summary>
/// The raycast rays.
/// The pointers raycast collection.
/// </summary>
RayStep[] Rays { get; }

/// <summary>
/// The physics layers to use when raycasting.
/// The Physics Layers, in prioritized order, that are used to determine the <see cref="IPointerResult.CurrentPointerTarget"/> when raycasting.
/// </summary>
/// <remarks>If set, will override the <see cref="IMixedRealityInputSystem"/>'s default raycasting layer mask array.</remarks>
/// <remarks>
/// If set, will override the <see cref="MixedRealityInputSystemProfile.PointerRaycastLayerMasks"/>'s default raycasting layer mask array.
/// </remarks>
/// <example>
/// Allow the pointer to hit SR, but first prioritize any DefaultRaycastLayers (potentially behind SR)
/// Allow the pointer to hit SR, but first prioritize any <see cref="Physics.DefaultRaycastLayers"/> (potentially behind SR)
/// <code language="csharp"><![CDATA[
/// int sr = LayerMask.GetMask("SR");
/// int nonSR = Physics.DefaultRaycastLayers &amp; ~sr;
/// IMixedRealityPointer.PrioritizedLayerMasksOverride = new LayerMask[] { nonSR, sr };
/// IMixedRealityPointer.PointerRaycastLayerMasksOverride = new LayerMask[] { nonSR, sr };
/// ]]></code>
/// </example>
LayerMask[] PrioritizedLayerMasksOverride { get; set; }
LayerMask[] PointerRaycastLayerMasksOverride { get; set; }

/// <summary>
/// The currently targeted focus handler.
Expand Down
27 changes: 15 additions & 12 deletions Runtime/Services/InputSystem/FocusProvider.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -55,7 +55,7 @@ float IMixedRealityFocusProvider.GlobalPointingExtent
private LayerMask[] focusLayerMasks = null;

/// <inheritdoc />
public LayerMask[] FocusLayerMasks
public LayerMask[] GlobalPointerRaycastLayerMasks
{
get
{
Expand All @@ -64,7 +64,7 @@ public LayerMask[] FocusLayerMasks
if (MixedRealityToolkit.HasActiveProfile &&
MixedRealityToolkit.Instance.ActiveProfile.IsInputSystemEnabled)
{
return focusLayerMasks = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.PointingRaycastLayerMasks;
return focusLayerMasks = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.PointerRaycastLayerMasks;
}

return focusLayerMasks = new LayerMask[] { Physics.DefaultRaycastLayers };
Expand Down Expand Up @@ -133,7 +133,7 @@ private bool IsSetupValid
[Serializable]
private class PointerData : IPointerResult, IEquatable<PointerData>
{
private const int IgnoreRaycastLayer = 2;
private const int IGNORE_RAYCAST_LAYER = 2;

public readonly IMixedRealityPointer Pointer;

Expand Down Expand Up @@ -268,8 +268,8 @@ public void UpdateHit(PointerHitResult hitResult, GameObject syncTarget)
syncedPointerTarget = CurrentPointerTarget;

prevPhysicsLayer = CurrentPointerTarget.layer;
Debug.Assert(prevPhysicsLayer != IgnoreRaycastLayer, $"Failed to get a valid raycast layer for {syncedPointerTarget.name}: {LayerMask.LayerToName(prevPhysicsLayer)}");
CurrentPointerTarget.SetLayerRecursively(IgnoreRaycastLayer);
Debug.Assert(prevPhysicsLayer != IGNORE_RAYCAST_LAYER, $"Failed to get a valid raycast layer for {syncedPointerTarget.name}: {LayerMask.LayerToName(prevPhysicsLayer)}");
CurrentPointerTarget.SetLayerRecursively(IGNORE_RAYCAST_LAYER);

var grabPoint = Pointer.OverrideGrabPoint ?? focusDetails.EndPoint;

Expand Down Expand Up @@ -376,7 +376,7 @@ public void UpdateFocusLockedHit()
}

/// <summary>
/// Rest the currently focused object data.
/// Reset the currently focused object data.
/// </summary>
/// <param name="clearPreviousObject">Optional flag to choose not to clear the previous object.</param>
public void ResetFocusedObjects(bool clearPreviousObject = true)
Expand Down Expand Up @@ -636,7 +636,7 @@ private void EnsureUiRaycastCameraSetup()

// The raycast camera is used to raycast into the UI scene,
// it doesn't need to render anything so is disabled
// The default settings are all that is necessary
// The default settings are all that is necessary
uiRaycastCamera = cameraObject.EnsureComponent<Camera>();
uiRaycastCamera.enabled = false;
}
Expand Down Expand Up @@ -817,7 +817,7 @@ private void UpdatePointer(PointerData pointer)
else
{
// Otherwise, continue
var prioritizedLayerMasks = (pointer.Pointer.PrioritizedLayerMasksOverride ?? FocusLayerMasks);
var prioritizedLayerMasks = (pointer.Pointer.PointerRaycastLayerMasksOverride ?? GlobalPointerRaycastLayerMasks);

physicsHitResult.Clear();

Expand Down Expand Up @@ -906,25 +906,28 @@ private static void RaycastPhysics(IMixedRealityPointer pointer, LayerMask[] pri
switch (pointer.RaycastMode)
{
case RaycastMode.Simple:
if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointerRays[i], prioritizedLayerMasks, out var simplePhysicsHit))
if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointerRays[i], prioritizedLayerMasks, out var simplePhysicsHit) &&
simplePhysicsHit.collider != pointer.NearInteractionCollider)
{
// Set the pointer source's origin ray to this step
UpdatePointerRayOnHit(pointerRays, simplePhysicsHit, i, rayStartDistance, hitResult);
return;
}
break;
case RaycastMode.Box:
// TODO box raycast mode
Debug.LogWarning("Box Raycasting Mode not supported for pointers.");
break;
case RaycastMode.Sphere:
if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointerRays[i], pointer.SphereCastRadius, prioritizedLayerMasks, out var spherePhysicsHit))
if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointerRays[i], pointer.SphereCastRadius, prioritizedLayerMasks, out var spherePhysicsHit) &&
spherePhysicsHit.collider != pointer.NearInteractionCollider)
{
// Set the pointer source's origin ray to this step
UpdatePointerRayOnHit(pointerRays, spherePhysicsHit, i, rayStartDistance, hitResult);
return;
}
break;
// TODO SphereOverlap
// TODO Sphere Overlap
default:
Debug.LogError($"Invalid raycast mode {pointer.RaycastMode} for {pointer.PointerName} pointer.");
break;
Expand Down
7 changes: 4 additions & 3 deletions Runtime/Services/InputSystem/GazeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using XRTK.Interfaces.InputSystem;
using XRTK.Interfaces.InputSystem.Handlers;
using XRTK.Interfaces.Providers.Controllers;
using XRTK.Services;
using XRTK.Services.InputSystem.Pointers;
using XRTK.Services.InputSystem.Sources;
using XRTK.Utilities;
Expand All @@ -29,7 +30,7 @@ public class GazeProvider : MonoBehaviour, IMixedRealityGazeProvider, IMixedReal
private float maxGazeCollisionDistance = 10.0f;

/// <summary>
/// The LayerMasks, in prioritized order, that are used to determine the GazeTarget when raycasting.
/// The Physics layers, in prioritized order, that are used to determine the GazeTarget when raycasting.
/// <example>
/// <para>Allow the cursor to hit SR, but first prioritize any DefaultRaycastLayers (potentially behind SR)</para>
/// <code language="csharp"><![CDATA[
Expand All @@ -40,7 +41,7 @@ public class GazeProvider : MonoBehaviour, IMixedRealityGazeProvider, IMixedReal
/// </example>
/// </summary>
[SerializeField]
[Tooltip("The LayerMasks, in prioritized order, that are used to determine the GazeTarget when raycasting.")]
[Tooltip("The Physics layers, in prioritized order, that are used to determine the GazeTarget when raycasting.")]
private LayerMask[] raycastLayerMasks = { Physics.DefaultRaycastLayers };

/// <summary>
Expand Down Expand Up @@ -158,7 +159,7 @@ public InternalGazePointer(GazeProvider gazeProvider, string pointerName, IMixed
: base(pointerName, inputSourceParent)
{
this.gazeProvider = gazeProvider;
PrioritizedLayerMasksOverride = raycastLayerMasks;
PointerRaycastLayerMasksOverride = raycastLayerMasks;
this.pointerExtent = pointerExtent;
this.gazeTransform = gazeTransform;
this.stabilizer = stabilizer;
Expand Down
Loading

0 comments on commit a7e68a6

Please sign in to comment.