Exemplo n.º 1
0
        /// <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 Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            var camera = viewport.Camera as ProjectionCamera;

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

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

                var   matrix      = CameraExtensions.InverseViewMatrix(ref viewMatrix);
                float w           = (float)viewport.ActualWidth;
                float h           = (float)viewport.ActualHeight;
                var   aspectRatio = w / h;

                var     projMatrix = camera.GetProjectionMatrix(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 PerspectiveCamera)
                {
                    zn = camera.Position.ToVector3();
                }
                else
                {
                    v.Z = 0;
                    Vector3.TransformCoordinate(ref v, ref matrix, out zn);
                }
                Vector3 r = zf - zn;
                r.Normalize();

                return(new Ray(zn, r));
            }
            throw new HelixToolkitException("Unproject camera error.");
        }
        /// <summary>
        /// Initial implementation of hittest for billboard. Needs further improvement.
        /// </summary>
        /// <param name="rayWS"></param>
        /// <param name="hits"></param>
        /// <returns></returns>
        protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
        {
            var g      = this.geometryInternal as IBillboardText;
            var h      = false;
            var result = new HitTestResult();

            result.Distance = double.MaxValue;

            if (context == null || g.Width == 0 || g.Height == 0)
            {
                return(false);
            }

            if (g != null)
            {
                BoundingBox b      = new BoundingBox();
                var         left   = -g.Width / 2;
                var         right  = -left;
                var         top    = -g.Height / 2;
                var         bottom = -top;
                if (FixedSize)
                {
                    var viewportMatrix   = context.ViewportMatrix;
                    var projectionMatrix = context.ProjectionMatrix;
                    var viewMatrix       = context.ViewMatrix;
                    var visualToScreen   = viewMatrix * projectionMatrix * viewportMatrix;

                    var center      = new Vector4(g.Positions[0], 1);
                    var screenPoint = Vector4.Transform(center, visualToScreen);
                    var spw         = screenPoint.W;
                    var spx         = screenPoint.X;
                    var spy         = screenPoint.Y;
                    var spz         = screenPoint.Z / spw / projectionMatrix.M33;

                    var     matrix = CameraExtensions.InverseViewMatrix(ref viewMatrix);
                    var     width  = (float)context.ActualWidth;
                    var     height = (float)context.ActualHeight;
                    Vector3 v      = new Vector3();

                    var x = spx + left * spw;
                    var y = spy + bottom * spw;
                    v.X = (2 * x / width / spw - 1) / projectionMatrix.M11;
                    v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22;
                    v.Z = spz;

                    Vector3 bl;
                    Vector3.TransformCoordinate(ref v, ref matrix, out bl);


                    x   = spx + right * spw;
                    y   = spy + bottom * spw;
                    v.X = (2 * x / width / spw - 1) / projectionMatrix.M11;
                    v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22;
                    v.Z = spz;

                    Vector3 br;
                    Vector3.TransformCoordinate(ref v, ref matrix, out br);

                    x   = spx + right * spw;
                    y   = spy + top * spw;
                    v.X = (2 * x / width / spw - 1) / projectionMatrix.M11;
                    v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22;
                    v.Z = spz;

                    Vector3 tr;
                    Vector3.TransformCoordinate(ref v, ref matrix, out tr);

                    x   = spx + left * spw;
                    y   = spy + top * spw;
                    v.X = (2 * x / width / spw - 1) / projectionMatrix.M11;
                    v.Y = -(2 * y / height / spw - 1) / projectionMatrix.M22;
                    v.Z = spz;

                    Vector3 tl;
                    Vector3.TransformCoordinate(ref v, ref matrix, out tl);

                    b = BoundingBox.FromPoints(new Vector3[] { tl, tr, bl, br });

                    /*
                     * var visualToScreen = viewport.GetViewProjectionMatrix() * viewport.GetViewportMatrix();
                     *
                     * var screenToVisual = visualToScreen.Inverted();
                     *
                     * var center = new Vector4(g.Positions[0], 1);
                     * var screenPoint = Vector4.Transform(center, visualToScreen);
                     * var spw = screenPoint.W;
                     * var spx = screenPoint.X;
                     * var spy = screenPoint.Y;
                     * var spz = screenPoint.Z;
                     *
                     * //Debug.WriteLine(spw);
                     * // Debug.WriteLine(string.Format("Z={0}; W={1}", spz, spw));
                     * var bl = new Vector4(spx + left * spw, spy + bottom * spw, spz, spw);
                     * bl = Vector4.Transform(bl, screenToVisual);
                     * bl /= bl.W;
                     *
                     * var br = new Vector4(spx + right * spw, spy + bottom * spw, spz, spw);
                     * br = Vector4.Transform(br, screenToVisual);
                     * br /= br.W;
                     *
                     * var tr = new Vector4(spx + right * spw, spy + top * spw, spz, spw);
                     * tr = Vector4.Transform(tr, screenToVisual);
                     * tr /= tr.W;
                     *
                     * var tl = new Vector4(spx + left * spw, spy + top * spw, spz, spw);
                     * tl = Vector4.Transform(tl, screenToVisual);
                     * tl /= tl.W;
                     *
                     * b = BoundingBox.FromPoints(new Vector3[] { tl.ToVector3(), tr.ToVector3(), bl.ToVector3(), br.ToVector3() });
                     */
                }
                else
                {
                    var center     = new Vector4(g.Positions[0], 1);
                    var viewMatrix = context.ViewMatrix;

                    var vcenter = Vector4.Transform(center, viewMatrix);
                    var vcX     = vcenter.X;
                    var vcY     = vcenter.Y;

                    var bl            = new Vector4(vcX + left, vcY + bottom, vcenter.Z, vcenter.W);
                    var br            = new Vector4(vcX + right, vcY + bottom, vcenter.Z, vcenter.W);
                    var tr            = new Vector4(vcX + right, vcY + top, vcenter.Z, vcenter.W);
                    var tl            = new Vector4(vcX + left, vcY + top, vcenter.Z, vcenter.W);
                    var invViewMatrix = CameraExtensions.InverseViewMatrix(ref viewMatrix);

                    bl  = Vector4.Transform(bl, invViewMatrix);
                    bl /= bl.W;
                    br  = Vector4.Transform(br, invViewMatrix);
                    br /= br.W;
                    tr  = Vector4.Transform(tr, invViewMatrix);
                    tr /= tr.W;
                    tl  = Vector4.Transform(tl, invViewMatrix);
                    tl /= tl.W;
                    b   = BoundingBox.FromPoints(new Vector3[] { tl.ToVector3(), tr.ToVector3(), bl.ToVector3(), br.ToVector3() });
                }

                // this all happens now in world space now:
                //Debug.WriteLine(string.Format("RayPosition:{0}; Direction:{1};", rayWS.Position, rayWS.Direction));
                if (rayWS.Intersects(ref b))
                {
                    float distance;
                    if (Collision.RayIntersectsBox(ref rayWS, ref b, out distance))
                    {
                        h = true;
                        result.ModelHit = this;
                        result.IsValid  = true;
                        result.PointHit = (rayWS.Position + (rayWS.Direction * distance)).ToPoint3D();
                        result.Distance = distance;
                        Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Bound={1}; Distance={2}", result.PointHit, b, distance));
                    }
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }