/// <inheritdoc />
        public bool SphereCast(RayStep step, float radius, LayerMask[] prioritizedLayerMasks, bool focusIndividualCompoundCollider, out MixedRealityRaycastHit hitInfo)
        {
            var result = MixedRealityRaycaster.RaycastSpherePhysicsStep(step, radius, step.Length, prioritizedLayerMasks, focusIndividualCompoundCollider, out RaycastHit physicsHit);

            hitInfo = new MixedRealityRaycastHit(result, physicsHit);
            return(result);
        }
예제 #2
0
        private void SphereRaycastStepUpdate(RayStep rayStep)
        {
            bool  isHit;
            float scaleOverride = ScaleOverride;

            // Do the cast!
            float size = scaleOverride > 0 ? scaleOverride : transform.lossyScale.x * sphereSize;

            isHit = MixedRealityRaycaster.RaycastSpherePhysicsStep(rayStep, size, maxDistance, magneticSurfaces, out RaycastHit result);

            OnSurface = isHit;

            // Enforce CloseDistance
            Vector3 hitDelta = result.point - rayStep.Origin;
            float   length   = hitDelta.magnitude;

            if (length < closeDistance)
            {
                result.point = rayStep.Origin + rayStep.Direction * closeDistance;
            }

            // Apply results
            if (isHit)
            {
                GoalPosition = result.point + surfaceNormalOffset * result.normal + surfaceRayOffset * rayStep.Direction;
                GoalRotation = CalculateMagnetismOrientation(rayStep.Direction, result.normal);
            }
        }
예제 #3
0
        /// <summary>
        /// Perform a Unity physics Raycast to determine which scene objects with a collider is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointer"></param>
        /// <param name="prioritizedLayerMasks"></param>
        private static void RaycastPhysics(PointerData pointer, LayerMask[] prioritizedLayerMasks)
        {
            bool       isHit        = false;
            int        rayStepIndex = 0;
            RayStep    rayStep      = default(RayStep);
            RaycastHit physicsHit   = default(RaycastHit);

            Debug.Assert(pointer.Pointer.Rays != null, "No valid rays for pointer");
            Debug.Assert(pointer.Pointer.Rays.Length > 0, "No valid rays for pointer");

            // Check raycast for each step in the pointing source
            for (int i = 0; i < pointer.Pointer.Rays.Length; i++)
            {
                switch (pointer.Pointer.RaycastMode)
                {
                case RaycastModeType.Simple:
                    if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointer.Pointer.Rays[i], prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        isHit        = true;
                        rayStep      = pointer.Pointer.Rays[i];
                        rayStepIndex = i;
                    }
                    break;

                case RaycastModeType.Box:
                    Debug.LogWarning("Box Raycasting Mode not supported for pointers.");
                    break;

                case RaycastModeType.Sphere:
                    if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointer.Pointer.Rays[i], pointer.Pointer.SphereCastRadius, prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        isHit        = true;
                        rayStep      = pointer.Pointer.Rays[i];
                        rayStepIndex = i;
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (isHit)
                {
                    break;
                }
            }

            if (isHit)
            {
                pointer.UpdateHit(physicsHit, rayStep, rayStepIndex);
            }
            else
            {
                pointer.UpdateHit();
            }
        }
예제 #4
0
        /// <summary>
        /// Perform a Unity physics Raycast to determine which scene objects with a collider is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointer"></param>
        /// <param name="prioritizedLayerMasks"></param>
        /// <param name="hitResult"></param>
        private static void RaycastPhysics(IMixedRealityPointer pointer, LayerMask[] prioritizedLayerMasks, PointerHitResult hitResult)
        {
            float rayStartDistance = 0;
            var   pointerRays      = pointer.Rays;

            if (pointerRays == null)
            {
                Debug.LogError($"No valid rays for {pointer.PointerName} pointer.");
                return;
            }

            if (pointerRays.Length <= 0)
            {
                Debug.LogError($"No valid rays for {pointer.PointerName} pointer");
                return;
            }

            // Check raycast for each step in the pointing source
            for (int i = 0; i < pointerRays.Length; i++)
            {
                switch (pointer.RaycastMode)
                {
                case RaycastMode.Simple:
                    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) &&
                        spherePhysicsHit.collider != pointer.NearInteractionCollider)
                    {
                        // Set the pointer source's origin ray to this step
                        UpdatePointerRayOnHit(pointerRays, spherePhysicsHit, i, rayStartDistance, hitResult);
                        return;
                    }
                    break;

                // TODO Sphere Overlap
                default:
                    Debug.LogError($"Invalid raycast mode {pointer.RaycastMode} for {pointer.PointerName} pointer.");
                    break;
                }

                rayStartDistance += pointer.Rays[i].Length;
            }
        }
        /// <inheritdoc />
        public bool SphereCast(RayStep step, float radius, LayerMask[] prioritizedLayerMasks, bool focusIndividualCompoundCollider, out MixedRealityRaycastHit hitInfo)
        {
            Profiler.BeginSample("[MRTK] DefaultRaycastProvider.SphereCast");

            var result = MixedRealityRaycaster.RaycastSpherePhysicsStep(step, radius, step.Length, prioritizedLayerMasks, focusIndividualCompoundCollider, out RaycastHit physicsHit);

            hitInfo = new MixedRealityRaycastHit(result, physicsHit);

            Profiler.EndSample(); // SphereCast
            return(result);
        }
예제 #6
0
        /// <summary>
        /// Perform a Unity physics Raycast to determine which scene objects with a collider is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointerData"></param>
        /// <param name="prioritizedLayerMasks"></param>
        private static void RaycastPhysics(PointerData pointerData, LayerMask[] prioritizedLayerMasks)
        {
            RayStep[] pointerRays = pointerData.Pointer.Rays;

            if (pointerRays == null)
            {
                Debug.LogError($"No valid rays for {pointerData.Pointer.PointerName} pointer.");
                return;
            }

            if (pointerRays.Length <= 0)
            {
                Debug.LogError($"No valid rays for {pointerData.Pointer.PointerName} pointer");
                return;
            }

            // Check raycast for each step in the pointing source
            for (int i = 0; i < pointerRays.Length; i++)
            {
                RaycastHit physicsHit;
                switch (pointerData.Pointer.RaycastMode)
                {
                case RaycastMode.Simple:
                    if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointerRays[i], prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        UpdatePointerRayOnHit(pointerData, pointerRays, in physicsHit, i);
                        return;
                    }
                    break;

                case RaycastMode.Box:
                    Debug.LogWarning("Box Raycasting Mode not supported for pointers.");
                    break;

                case RaycastMode.Sphere:
                    if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointerRays[i], pointerData.Pointer.SphereCastRadius, prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        UpdatePointerRayOnHit(pointerData, pointerRays, in physicsHit, i);
                        return;
                    }
                    break;

                default:
                    Debug.LogError($"Invalid raycast mode {pointerData.Pointer.RaycastMode} for {pointerData.Pointer.PointerName} pointer.");
                    break;
                }
            }

            pointerData.UpdateHit();
        }
예제 #7
0
    public bool SphereCast(
        RayStep step,
        float radius,
        LayerMask[] prioritizedLayerMasks,
        bool focusIndividualCompoundCollider,
        out MixedRealityRaycastHit hitInfo)
    {
        // For now, this is just using the default behavior for sphere cast.
        // Leaving MapRenderer integration for a future change.

        var result =
            MixedRealityRaycaster.RaycastSpherePhysicsStep(
                step,
                radius,
                step.Length,
                prioritizedLayerMasks,
                focusIndividualCompoundCollider,
                out RaycastHit physicsHit);

        hitInfo = new MixedRealityRaycastHit(result, physicsHit);
        return(result);
    }
예제 #8
0
        /// <summary>
        /// Perform a Unity physics Raycast to determine which scene objects with a collider is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointerData"></param>
        /// <param name="prioritizedLayerMasks"></param>
        private static void RaycastPhysics(PointerData pointerData, LayerMask[] prioritizedLayerMasks)
        {
            bool       isHit        = false;
            int        rayStepIndex = 0;
            RayStep    rayStep      = default;
            RaycastHit physicsHit   = default;

            if (pointerData.Pointer.Rays == null)
            {
                Debug.LogError($"No valid rays for {pointerData.Pointer.PointerName} pointer.");
                return;
            }

            if (pointerData.Pointer.Rays.Length <= 0)
            {
                Debug.LogError($"No valid rays for {pointerData.Pointer.PointerName} pointer");
                return;
            }

            // Check raycast for each step in the pointing source
            for (int i = 0; i < pointerData.Pointer.Rays.Length; i++)
            {
                switch (pointerData.Pointer.RaycastMode)
                {
                case RaycastModeType.Simple:
                    if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointerData.Pointer.Rays[i], prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        isHit        = true;
                        rayStep      = pointerData.Pointer.Rays[i];
                        rayStepIndex = i;
                    }
                    break;

                case RaycastModeType.Box:
                    Debug.LogWarning("Box Raycasting Mode not supported for pointers.");
                    break;

                case RaycastModeType.Sphere:
                    if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointerData.Pointer.Rays[i], pointerData.Pointer.SphereCastRadius, prioritizedLayerMasks, out physicsHit))
                    {
                        // Set the pointer source's origin ray to this step
                        isHit        = true;
                        rayStep      = pointerData.Pointer.Rays[i];
                        rayStepIndex = i;
                    }
                    break;

                default:
                    Debug.LogError($"Invalid raycast mode {pointerData.Pointer.RaycastMode} for {pointerData.Pointer.PointerName} pointer.");
                    break;
                }

                if (isHit)
                {
                    break;
                }
            }

            if (isHit)
            {
                pointerData.UpdateHit(physicsHit, rayStep, rayStepIndex);
            }
            else
            {
                pointerData.UpdateHit();
            }
        }
        /// <summary>
        /// Perform a scene query to determine which scene objects with a collider is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointerData"></param>
        /// <param name="prioritizedLayerMasks"></param>
        private static void QueryScene(IMixedRealityPointer pointer, LayerMask[] prioritizedLayerMasks, PointerHitResult hit)
        {
            float      rayStartDistance = 0;
            RaycastHit physicsHit;

            RayStep[] pointerRays = pointer.Rays;

            if (pointerRays == null)
            {
                Debug.LogError($"No valid rays for {pointer.PointerName} pointer.");
                return;
            }

            if (pointerRays.Length <= 0)
            {
                Debug.LogError($"No valid rays for {pointer.PointerName} pointer");
                return;
            }

            // Perform query for each step in the pointing source
            for (int i = 0; i < pointerRays.Length; i++)
            {
                switch (pointer.SceneQueryType)
                {
                case SceneQueryType.SimpleRaycast:
                    if (MixedRealityRaycaster.RaycastSimplePhysicsStep(pointerRays[i], prioritizedLayerMasks, out physicsHit))
                    {
                        UpdatePointerRayOnHit(pointerRays, physicsHit, i, rayStartDistance, hit);
                        return;
                    }
                    break;

                case SceneQueryType.BoxRaycast:
                    Debug.LogWarning("Box Raycasting Mode not supported for pointers.");
                    break;

                case SceneQueryType.SphereCast:
                    if (MixedRealityRaycaster.RaycastSpherePhysicsStep(pointerRays[i], pointer.SphereCastRadius, prioritizedLayerMasks, out physicsHit))
                    {
                        UpdatePointerRayOnHit(pointerRays, physicsHit, i, rayStartDistance, hit);
                        return;
                    }
                    break;

                case SceneQueryType.SphereOverlap:
                    Collider[] colliders = UnityEngine.Physics.OverlapSphere(pointer.Rays[i].Origin, pointer.SphereCastRadius, ~UnityEngine.Physics.IgnoreRaycastLayer);

                    if (colliders.Length > 0)
                    {
                        Vector3    testPoint       = pointer.Rays[i].Origin;
                        GameObject closest         = null;
                        float      closestDistance = Mathf.Infinity;
                        Vector3    objectHitPoint  = testPoint;

                        foreach (Collider collider in colliders)
                        {
                            // Policy: in order for an collider to be near interactable it must have
                            // a NearInteractionGrabbable component on it.
                            // FIXME: This is assuming only the grab pointer is using SceneQueryType.SphereOverlap,
                            //        but there may be other pointers using the same query type which have different semantics.
                            if (collider.GetComponent <NearInteractionGrabbable>() == null)
                            {
                                continue;
                            }
                            // From https://docs.unity3d.com/ScriptReference/Collider.ClosestPoint.html
                            // If location is in the collider the closestPoint will be inside.
                            Vector3 closestPointToCollider = collider.ClosestPoint(testPoint);
                            float   distance = (testPoint - closestPointToCollider).sqrMagnitude;
                            if (distance < closestDistance)
                            {
                                closestDistance = distance;
                                closest         = collider.gameObject;
                                objectHitPoint  = closestPointToCollider;
                            }
                        }
                        if (closest != null)
                        {
                            hit.Set(closest, objectHitPoint, Vector3.zero, pointer.Rays[i], 0, closestDistance);
                            return;
                        }
                    }
                    break;

                default:
                    Debug.LogError($"Invalid raycast mode {pointer.SceneQueryType} for {pointer.PointerName} pointer.");
                    break;
                }

                rayStartDistance += pointer.Rays[i].Length;
            }
        }