Example #1
0
        public static Ray UnProject(this Vector2 point2d, ref Matrix view, ref Matrix projection, float nearPlane, float w, float h, bool isPerpective)
        {
            var px = point2d.X;
            var py = point2d.Y;

            var matrix = MatrixExtensions.PsudoInvert(ref view);

            var v = new Vector3
            {
                X = (2 * px / w - 1) / projection.M11,
                Y = -(2 * py / h - 1) / projection.M22,
                Z = 1 / projection.M33
            };

            Vector3.TransformCoordinate(ref v, ref matrix, out var zf);
            Vector3 zn;

            if (isPerpective)
            {
                zn = new Vector3(matrix.M41, matrix.M42, matrix.M43);
            }
            else
            {
                v.Z = 0;
                Vector3.TransformCoordinate(ref v, ref matrix, out zn);
            }
            var r = zf - zn;

            r.Normalize();

            return(new Ray(zn + r * nearPlane, r));
        }
Example #2
0
        /// <summary>
        /// Un-project 2D screen point onto 3D space by camera.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="point2d">The point2d.</param>
        /// <param name="ray">The ray.</param>
        /// <returns></returns>
        public static bool UnProject(this IViewport3DX viewport, Vector2 point2d, out Ray ray)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            if (viewport.RenderHost != null && viewport.CameraCore is ProjectionCameraCore camera)
            {
                var px = point2d.X;
                var py = point2d.Y;

                var viewMatrix = camera.CreateViewMatrix();

                var   matrix      = MatrixExtensions.PsudoInvert(ref viewMatrix);
                float w           = viewport.RenderHost.ActualWidth;
                float h           = viewport.RenderHost.ActualHeight;
                var   aspectRatio = w / h;

                var projMatrix = camera.CreateProjectionMatrix(aspectRatio);

                Vector3 v = new Vector3
                {
                    X = (2 * px / w - 1) / projMatrix.M11,
                    Y = -(2 * py / h - 1) / projMatrix.M22,
                    Z = 1 / projMatrix.M33
                };
                Vector3.TransformCoordinate(ref v, ref matrix, out Vector3 zf);
                Vector3 zn;
                if (camera is PerspectiveCameraCore)
                {
                    zn = camera.Position;
                }
                else
                {
                    v.Z = 0;
                    Vector3.TransformCoordinate(ref v, ref matrix, out zn);
                }
                Vector3 r = zf - zn;
                r.Normalize();

                ray = new Ray(zn + r * camera.NearPlaneDistance, r);
                return(true);
            }
            else
            {
                ray = new Ray();
                return(false);
            }
        }
        /// <summary>
        /// Un-projects a 2D screen point.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="point2d">The input point.</param>
        /// <returns>The ray.</returns>
        public static Ray UnProject(this ViewportCore viewport, Vector2 point2d)
        {
            var camera = viewport.CameraCore as ProjectionCameraCore;

            if (camera != null)
            {
                var px = (float)point2d.X;
                var py = (float)point2d.Y;

                var     viewMatrix = camera.CreateViewMatrix();
                Vector3 v          = new Vector3();

                var   matrix      = MatrixExtensions.PsudoInvert(ref viewMatrix);
                float w           = (float)viewport.ViewportRectangle.Width;
                float h           = (float)viewport.ViewportRectangle.Height;
                var   aspectRatio = w / h;

                var     projMatrix = camera.CreateProjectionMatrix(aspectRatio);
                Vector3 zn, zf;
                v.X = (2 * px / w - 1) / projMatrix.M11;
                v.Y = -(2 * py / h - 1) / projMatrix.M22;
                v.Z = 1 / projMatrix.M33;
                Vector3.TransformCoordinate(ref v, ref matrix, out zf);

                if (camera is PerspectiveCameraCore)
                {
                    zn = camera.Position;
                }
                else
                {
                    v.Z = 0;
                    Vector3.TransformCoordinate(ref v, ref matrix, out zn);
                }
                Vector3 r = zf - zn;
                r.Normalize();

                return(new Ray(zn + r * camera.NearPlaneDistance, r));
            }
            throw new HelixToolkitException("Unproject camera error.");
        }
