Beispiel #1
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);
            }
        }
Beispiel #2
0
        private void BoxRaycastStepUpdate(RayStep rayStep)
        {
            Vector3 scale         = transform.lossyScale;
            float   scaleOverride = ScaleOverride;

            if (scaleOverride > 0)
            {
                scale = scale.normalized * scaleOverride;
            }

            Quaternion orientation = orientationMode == OrientModeEnum.None ?
                                     Quaternion.LookRotation(rayStep.Direction, Vector3.up) :
                                     CalculateMagnetismOrientation(rayStep.Direction, Vector3.up);

            Matrix4x4 targetMatrix = Matrix4x4.TRS(Vector3.zero, orientation, scale);

            if (boxCollider == null)
            {
                boxCollider = GetComponent <BoxCollider>();
            }

            Debug.Assert(boxCollider != null, $"Missing a box collider for Surface Magnetism on {gameObject}");

            Vector3 extents = boxCollider.size;

            if (MixedRealityRaycaster.RaycastBoxPhysicsStep(rayStep, extents, transform.position, targetMatrix, maxDistance, magneticSurfaces, boxRaysPerEdge, orthographicBoxCast, out Vector3[] positions, out Vector3[] normals, out bool[] hits))
        /// <inheritdoc />
        public bool Raycast(RayStep step, LayerMask[] prioritizedLayerMasks, bool focusIndividualCompoundCollider, out MixedRealityRaycastHit hitInfo)
        {
            bool result = MixedRealityRaycaster.RaycastSimplePhysicsStep(step, step.Length, prioritizedLayerMasks, focusIndividualCompoundCollider, out RaycastHit physicsHit);

            hitInfo = new MixedRealityRaycastHit(result, physicsHit);
            return(result);
        }
        /// <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);
        }
Beispiel #5
0
        /// <summary>
        /// Calculate solver for simple raycast with provided ray
        /// </summary>
        /// <param name="rayStep">start/end ray passed by read-only reference to avoid struct-copy performance</param>
        private void SimpleRaycastStepUpdate(ref RayStep rayStep)
        {
            bool       isHit;
            RaycastHit result;

            // Do the cast!
            isHit = MixedRealityRaycaster.RaycastSimplePhysicsStep(rayStep, maxRaycastDistance, magneticSurfaces, false, out result);

            OnSurface = isHit;

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

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

            // Apply results
            if (isHit)
            {
                GoalPosition = result.point + surfaceNormalOffset * result.normal + surfaceRayOffset * rayStep.Direction;
                GoalRotation = CalculateMagnetismOrientation(rayStep.Direction, result.normal);
            }
        }
        /// <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();
            }
        }
Beispiel #7
0
        private void BoxRaycastStepUpdate(RayStep rayStep)
        {
            Vector3 scale         = transform.lossyScale;
            float   scaleOverride = ScaleOverride;

            if (scaleOverride > 0)
            {
                scale = scale.normalized * scaleOverride;
            }

            Quaternion orientation = orientationMode == OrientModeEnum.None ?
                                     Quaternion.LookRotation(rayStep.Direction, Vector3.up) :
                                     CalculateMagnetismOrientation(rayStep.Direction, Vector3.up);

            Matrix4x4 targetMatrix = Matrix4x4.TRS(Vector3.zero, orientation, scale);

            if (boxCollider == null)
            {
                boxCollider = GetComponent <BoxCollider>();
            }

            Debug.Assert(boxCollider != null, $"Missing a box collider for Surface Magnetism on {gameObject}");

            Vector3 extents = boxCollider.size;

            Vector3[] positions;
            Vector3[] normals;
            bool[]    hits;

            if (MixedRealityRaycaster.RaycastBoxPhysicsStep(rayStep, extents, transform.position, targetMatrix, maxDistance, magneticSurfaces, boxRaysPerEdge, orthographicBoxCast, out positions, out normals, out hits))
            {
                Plane plane;
                float distance;

                // Place an unconstrained plane down the ray. Don't use vertical constrain.
                FindPlacementPlane(rayStep.Origin, rayStep.Direction, positions, normals, hits, boxCollider.size.x, maximumNormalVariance, false, orientationMode == OrientModeEnum.None, out plane, out distance);

                // If placing on a horizontal surface, need to adjust the calculated distance by half the app height
                float verticalCorrectionOffset = 0;
                if (IsNormalVertical(plane.normal) && !Mathf.Approximately(rayStep.Direction.y, 0))
                {
                    float   boxSurfaceVerticalOffset = targetMatrix.MultiplyVector(new Vector3(0, extents.y * 0.5f, 0)).magnitude;
                    Vector3 correctionVector         = boxSurfaceVerticalOffset * (rayStep.Direction / rayStep.Direction.y);
                    verticalCorrectionOffset = -correctionVector.magnitude;
                }

                float boxSurfaceOffset = targetMatrix.MultiplyVector(new Vector3(0, 0, extents.z * 0.5f)).magnitude;

                // Apply boxSurfaceOffset to ray direction and not surface normal direction to reduce sliding
                GoalPosition = rayStep.Origin + rayStep.Direction * Mathf.Max(closeDistance, distance + surfaceRayOffset + boxSurfaceOffset + verticalCorrectionOffset) + plane.normal * (0 * boxSurfaceOffset + surfaceNormalOffset);
                GoalRotation = CalculateMagnetismOrientation(rayStep.Direction, plane.normal);
                OnSurface    = true;
            }
            else
            {
                OnSurface = false;
            }
        }
