Example #1
0
            public void UpdateHit(float extent)
            {
                PreviousEndObject = End.Object;

                RayStep firstStep = PointingSource.Rays[0];
                RayStep finalStep = PointingSource.Rays[PointingSource.Rays.Length - 1];

                RayStepIndex = 0;

                StartPoint = firstStep.Origin;
                End        = new FocusDetails
                {
                    Point  = finalStep.Terminus,
                    Normal = (-finalStep.Direction),
                    Object = null
                };
            }
Example #2
0
        /// <summary>
        /// Raycasts a single graphic <see cref="Microsoft.MixedReality.Toolkit.Physics.RayStep"/>
        /// </summary>
        private bool RaycastGraphicsStep(PointerEventData graphicEventData, RayStep step, LayerMask[] prioritizedLayerMasks, out RaycastResult uiRaycastResult)
        {
            Debug.Assert(step.Direction != Vector3.zero, "RayStep Direction is Invalid.");

            // Move the uiRaycast camera to the current pointer's position.
            UIRaycastCamera.transform.position = step.Origin;
            UIRaycastCamera.transform.rotation = Quaternion.LookRotation(step.Direction, Vector3.up);

            // We always raycast from the center of the camera.
            graphicEventData.position = new Vector2(UIRaycastCamera.pixelWidth * 0.5f, UIRaycastCamera.pixelHeight * 0.5f);

            // Graphics raycast
            uiRaycastResult = EventSystem.current.Raycast(graphicEventData, prioritizedLayerMasks);
            graphicEventData.pointerCurrentRaycast = uiRaycastResult;

            return(uiRaycastCamera.gameObject != null);
        }
Example #3
0
            public void UpdateHit()
            {
                PreviousPointerTarget = Details.Object;

                RayStep firstStep = Pointer.Rays[0];
                RayStep finalStep = Pointer.Rays[Pointer.Rays.Length - 1];

                RayStepIndex = 0;

                StartPoint = firstStep.Origin;

                focusDetails.Point  = finalStep.Terminus;
                focusDetails.Normal = -finalStep.Direction;
                focusDetails.Object = null;

                pointerWasLocked = false;
            }
        /// <inheritdoc />
        public override void OnPreRaycast()
        {
            Debug.Assert(lineBase != null);

            Vector3 pointerPosition;

            TryGetPointerPosition(out pointerPosition);

            lineBase.UpdateMatrix();

            // Set our first and last points
            lineBase.FirstPoint = pointerPosition;

            if (IsFocusLocked)
            {
                lineBase.LastPoint = pointerPosition + ((Result.Details.Point - pointerPosition).normalized * PointerExtent);
            }
            else
            {
                lineBase.LastPoint = pointerPosition + (PointerDirection * PointerExtent);
            }

            // Make sure our array will hold
            if (Rays == null || Rays.Length != LineCastResolution)
            {
                Rays = new RayStep[LineCastResolution];
            }

            // Set up our rays
            if (!IsFocusLocked)
            {
                // Turn off gravity so we get accurate rays
                gravityDistorter.enabled = false;
            }

            float   stepSize  = 1f / Rays.Length;
            Vector3 lastPoint = lineBase.GetUnClampedPoint(0f);

            for (int i = 0; i < Rays.Length; i++)
            {
                Vector3 currentPoint = lineBase.GetUnClampedPoint(stepSize * (i + 1));
                Rays[i].UpdateRayStep(ref lastPoint, ref currentPoint);
                lastPoint = currentPoint;
            }
        }
Example #5
0
        /// <inheritdoc />
        protected override void UpdateRays()
        {
            // Make sure our array will hold
            if (Rays == null || Rays.Length != LineCastResolution)
            {
                Rays = new RayStep[LineCastResolution];
            }

            float   stepSize  = 1f / Rays.Length;
            Vector3 lastPoint = LineBase.GetUnClampedPoint(0f);

            for (int i = 0; i < Rays.Length; i++)
            {
                Vector3 currentPoint = LineBase.GetUnClampedPoint(stepSize * (i + 1));
                Rays[i].UpdateRayStep(ref lastPoint, ref currentPoint);
                lastPoint = currentPoint;
            }
        }
Example #6
0
        private void RaycastUnityUI(PointerData pointer, LayerMask[] prioritizedLayerMasks)
        {
            Debug.Assert(pointer.End.Point != Vector3.zero, "No pointer source end point found to raycast against!");
            Debug.Assert(UIRaycastCamera != null, "You must assign a UIRaycastCamera on the FocusManager before you can process uGUI raycasting.");

            RaycastResult uiRaycastResult        = default(RaycastResult);
            bool          overridePhysicsRaycast = false;
            RayStep       rayStep      = default(RayStep);
            int           rayStepIndex = 0;

            // Comment back in GetType() only when debugging for a specific pointer.
            Debug.Assert(pointer.PointingSource.Rays != null, "No valid rays for pointer " /* + pointer.GetType()*/);
            Debug.Assert(pointer.PointingSource.Rays.Length > 0, "No valid rays for pointer " /* + pointer.GetType()*/);

            // Cast rays for every step until we score a hit
            for (int i = 0; i < pointer.PointingSource.Rays.Length; i++)
            {
                if (RaycastUnityUIStep(pointer, pointer.PointingSource.Rays[i], prioritizedLayerMasks, out overridePhysicsRaycast, out uiRaycastResult))
                {
                    rayStepIndex = i;
                    rayStep      = pointer.PointingSource.Rays[i];
                    break;
                }
            }

            // Check if we need to overwrite the physics raycast info
            if ((pointer.End.Object == null || overridePhysicsRaycast) && uiRaycastResult.isValid &&
                uiRaycastResult.module != null && uiRaycastResult.module.eventCamera == UIRaycastCamera)
            {
                newUiRaycastPosition.x = uiRaycastResult.screenPosition.x;
                newUiRaycastPosition.y = uiRaycastResult.screenPosition.y;
                newUiRaycastPosition.z = uiRaycastResult.distance;

                Vector3 worldPos = UIRaycastCamera.ScreenToWorldPoint(newUiRaycastPosition);

                var hitInfo = new RaycastHit
                {
                    point  = worldPos,
                    normal = -uiRaycastResult.gameObject.transform.forward
                };

                pointer.UpdateHit(uiRaycastResult, hitInfo, rayStep, rayStepIndex);
            }
        }
        /// <summary>
        /// Perform a Unity Graphics Raycast to determine which uGUI element is currently being gazed at, if any.
        /// </summary>
        /// <param name="pointer"></param>
        /// <param name="prioritizedLayerMasks"></param>
        private void RaycastGraphics(PointerData pointer, LayerMask[] prioritizedLayerMasks)
        {
            Debug.Assert(pointer.Details.Point != Vector3.zero, "Invalid pointer source start point found to raycast from!");
            Debug.Assert(UIRaycastCamera != null, "You must assign a UIRaycastCamera on the FocusProvider before you can process uGUI raycasting.");

            RaycastResult raycastResult          = default(RaycastResult);
            bool          overridePhysicsRaycast = false;
            RayStep       rayStep      = default(RayStep);
            int           rayStepIndex = 0;

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

            // Cast rays for every step until we score a hit
            for (int i = 0; i < pointer.Pointer.Rays.Length; i++)
            {
                if (RaycastGraphicsStep(pointer, pointer.Pointer.Rays[i], prioritizedLayerMasks, out overridePhysicsRaycast, out raycastResult))
                {
                    rayStepIndex = i;
                    rayStep      = pointer.Pointer.Rays[i];
                    break;
                }
            }

            // Check if we need to overwrite the physics raycast info
            if ((pointer.CurrentPointerTarget == null || overridePhysicsRaycast) && raycastResult.isValid &&
                raycastResult.module != null && raycastResult.module.eventCamera == UIRaycastCamera)
            {
                newUiRaycastPosition.x = raycastResult.screenPosition.x;
                newUiRaycastPosition.y = raycastResult.screenPosition.y;
                newUiRaycastPosition.z = raycastResult.distance;

                Vector3 worldPos = UIRaycastCamera.ScreenToWorldPoint(newUiRaycastPosition);

                var hitInfo = new RaycastHit
                {
                    point  = worldPos,
                    normal = -raycastResult.gameObject.transform.forward
                };

                pointer.UpdateHit(raycastResult, hitInfo, rayStep, rayStepIndex);
            }
        }
Example #8
0
        public Quaternion GetModifiedRotation(ICursor cursor)
        {
            Quaternion rotation;

            RayStep lastStep = cursor.Pointer.Rays[cursor.Pointer.Rays.Length - 1];
            Vector3 forward  = UseGazeBasedNormal ? -lastStep.direction : HostTransform.rotation * CursorNormal;

            // Determine the cursor forward
            if (forward.magnitude > 0)
            {
                rotation = Quaternion.LookRotation(forward, Vector3.up);
            }
            else
            {
                rotation = cursor.Rotation;
            }

            return(rotation);
        }
Example #9
0
        public void UpdateRenderedLine(RayStep[] lines, PointerResult result, bool selectPressed, float extent)
        {
            if (LineBase == null)
            {
                return;
            }

            Gradient lineColor = LineColorNoTarget;

            if (InteractionEnabled)
            {
                LineBase.enabled = true;

                // If we hit something
                if (result.End.Object != null)
                {
                    lineColor          = LineColorValid;
                    LineBase.LastPoint = result.End.Point;
                }
                else
                {
                    LineBase.LastPoint = RayStep.GetPointByDistance(lines, extent);
                }

                if (selectPressed)
                {
                    lineColor = LineColorSelected;
                }
            }
            else
            {
                LineBase.enabled = false;
            }

            for (int i = 0; i < LineRenderers.Length; i++)
            {
                LineRenderers[i].LineColor = lineColor;
            }
        }
Example #10
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);
    }
        /// <summary>
        /// Initialize all applicable settings on this pointer from <paramref name="testProxy"/> and then set this pointer active,
        /// so that it will update its <see cref="Toolkit.Input.IMixedRealityPointer.Result"/> in the next <see cref="Toolkit.Input.FocusProvider.Update"/>.
        /// </summary>
        public void SetFromTestProxy(FocusRaycastTestProxy testProxy)
        {
            if (Rays == null || Rays.Length != testProxy.LineCastResolution)
            {
                Rays = new RayStep[testProxy.LineCastResolution];
            }

            var lineBase = testProxy.RayLineData;

            float   stepSize  = 1f / Rays.Length;
            Vector3 lastPoint = lineBase.GetUnClampedPoint(0f);

            for (int i = 0; i < Rays.Length; i++)
            {
                Vector3 currentPoint = lineBase.GetUnClampedPoint(stepSize * (i + 1));
                Rays[i].UpdateRayStep(ref lastPoint, ref currentPoint);
                lastPoint = currentPoint;
            }

            PrioritizedLayerMasksOverride = testProxy.PrioritizedLayerMasks;

            IsActive = true;
        }
        private void SimpleRaycastStepUpdate(RayStep rayStep)
        {
            bool       isHit;
            RaycastHit result;

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

            // 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);
            }
        }
