Esempio n. 1
0
        /// <summary>
        /// Hits the size of the test fixed.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="modelMatrix">The model matrix.</param>
        /// <param name="hits">The hits.</param>
        /// <param name="originalSource">The original source.</param>
        /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param>
        /// <returns></returns>
        protected bool HitTestFixedSize(HitTestContext context, ref Matrix modelMatrix, ref List <HitTestResult> hits,
                                        object originalSource, int count)
        {
            if (BillboardVertices == null || BillboardVertices.Count == 0)
            {
                return(false);
            }
            var h      = false;
            var result = new BillboardHitResult
            {
                Distance = double.MaxValue
            };
            var visualToScreen = context.RenderMatrices.ScreenViewProjectionMatrix;
            var screenPoint    = context.HitPointSP * context.RenderMatrices.DpiScale;

            if (screenPoint.X < 0 || screenPoint.Y < 0)
            {
                return(false);
            }

            for (var i = 0; i < count; ++i)
            {
                var vert = BillboardVertices[i];
                var pos  = vert.Position.ToVector3();
                var c    = Vector3.TransformCoordinate(pos, modelMatrix);
                var dir  = c - context.RayWS.Position;
                if (Vector3.Dot(dir, context.RayWS.Direction) < 0)
                {
                    continue;
                }
                var quad = GetScreenQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref visualToScreen, context.RenderMatrices.DpiScale);
                if (quad.IsPointInQuad2D(ref screenPoint))
                {
                    var v    = c - context.RayWS.Position;
                    var dist = Vector3.Dot(context.RayWS.Direction, v);
                    if (dist > result.Distance)
                    {
                        continue;
                    }
                    h = true;

                    result.ModelHit = originalSource;
                    result.IsValid  = true;
                    result.PointHit = context.RayWS.Position + context.RayWS.Direction * dist;
                    result.Distance = dist;
                    result.Geometry = this;
                    AssignResultAdditional(result, i);
                    if (logger.IsEnabled(LogLevel.Trace))
                    {
                        logger.LogTrace("Hit; HitPoint:{}; Text={}", result.PointHit, (result.TextInfo == null ? Type.ToString() : result.TextInfo.Text));
                    }
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
Esempio n. 2
0
        /// <summary>
        /// Hits the test.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="modelMatrix">The model matrix.</param>
        /// <param name="rayWS">The ray ws.</param>
        /// <param name="hits">The hits.</param>
        /// <param name="originalSource">The original source.</param>
        /// <param name="fixedSize">if set to <c>true</c> [fixed size].</param>
        /// <returns></returns>
        public virtual bool HitTest(RenderContext context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits,
                                    object originalSource, bool fixedSize)
        {
            var h      = false;
            var result = new BillboardHitResult
            {
                Distance = double.MaxValue
            };

            if (context == null || Width == 0 || Height == 0 || (!fixedSize && !BoundingSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS)))
            {
                return(false);
            }
            var scale            = modelMatrix.ScaleVector;
            var left             = -(Width * scale.X) / 2;
            var right            = -left;
            var top              = -(Height * scale.Y) / 2;
            var bottom           = -top;
            var projectionMatrix = context.ProjectionMatrix;
            var viewMatrix       = context.ViewMatrix;
            var viewMatrixInv    = viewMatrix.PsudoInvert();
            var visualToScreen   = context.ScreenViewProjectionMatrix;

            foreach (var center in BillboardVertices.Select(x => x.Position))
            {
                var c   = Vector3.TransformCoordinate(center.ToVector3(), modelMatrix);
                var dir = c - rayWS.Position;
                dir.Normalize();
                if (Vector3.Dot(dir, rayWS.Direction.Normalized()) < 0)
                {
                    continue;
                }

                var b = GetHitTestBound(c,
                                        left, right, top, bottom, ref projectionMatrix, ref viewMatrix, ref viewMatrixInv, ref visualToScreen,
                                        fixedSize, (float)context.ActualWidth, (float)context.ActualHeight);
                if (rayWS.Intersects(ref b))
                {
                    if (Collision.RayIntersectsBox(ref rayWS, ref b, out float distance))
                    {
                        h = true;
                        result.ModelHit = originalSource;
                        result.IsValid  = true;
                        result.PointHit = rayWS.Position + (rayWS.Direction * distance);
                        result.Distance = distance;
                        result.Geometry = this;
                        Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Bound={1}; Distance={2}", result.PointHit, b, distance));
                        break;
                    }
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
Esempio n. 3
0
        /// <summary>
        /// Hits the size of the test fixed.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="modelMatrix">The model matrix.</param>
        /// <param name="rayWS">The ray ws.</param>
        /// <param name="hits">The hits.</param>
        /// <param name="originalSource">The original source.</param>
        /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param>
        /// <returns></returns>
        protected bool HitTestFixedSize(IRenderMatrices context, ref Matrix modelMatrix,
                                        ref Ray rayWS, ref List <HitTestResult> hits,
                                        object originalSource, int count)
        {
            var h      = false;
            var result = new BillboardHitResult
            {
                Distance = double.MaxValue
            };
            var visualToScreen = context.ScreenViewProjectionMatrix;
            var screenPoint3D  = Vector3.TransformCoordinate(rayWS.Position, visualToScreen);
            var screenPoint    = new Vector2(screenPoint3D.X, screenPoint3D.Y);

            if (screenPoint.X < 0 || screenPoint.Y < 0)
            {
                return(false);
            }

            for (int i = 0; i < count; ++i)
            {
                var vert = BillboardVertices[i];
                var pos  = vert.Position.ToVector3();
                var c    = Vector3.TransformCoordinate(pos, modelMatrix);
                var dir  = c - rayWS.Position;
                if (Vector3.Dot(dir, rayWS.Direction) < 0)
                {
                    continue;
                }
                var quad = GetScreenQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref visualToScreen, context.DpiScale);
                if (quad.IsPointInQuad2D(ref screenPoint))
                {
                    var v    = c - rayWS.Position;
                    var dist = Vector3.Dot(rayWS.Direction, v);
                    if (dist > result.Distance)
                    {
                        continue;
                    }
                    h = true;

                    result.ModelHit = originalSource;
                    result.IsValid  = true;
                    result.PointHit = rayWS.Position + rayWS.Direction * dist;
                    result.Distance = dist;
                    result.Geometry = this;
                    AssignResultAdditional(result, i);
                    Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Text={1}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text));
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
Esempio n. 4
0
        /// <summary>
        /// Hits the size of the test non fixed.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="modelMatrix">The model matrix.</param>
        /// <param name="hits">The hits.</param>
        /// <param name="originalSource">The original source.</param>
        /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param>
        /// <returns></returns>
        protected bool HitTestNonFixedSize(HitTestContext context, ref Matrix modelMatrix, ref List <HitTestResult> hits,
                                           object originalSource, int count)
        {
            if (BillboardVertices == null || BillboardVertices.Count == 0)
            {
                return(false);
            }
            var h      = false;
            var result = new BillboardHitResult
            {
                Distance = double.MaxValue
            };
            var viewMatrix    = context.RenderMatrices.ViewMatrix;
            var viewMatrixInv = viewMatrix.PsudoInvert();
            var rayWS         = context.RayWS;

            for (var i = 0; i < count; ++i)
            {
                var vert = BillboardVertices[i];
                var pos  = vert.Position.ToVector3();
                var c    = Vector3.TransformCoordinate(pos, modelMatrix);
                var dir  = c - rayWS.Position;
                if (Vector3.Dot(dir, rayWS.Direction) < 0)
                {
                    continue;
                }
                var quad = GetHitTestQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref viewMatrix, ref viewMatrixInv);
                if (Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.TR, ref quad.BR, out Vector3 hitPoint) ||
                    Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.BR, ref quad.BL, out hitPoint))
                {
                    var dist = (rayWS.Position - hitPoint).Length();
                    if (dist > result.Distance)
                    {
                        continue;
                    }
                    h = true;
                    result.ModelHit = originalSource;
                    result.IsValid  = true;
                    result.PointHit = hitPoint;
                    result.Distance = dist;
                    result.Geometry = this;
                    AssignResultAdditional(result, i);
                    if (logger.IsEnabled(LogLevel.Trace))
                    {
                        logger.LogTrace("Hit; HitPoint:{}; Text={}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text);
                    }
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
Esempio n. 5
0
        /// <summary>
        /// Hits the size of the test non fixed.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="modelMatrix">The model matrix.</param>
        /// <param name="rayWS">The ray ws.</param>
        /// <param name="hits">The hits.</param>
        /// <param name="originalSource">The original source.</param>
        /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param>
        /// <returns></returns>
        protected bool HitTestNonFixedSize(RenderContext context, ref Matrix modelMatrix,
                                           ref Ray rayWS, ref List <HitTestResult> hits,
                                           object originalSource, int count)
        {
            var h      = false;
            var result = new BillboardHitResult
            {
                Distance = double.MaxValue
            };
            var viewMatrix    = context.ViewMatrix;
            var viewMatrixInv = viewMatrix.PsudoInvert();
            var scale3D       = modelMatrix.ScaleVector;
            var scale         = new Vector2(scale3D.X, scale3D.Y);

            for (int i = 0; i < count; ++i)
            {
                var vert = BillboardVertices[i];
                var pos  = vert.Position.ToVector3();
                var c    = Vector3.TransformCoordinate(pos, modelMatrix);
                var dir  = c - rayWS.Position;
                if (Vector3.Dot(dir, rayWS.Direction) < 0)
                {
                    continue;
                }
                var quad = GetHitTestQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref viewMatrix, ref viewMatrixInv, ref scale);
                if (Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.TR, ref quad.BR, out Vector3 hitPoint) ||
                    Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.BR, ref quad.BL, out hitPoint))
                {
                    var dist = (rayWS.Position - hitPoint).Length();
                    if (dist > result.Distance)
                    {
                        continue;
                    }
                    h = true;
                    result.ModelHit = originalSource;
                    result.IsValid  = true;
                    result.PointHit = hitPoint;
                    result.Distance = dist;
                    result.Geometry = this;
                    AssignResultAdditional(result, i);
                    Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Text={1}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text));
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
 protected override void AssignResultAdditional(BillboardHitResult result, int index)
 {
     base.AssignResultAdditional(result, index);
     result.TextInfo      = this.TextInfo;
     result.TextInfoIndex = index;
 }
Esempio n. 7
0
        public override bool HitTest(RenderContext context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits,
                                     object originalSource, bool fixedSize)
        {
            var h      = false;
            var result = new BillboardHitResult();

            result.Distance = double.MaxValue;

            if (context == null || Width == 0 || Height == 0)
            {
                return(false);
            }
            var scale            = modelMatrix.ScaleVector;
            var projectionMatrix = context.ProjectionMatrix;
            var viewMatrix       = context.ViewMatrix;
            var viewMatrixInv    = viewMatrix.PsudoInvert();
            var visualToScreen   = context.ScreenViewProjectionMatrix;
            int index            = -1;

            foreach (var info in TextInfo)
            {
                ++index;
                var c   = Vector3.TransformCoordinate(info.Origin, modelMatrix);
                var dir = c - rayWS.Position;
                dir.Normalize();
                if (Vector3.Dot(dir, rayWS.Direction.Normalized()) < 0)
                {
                    continue;
                }

                if (!fixedSize && !info.BoundSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS))
                {
                    continue;
                }
                var left   = -(info.ActualWidth * scale.X) / 2;
                var right  = -left;
                var top    = -(info.AcutalHeight * scale.Y) / 2;
                var bottom = -top;
                var b      = GetHitTestBound(c,
                                             left, right, top, bottom, ref projectionMatrix, ref viewMatrix, ref viewMatrixInv, ref visualToScreen,
                                             fixedSize, (float)context.ActualWidth, (float)context.ActualHeight);

                if (rayWS.Intersects(ref b))
                {
                    float distance;
                    if (Collision.RayIntersectsBox(ref rayWS, ref b, out distance))
                    {
                        h = true;
                        result.ModelHit      = originalSource;
                        result.IsValid       = true;
                        result.PointHit      = rayWS.Position + (rayWS.Direction * distance);
                        result.Distance      = distance;
                        result.TextInfo      = info;
                        result.TextInfoIndex = index;
                        Debug.WriteLine($"Hit; Text:{info.Text}; HitPoint:{result.PointHit};");
                        break;
                    }
                }
            }
            if (h)
            {
                hits.Add(result);
            }
            return(h);
        }
Esempio n. 8
0
 protected virtual void AssignResultAdditional(BillboardHitResult result, int index)
 {
     result.TextInfoIndex = index;
     result.Type          = Type;
 }