Beispiel #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="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);
        }
Beispiel #10
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();
        }
        private bool IsPointerRayHitSelf()
        {
            if (currentInputSource == null || currentPointer == null)
            {
                return(false);
            }

            if (currentPointer.Rays.Length > 0)
            {
                RaycastHit  result;
                LayerMask[] magneticSurfaces = { UnityEngine.Physics.DefaultRaycastLayers };
                if (MixedRealityRaycaster.RaycastSimplePhysicsStep(currentPointer.Rays[0], Mathf.Infinity, magneticSurfaces, out result))
                {
                    if (result.collider.gameObject == this.gameObject)
                    {
                        return(true);
                    }
                }
                return(false);
            }
            return(false);
        }
Beispiel #12
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);
    }
Beispiel #13
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;
            }
        }
Beispiel #15
0
    public bool Raycast(
        RayStep step,
        LayerMask[] prioritizedLayerMasks,
        bool focusIndividualCompoundCollider,
        out MixedRealityRaycastHit hitInfo)
    {
        var hasPhysicsHit =
            MixedRealityRaycaster.RaycastSimplePhysicsStep(
                step,
                prioritizedLayerMasks,
                focusIndividualCompoundCollider,
                out RaycastHit physicsHit);

        MapRendererRaycastHit?closestMapHitInfo  = null;
        MapRenderer           closestMapRenderer = null;

        foreach (var mapRenderer in _mapRenderers)
        {
            if (
                mapRenderer.Raycast(
                    step,
                    out var mapHitInfo,
                    hasPhysicsHit ? physicsHit.distance : step.Length))
            {
                if (hasPhysicsHit)
                {
                    if (physicsHit.distance > mapHitInfo.Distance)
                    {
                        if (!closestMapHitInfo.HasValue || closestMapHitInfo.Value.Distance > mapHitInfo.Distance)
                        {
                            closestMapRenderer = mapRenderer;
                            closestMapHitInfo  = mapHitInfo;
                        }
                    }
                }
                else
                {
                    if (!closestMapHitInfo.HasValue || closestMapHitInfo.Value.Distance > mapHitInfo.Distance)
                    {
                        closestMapRenderer = mapRenderer;
                        closestMapHitInfo  = mapHitInfo;
                    }
                }
            }
        }

        if (closestMapHitInfo != null)
        {
            hitInfo = new MixedRealityRaycastHit();
            var mapRendererHitInfo = closestMapHitInfo.Value;
            hitInfo.distance  = mapRendererHitInfo.Distance;
            hitInfo.point     = mapRendererHitInfo.Point;
            hitInfo.normal    = mapRendererHitInfo.Normal;
            hitInfo.transform = closestMapRenderer.transform;
            return(true);
        }
        else
        {
            hitInfo = new MixedRealityRaycastHit(hasPhysicsHit, physicsHit);
            return(hasPhysicsHit);
        }
    }