Example #13
0
        /// <summary>
        /// Update the cursor's transform
        /// </summary>
        protected virtual void UpdateCursorTransform()
        {
            FocusDetails focusDetails      = FocusManager.Instance.GetFocusDetails(Pointer);
            GameObject   newTargetedObject = focusDetails.Object;
            Vector3      lookForward       = Vector3.forward;

            // Normalize scale on before update
            targetScale = Vector3.one;

            // If no game object is hit, put the cursor at the default distance
            if (newTargetedObject == null)
            {
                TargetedObject         = null;
                TargetedCursorModifier = null;

                if (pointerIsInputSourcePointer)
                {
                    // This value get re-queried every update, in case the app has
                    // changed the pointing extent of the pointer for the current scenario.
                    float distance = FocusManager.Instance.GetPointingExtent(Pointer);
                    if (DefaultCursorDistance != distance)
                    {
                        DefaultCursorDistance = distance;
                    }
                }
                else if (DefaultCursorDistance != originalDefaultCursorDistance)
                {
                    DefaultCursorDistance = originalDefaultCursorDistance;
                }

                targetPosition = RayStep.GetPointByDistance(Pointer.Rays, DefaultCursorDistance);
                lookForward    = -RayStep.GetDirectionByDistance(Pointer.Rays, DefaultCursorDistance);
                targetRotation = lookForward.magnitude > 0 ? Quaternion.LookRotation(lookForward, Vector3.up) : transform.rotation;
            }
            else
            {
                // Update currently targeted object
                TargetedObject = newTargetedObject;

                if (TargetedCursorModifier != null)
                {
                    TargetedCursorModifier.GetModifiedTransform(this, out targetPosition, out targetRotation, out targetScale);
                }
                else
                {
                    // If no modifier is on the target, just use the hit result to set cursor position
                    // Get the look forward by using distance between pointer origin and target position
                    // (This may not be strictly accurate for extremely wobbly pointers, but it should produce usable results)
                    float distanceToTarget = Vector3.Distance(Pointer.Rays[0].Origin, focusDetails.Point);
                    lookForward    = -RayStep.GetDirectionByDistance(Pointer.Rays, distanceToTarget);
                    targetPosition = focusDetails.Point + (lookForward * SurfaceCursorDistance);
                    Vector3 lookRotation = Vector3.Slerp(focusDetails.Normal, lookForward, LookRotationBlend);
                    targetRotation = Quaternion.LookRotation(lookRotation == Vector3.zero ? lookForward : lookRotation, Vector3.up);
                }
            }

            float deltaTime = UseUnscaledTime
                ? Time.unscaledDeltaTime
                : Time.deltaTime;

            // Use the lerp times to blend the position to the target position

            if (float.IsNaN(transform.position.x) || float.IsNaN(targetPosition.x) || PositionLerpTime == 0)
            {
                //transform.position = Vector3.zero;
            }
            else
            {
                transform.position   = Vector3.Lerp(transform.position, targetPosition, deltaTime / PositionLerpTime);
                transform.localScale = Vector3.Lerp(transform.localScale, targetScale, deltaTime / ScaleLerpTime);
                transform.rotation   = Quaternion.Lerp(transform.rotation, targetRotation, deltaTime / RotationLerpTime);
                //DongFengMain.Instance.ShowCursor();
            }
        }
Example #14
0
 /// <summary>
 /// Converts a remote <see cref="RayCast"/> into a <see cref="RayStep"/>.
 /// </summary>
 /// <param name="input">The ray cast to be converted.</param>
 /// <param name="output">The converted ray step.</param>
 public static void ToEvergine(this RayCast input, out RayStep output)
 {
     input.StartPos.ToEvergine(out var origin);
     input.EndPos.ToEvergine(out var terminus);
     output = new RayStep(origin, terminus);
 }
Example #15
0
        /// <summary>
        /// Raycasts each graphic <see cref="RayStep"/>
        /// </summary>
        /// <param name="pointerData"></param>
        /// <param name="step"></param>
        /// <param name="prioritizedLayerMasks"></param>
        /// <param name="overridePhysicsRaycast"></param>
        /// <param name="uiRaycastResult"></param>
        /// <returns></returns>
        private bool RaycastGraphicsStep(PointerData pointerData, RayStep step, LayerMask[] prioritizedLayerMasks, out bool overridePhysicsRaycast, out RaycastResult uiRaycastResult)
        {
            Debug.Assert(step.Direction != Vector3.zero, "RayStep Direction is Invalid.");

            // Move the uiRaycast camera to the current pointer's position.
            var cameraTransform = UIRaycastCamera.transform;

            cameraTransform.position = step.Origin;
            cameraTransform.forward  = step.Direction;

            // We always raycast from the center of the camera.
            pointerData.GraphicEventData.position = new Vector2(UIRaycastCamera.pixelWidth * 0.5f, UIRaycastCamera.pixelHeight * 0.5f);

            // Graphics raycast
            uiRaycastResult = EventSystem.current.Raycast(pointerData.GraphicEventData, prioritizedLayerMasks);
            pointerData.GraphicEventData.pointerCurrentRaycast = uiRaycastResult;

            overridePhysicsRaycast = false;

            if (uiRaycastResult.gameObject == null)
            {
                return(false);
            }

            // If we have a raycast result, check if we need to overwrite the physics raycast info

            if (pointerData.CurrentPointerTarget == null)
            {
                return(true);
            }

            var distance = 0f;

            for (int i = 0; i < pointerData.RayStepIndex; i++)
            {
                distance += pointerData.Pointer.Rays[i].Length;
            }

            // Check layer prioritization
            if (prioritizedLayerMasks.Length > 1)
            {
                // Get the index in the prioritized layer masks
                int uiLayerIndex     = uiRaycastResult.gameObject.layer.FindLayerListIndex(prioritizedLayerMasks);
                int threeDLayerIndex = pointerData.Details.LastRaycastHit.collider.gameObject.layer.FindLayerListIndex(prioritizedLayerMasks);

                if (threeDLayerIndex > uiLayerIndex)
                {
                    overridePhysicsRaycast = true;
                }
                else if (threeDLayerIndex == uiLayerIndex)
                {
                    if (distance > uiRaycastResult.distance)
                    {
                        overridePhysicsRaycast = true;
                    }
                }
            }
            else
            {
                if (distance > uiRaycastResult.distance)
                {
                    overridePhysicsRaycast = true;
                }
            }

            return(true);
        }
Example #16
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>
            /// Set hit focus information from a closest-colliders-to pointer check.
            /// </summary>
            public void Set(GameObject hitObject, Vector3 hitPointOnObject, Vector4 hitNormalOnObject, RayStep ray, int rayStepIndex, float rayDistance)
            {
                raycastHit            = default(RaycastHit);
                graphicsRaycastResult = default(RaycastResult);

                this.hitObject         = hitObject;
                this.hitPointOnObject  = hitPointOnObject;
                this.hitNormalOnObject = hitNormalOnObject;

                this.ray          = ray;
                this.rayStepIndex = rayStepIndex;
                this.rayDistance  = rayDistance;
            }
Example #18
0
        /// <summary>
        /// Box raycasts each physics <see cref="RayStep"/>.
        /// </summary>
        /// <returns>Whether or not the raycast hit something.</returns>
        public static bool RaycastBoxPhysicsStep(RayStep step, Vector3 extents, Vector3 targetPosition, Matrix4x4 matrix, float maxDistance, LayerMask[] prioritizedLayerMasks, int raysPerEdge, bool isOrthographic, out Vector3[] points, out Vector3[] normals, out bool[] hits)
        {
            if (Application.isEditor && DebugEnabled)
            {
                Debug.DrawLine(step.Origin, step.Origin + step.Direction * 10.0f, Color.green);
            }

            extents /= (raysPerEdge - 1);

            int  halfRaysPerEdge = (int)((raysPerEdge - 1) * 0.5f);
            int  numRays         = raysPerEdge * raysPerEdge;
            bool hitSomething    = false;

            points  = new Vector3[numRays];
            normals = new Vector3[numRays];
            hits    = new bool[numRays];

            int index = 0;

            for (int x = -halfRaysPerEdge; x <= halfRaysPerEdge; x += 1)
            {
                for (int y = -halfRaysPerEdge; y <= halfRaysPerEdge; y += 1)
                {
                    Vector3 offset = matrix.MultiplyVector(new Vector3(x * extents.x, y * extents.y, 0));

                    Vector3 origin    = step.Origin;
                    Vector3 direction = (targetPosition + offset) - step.Origin;

                    if (isOrthographic)
                    {
                        origin   += offset;
                        direction = step.Direction;
                    }

                    RaycastHit rayHit;
                    hits[index] = RaycastSimplePhysicsStep(new RayStep(origin, direction.normalized * maxDistance), prioritizedLayerMasks, out rayHit);

                    if (hits[index])
                    {
                        hitSomething   = true;
                        points[index]  = rayHit.point;
                        normals[index] = rayHit.normal;

                        if (Application.isEditor && DebugEnabled)
                        {
                            Debug.DrawLine(origin, points[index], Color.yellow);
                        }
                    }
                    else
                    {
                        if (Application.isEditor && DebugEnabled)
                        {
                            Debug.DrawLine(origin, origin + direction * 3.0f, Color.gray);
                        }
                    }

                    index++;
                }
            }

            return(hitSomething);
        }