Example #4
0
        protected override bool OnHitTest(RenderContext context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
        {
            var   p = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix);
            var   screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore;
            float viewportSize    = screenSpaceCore.Size * screenSpaceCore.SizeScale;
            var   offx            = (float)(context.ActualWidth / 2 * (1 + screenSpaceCore.RelativeScreenLocationX) - viewportSize / 2);
            var   offy            = (float)(context.ActualHeight / 2 * (1 + screenSpaceCore.RelativeScreenLocationY) - viewportSize / 2);

            offx = Math.Max(0, Math.Min(offx, (int)(context.ActualWidth - viewportSize)));
            offy = Math.Max(0, Math.Min(offy, (int)(context.ActualHeight - viewportSize)));
            var px = p.X - offx;
            var py = p.Y - offy;

            if (px < 0 || py < 0 || px > viewportSize || py > viewportSize)
            {
                return(false);
            }

            var     viewMatrix = screenSpaceCore.GlobalTransform.View;
            Vector3 v          = new Vector3();

            var     matrix      = MatrixExtensions.PsudoInvert(ref viewMatrix);
            var     aspectRatio = screenSpaceCore.ScreenRatio;
            var     projMatrix  = screenSpaceCore.GlobalTransform.Projection;
            Vector3 zn;

            v.X = (2 * px / viewportSize - 1) / projMatrix.M11;
            v.Y = (2 * py / viewportSize - 1) / projMatrix.M22;
            v.Z = 1 / projMatrix.M33;
            Vector3.TransformCoordinate(ref v, ref matrix, out Vector3 zf);
            if (screenSpaceCore.IsPerspective)
            {
                zn = screenSpaceCore.GlobalTransform.EyePos;
            }
            else
            {
                v.Z = 0;
                Vector3.TransformCoordinate(ref v, ref matrix, out zn);
            }

            Vector3 r = zf - zn;

            r.Normalize();

            ray = new Ray(zn, r);
            List <HitTestResult> viewBoxHit = new List <HitTestResult>();

            if (base.OnHitTest(context, totalModelMatrix, ref ray, ref viewBoxHit))
            {
                hits?.Clear();
                hits = viewBoxHit;
                Debug.WriteLine("View box hit.");
                var     hit    = viewBoxHit[0];
                Vector3 normal = Vector3.Zero;
                int     inv    = isRightHanded ? 1 : -1;
                if (hit.ModelHit == ViewBoxMeshModel)
                {
                    normal = -hit.NormalAtHit * inv;
                    //Fix the normal if returned normal is reversed
                    if (Vector3.Dot(normal, context.Camera.LookDirection) < 0)
                    {
                        normal *= -1;
                    }
                }
                else if (hit.Tag is int index)
                {
                    if (hit.ModelHit == EdgeModel && index < edgeInstances.Length)
                    {
                        Matrix transform = edgeInstances[index];
                        normal = -transform.TranslationVector;
                    }
                    else if (hit.ModelHit == CornerModel && index < cornerInstances.Length)
                    {
                        Matrix transform = cornerInstances[index];
                        normal = -transform.TranslationVector;
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
                normal.Normalize();
                if (Vector3.Cross(normal, UpDirection).LengthSquared() < 1e-5)
                {
                    var vecLeft = new Vector3(-normal.Y, -normal.Z, -normal.X);
                    OnViewBoxClicked?.Invoke(this, new ViewBoxClickedEventArgs(normal, vecLeft));
                }
                else
                {
                    OnViewBoxClicked?.Invoke(this, new ViewBoxClickedEventArgs(normal, UpDirection));
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
            protected override bool OnHitTest(RenderContext context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
            {
                var   p = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix);
                var   screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore;
                float viewportSize    = screenSpaceCore.Size * screenSpaceCore.SizeScale;
                var   offx            = (float)(context.ActualWidth / 2 * (1 + screenSpaceCore.RelativeScreenLocationX) - viewportSize / 2);
                var   offy            = (float)(context.ActualHeight / 2 * (1 + screenSpaceCore.RelativeScreenLocationY) - viewportSize / 2);

                offx = Math.Max(0, Math.Min(offx, (int)(context.ActualWidth - viewportSize)));
                offy = Math.Max(0, Math.Min(offy, (int)(context.ActualHeight - viewportSize)));
                var px = p.X - offx;
                var py = p.Y - offy;

                if (px < 0 || py < 0 || px > viewportSize || py > viewportSize)
                {
                    return(false);
                }

                var     viewMatrix = screenSpaceCore.GlobalTransform.View;
                Vector3 v          = new Vector3();

                var     matrix      = MatrixExtensions.PsudoInvert(ref viewMatrix);
                var     aspectRatio = screenSpaceCore.ScreenRatio;
                var     projMatrix  = screenSpaceCore.GlobalTransform.Projection;
                Vector3 zn;

                v.X = (2 * px / viewportSize - 1) / projMatrix.M11;
                v.Y = (2 * py / viewportSize - 1) / projMatrix.M22;
                v.Z = 1 / projMatrix.M33;
                Vector3.TransformCoordinate(ref v, ref matrix, out Vector3 zf);
                if (screenSpaceCore.IsPerspective)
                {
                    zn = screenSpaceCore.GlobalTransform.EyePos;
                }
                else
                {
                    v.Z = 0;
                    Vector3.TransformCoordinate(ref v, ref matrix, out zn);
                }

                Vector3 r = zf - zn;

                r.Normalize();

                ray = new Ray(zn, r);
                screenSpaceHits.Clear();
                if (base.OnHitTest(context, totalModelMatrix, ref ray, ref screenSpaceHits))
                {
                    if (hits == null)
                    {
                        hits = new List <HitTestResult>();
                    }
                    hits.Clear();
                    hits.AddRange(screenSpaceHits);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }