protected override void DefaultValues()
        {
            base.DefaultValues();

            this.collisions = new List <HitResult3D>();
            this.resultZero = new HitResult3D();
        }
        /// <summary>
        /// Check cursor collision
        /// </summary>
        /// <param name="ray">ray cast</param>
        /// <param name="rayDistance">The ray distance to test</param>
        /// <returns>Cursor hit</returns>
        public CursorHit CheckCursorCollision(ref Ray ray, float rayDistance)
        {
            HitResult3D result = this.Owner.Scene.PhysicsManager.Simulation3D.RayCast(ref ray, rayDistance);

            CursorHit cursorHit = new CursorHit();

            if (result.Succeeded)
            {
                cursorHit.Hit      = true;
                cursorHit.Position = result.Point - (ray.Direction * this.SurfaceOffset);
                cursorHit.Target   = result.Point + result.Normal;
            }

            return(cursorHit);
        }
        private void CheckButtonInteraction(ref HitResult3D result)
        {
            ButtonComponentBase currentButton = null;

            if (result.Succeeded)
            {
                Entity entityHiting = (result.PhysicBody.UserData as PhysicBody3D).Owner;
                currentButton = entityHiting?.Parent?.FindComponent <ButtonComponentBase>(false);
                if (currentButton != null)
                {
                    if (!currentButton.Hover)
                    {
                        currentButton.Hover = true;
                    }
                    if (this.TriggerValue > 0 && this.lastTriggerValue == 0)
                    {
                        currentButton?.Touch();
                    }

                    if (currentButton != this.lastButton && this.lastButton != null)
                    {
                        this.lastButton.Hover = false;
                    }
                }
                else
                {
                    if (this.lastButton != null)
                    {
                        this.lastButton.Hover = false;
                    }
                }
            }
            else
            {
                if (this.lastButton != null)
                {
                    this.lastButton.Hover = false;
                }
            }

            this.lastButton = currentButton;
        }
        //private void CheckNoesisInteraction(ref HitResult3D result, ref Ray ray)
        //{
        //    NoesisMouseSyncComponent noesisSyncComponent = null;
        //    if (result.Succeeded)
        //    {
        //        Entity noesisEntity = (result.PhysicBody.UserData as PhysicBody3D).Owner;
        //        var noesisPanel = noesisEntity?.FindComponent<NoesisPanel>();
        //        noesisSyncComponent = noesisEntity?.FindComponent<NoesisMouseSyncComponent>();

        //        if (noesisPanel != null && noesisSyncComponent != null)
        //        {
        //            int projectedX;
        //            int projectedY;
        //            float? rayDistance;
        //            if (noesisPanel != null && noesisPanel.View != null && noesisPanel.ProjectRay(ray, out projectedX, out projectedY, out rayDistance))
        //            {
        //                if (this.lastTriggerValue == 0 && this.TriggerValue > 0)
        //                {
        //                    noesisSyncComponent.MouseDown(projectedX, projectedY, Noesis.MouseButton.Left);
        //                }
        //                else if (this.lastTriggerValue > 0 && this.TriggerValue == 0)
        //                {
        //                    noesisSyncComponent.MouseUp(projectedX, projectedY, Noesis.MouseButton.Left);
        //                }
        //                else
        //                {
        //                    noesisSyncComponent.MouseMove(projectedX, projectedY);
        //                }
        //            }
        //        }
        //        else
        //        {
        //            this.lastNoesisPanel?.MouseMove(-1, -1);
        //            noesisSyncComponent = null;
        //        }
        //    }
        //    else
        //    {
        //        this.lastNoesisPanel?.MouseMove(-1, -1);
        //        noesisSyncComponent = null;
        //    }

        //    this.lastNoesisPanel = noesisSyncComponent;
        //}

        private HitResult3D NearestCollider(ref Vector3 startPosition, IList <HitResult3D> results)
        {
            float       minDistance = float.MaxValue;
            HitResult3D nearest     = this.resultZero;

            foreach (HitResult3D r in results)
            {
                if (!r.Succeeded)
                {
                    continue;
                }

                if (minDistance > r.HitFraction)
                {
                    nearest     = r;
                    minDistance = r.HitFraction;
                }
            }

            return(nearest);
        }
        protected override void CalculateGazeProperties(ref Ray ray, out Vector3 gazePosition, out Vector3 gazeNormal)
        {
            gazePosition = ray.Position + ray.Direction * 50;
            gazeNormal   = -ray.Direction;

            if (this.Owner.Scene.PhysicsManager.Simulation3D.InternalWorld == null)
            {
                return;
            }

            this.collisions.Clear();
            this.Owner.Scene.PhysicsManager.Simulation3D.RayCastAll(ref ray, 10, this.collisions);
            if (this.collisions != null && this.collisions.Count > 0)
            {
                HitResult3D result = this.NearestCollider(ref ray.Position, this.collisions);
                if (result.Succeeded)
                {
                    if (!this.gaze.IsVisible)
                    {
                        this.gaze.IsVisible = true;
                    }

                    gazePosition = result.Point + (result.Normal * 0.002f);
                    gazeNormal   = result.Normal;
                }

                // Noesis Panel
                //this.CheckNoesisInteraction(ref result, ref ray);

                // 3D Buttons
                this.CheckButtonInteraction(ref result);
            }
            else
            {
                if (gaze.IsVisible)
                {
                    this.gaze.IsVisible = false;
                }
            }
        }