Example #19
0
 /// <summary>
 /// Converts a <see cref="RayStep"/> into a remote <see cref="RayCast"/>.
 /// </summary>
 /// <param name="input">The ray step to be converted.</param>
 /// <param name="maxDistance">The ray max distance.</param>
 /// <param name="hitCollection">The hit collection mode to set on the converted ray cast.</param>
 /// <param name="maxHits">The maximum collected hits to set on the converted ray cast.</param>
 /// <param name="collisionMask">The collision mask to set on the converted ray cast.</param>
 /// <returns>The converted ray cast.</returns>
 public static RayCast ToRemote(this RayStep input, double maxDistance, HitCollectionPolicy hitCollection = HitCollectionPolicy.ClosestHits, int maxHits = 1024, uint collisionMask = 0xFFFFFFFF)
 {
     input.ToRemote(out var output, maxDistance, hitCollection, maxHits, collisionMask);
     return(output);
 }
Example #20
0
        /// <summary>
        /// Update the cursor's transform
        /// </summary>
        protected virtual void UpdateCursorTransform()
        {
            if (Pointer == null)
            {
                Debug.LogError($"[BaseCursor.{name}] No Pointer has been assigned!");
                return;
            }

            FocusDetails focusDetails;

            if (!MixedRealityToolkit.InputSystem.FocusProvider.TryGetFocusDetails(Pointer, out focusDetails))
            {
                if (MixedRealityToolkit.InputSystem.FocusProvider.IsPointerRegistered(Pointer))
                {
                    Debug.LogError($"{name}: Unable to get focus details for {pointer.GetType().Name}!");
                }

                return;
            }

            GameObject newTargetedObject = MixedRealityToolkit.InputSystem.FocusProvider.GetFocusedObject(Pointer);
            Vector3    lookForward;

            // Normalize scale on before update
            targetScale = Vector3.one;

            // If no game object is hit, put the cursor at the default distance
            if (newTargetedObject == null)
            {
                TargetedObject = null;
                targetPosition = RayStep.GetPointByDistance(Pointer.Rays, defaultCursorDistance);
                lookForward    = -RayStep.GetDirectionByDistance(Pointer.Rays, defaultCursorDistance);
                targetRotation = lookForward.magnitude > 0 ? Quaternion.LookRotation(lookForward, Vector3.up) : transform.rotation;
            }
            else
            {
                // Update currently targeted object
                TargetedObject = newTargetedObject;

                if (Pointer.CursorModifier != null)
                {
                    Pointer.CursorModifier.GetModifiedTransform(this, out targetPosition, out targetRotation, out targetScale);
                }
                else
                {
                    // If no modifier is on the target, just use the hit result to set cursor position
                    // Get the look forward by using distance between pointer origin and target position
                    // (This may not be strictly accurate for extremely wobbly pointers, but it should produce usable results)
                    float distanceToTarget = Vector3.Distance(Pointer.Rays[0].Origin, focusDetails.Point);
                    lookForward    = -RayStep.GetDirectionByDistance(Pointer.Rays, distanceToTarget);
                    targetPosition = focusDetails.Point + (lookForward * surfaceCursorDistance);
                    Vector3 lookRotation = Vector3.Slerp(focusDetails.Normal, lookForward, lookRotationBlend);
                    targetRotation = Quaternion.LookRotation(lookRotation == Vector3.zero ? lookForward : lookRotation, Vector3.up);
                }
            }

            float deltaTime = useUnscaledTime
                ? Time.unscaledDeltaTime
                : Time.deltaTime;

            // Use the lerp times to blend the position to the target position
            transform.position   = Vector3.Lerp(transform.position, targetPosition, deltaTime / positionLerpTime);
            transform.localScale = Vector3.Lerp(transform.localScale, targetScale, deltaTime / scaleLerpTime);
            transform.rotation   = Quaternion.Lerp(transform.rotation, targetRotation, deltaTime / rotationLerpTime);
        }
Example #21
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);
        }
    }
Example #22
0
 /// <summary>
 /// Simple raycasts each physics <see cref="RayStep"/>.
 /// </summary>
 /// <param name="step"></param>
 /// <param name="prioritizedLayerMasks"></param>
 /// <param name="physicsHit"></param>
 /// <returns>Whether or not the raycast hit something.</returns>
 public static bool RaycastSimplePhysicsStep(RayStep step, LayerMask[] prioritizedLayerMasks, out RaycastHit physicsHit)
 {
     Debug.Assert(step.Length > 0, "step length must be greater than zero!");
     return(RaycastSimplePhysicsStep(step, step.Length, prioritizedLayerMasks, out physicsHit));
 }
Example #23
0
            /// <summary>
            /// Set hit information from a canvas raycast.
            /// </summary>
            public void Set(RaycastResult result, Vector3 hitPointOnObject, Vector4 hitNormalOnObject, RayStep ray, int rayStepIndex, float rayDistance)
            {
                RaycastHit            = default;
                GraphicsRaycastResult = result;

                HitObject         = result.gameObject;
                HitPointOnObject  = hitPointOnObject;
                HitNormalOnObject = hitNormalOnObject;

                Ray          = ray;
                RayStepIndex = rayStepIndex;
                RayDistance  = rayDistance;
            }
Example #24
0
 /// <summary>
 /// Sphere raycasts each physics <see cref="RayStep"/>.
 /// </summary>
 /// <param name="step"></param>
 /// <param name="radius"></param>
 /// <param name="prioritizedLayerMasks"></param>
 /// <param name="physicsHit"></param>
 /// <returns>Whether or not the raycast hit something.</returns>
 public static bool RaycastSpherePhysicsStep(RayStep step, float radius, LayerMask[] prioritizedLayerMasks, out RaycastHit physicsHit)
 {
     return(RaycastSpherePhysicsStep(step, radius, step.Length, prioritizedLayerMasks, out physicsHit));
 }
Example #25
0
 /// <summary>
 /// Simple raycasts each physics <see cref="RayStep"/>.
 /// </summary>
 /// <param name="step"></param>
 /// <param name="prioritizedLayerMasks"></param>
 /// <param name="physicsHit"></param>
 /// <returns>Whether or not the raycast hit something.</returns>
 public static bool RaycastSimplePhysicsStep(RayStep step, LayerMask[] prioritizedLayerMasks, out RaycastHit physicsHit)
 {
     return(RaycastSimplePhysicsStep(step, step.Length, prioritizedLayerMasks, out physicsHit));
 }
Example #26
0
 /// <summary>
 /// Converts a <see cref="RayStep"/> into a remote <see cref="RayCast"/>.
 /// </summary>
 /// <param name="input">The ray step to be converted.</param>
 /// <param name="output">The converted ray cast.</param>
 /// <param name="maxDistance">The ray max distance.</param>
 /// <param name="hitCollection">The hit collection mode to set on the converted ray cast.</param>
 /// <param name="maxHits">The maximum collected hits to set on the converted ray cast.</param>
 /// <param name="collisionMask">The collision mask to set on the converted ray cast.</param>
 public static void ToRemote(this RayStep input, out RayCast output, double maxDistance, HitCollectionPolicy hitCollection = HitCollectionPolicy.ClosestHits, int maxHits = 1024, uint collisionMask = 0xFFFFFFFF)
 {
     input.Origin.ToRemote(out Double3 starPos);
     input.Terminus.ToRemote(out Double3 endPos);
     output = new RayCast(starPos, endPos, maxDistance, hitCollection, maxHits, collisionMask);
 }