예제 #6
0
        /// <inheritdoc/>
        protected override void Update(TimeSpan gameTime)
        {
            Ray?ray             = null;
            var disableByPalmUp = false;

            if (this.Joint != null)
            {
                if (this.Joint.PoseIsValid)
                {
                    this.Joint.TrackedDevice.TryGetArticulatedHandJoint(XRHandJointKind.IndexProximal, out var handJoint);
                    var handPosition        = handJoint.Pose.Position;
                    var measuredRayPosition = handPosition;
                    var measuredDirection   = this.Joint.Pointer.Direction;

                    this.stabilizedRay.AddSample(new Ray(measuredRayPosition, measuredDirection));
                    ray = new Ray(this.stabilizedRay.StabilizedPosition, this.stabilizedRay.StabilizedDirection);
                }
            }
            else
            {
                ray = new Ray(this.MainCursor.transform.Position, this.MainCursor.transform.WorldTransform.Forward);
            }

            if (this.Joint?.PoseIsValid == true)
            {
                var jointOrientation = Matrix4x4.CreateFromQuaternion(this.Joint.Pose.Orientation);
                var jointNormal      = -jointOrientation.Up;

                var headForward = this.cam.Transform.WorldTransform.Forward;
                disableByPalmUp = !this.ShouldShowRay(headForward, jointNormal);
            }

            var disableByJointInvalid = true;
            var lineMeshVisible       = false;

            if (ray != null && ray.Value.Position != Vector3.Zero)
            {
                var r = ray.Value;

                var disableByProximity = false;
                if (this.cursor.Pinch)
                {
                    float dFactor = (Vector3.Transform(this.MainCursor.transform.Position, this.cam.Transform.WorldInverseTransform) - this.pinchPosRef).Z;
                    dFactor = (float)Math.Pow(1 - dFactor, 4);

                    this.transform.Position = r.GetPoint(this.pinchDist * dFactor);
                }
                else
                {
                    if (this.MainCursor.Pinch && !this.LineMesh.Owner.IsEnabled)
                    {
                        disableByProximity = true;
                    }
                    else
                    {
                        Vector3 collPoint = r.GetPoint(1000.0f);
                        this.transform.Position = collPoint; // Move the cursor to avoid collisions
                        Vector3     from   = r.GetPoint(-0.1f);
                        Vector3     to     = r.GetPoint(1000.0f);
                        HitResult3D result = this.Managers.PhysicManager3D.RayCast(ref from, ref to, this.collisionMask);

                        if (result.Succeeded)
                        {
                            Vector3 dir = r.Direction;
                            dir.Normalize();
                            collPoint = result.Point + (dir * 0.0025f);
                        }

                        float dist = (r.Position - collPoint).Length();
                        if (dist > 0.3f)
                        {
                            this.transform.Position = collPoint;

                            if (this.MainCursor.Pinch)
                            {
                                // Pinch is about to happen
                                this.pinchDist   = dist;
                                this.pinchPosRef = Vector3.Transform(this.MainCursor.transform.Position, this.cam.Transform.WorldInverseTransform);
                            }
                        }
                        else
                        {
                            disableByProximity = true;
                        }
                    }
                }

                // Update line
                disableByJointInvalid = this.Joint != null && !Tools.IsJointValid(this.Joint);

                lineMeshVisible = !disableByJointInvalid && !disableByProximity && !disableByPalmUp;
                if (lineMeshVisible)
                {
                    var distance = (this.transform.Position - r.Position).Length();

                    this.lineMeshTransform.Position = r.Position;
                    this.lineMeshTransform.Scale    = new Vector3(1, 1, distance);
                    this.lineMeshTransform.LocalLookAt(this.transform.Position, Vector3.Up);

                    this.LineMesh.TextureTiling = new Vector2(distance * 0.5f * 30.0f, 1.0f);
                }
            }

            this.LineMesh.Owner.IsEnabled          = lineMeshVisible;
            this.cursor.meshRenderer.IsEnabled     = lineMeshVisible;
            this.MainCursor.meshRenderer.IsEnabled = !disableByJointInvalid && !disableByPalmUp && !lineMeshVisible;

            this.cursor.Pinch = lineMeshVisible && this.MainCursor.Pinch;
            if (this.cursor.Pinch != this.cursor.PreviousPinch)
            {
                this.LineMesh.DiffuseTexture = this.cursor.Pinch ? null : this.handrayTexture;
            }
        }