/// <summary>
        ///
        /// </summary>
        public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
        {
            if (CanHitTest(context))
            {
                if ((this.instanceInternal != null) && (this.instanceInternal.Any()))
                {
                    bool hit = false;
                    int  idx = 0;
                    foreach (var modelMatrix in instanceInternal)
                    {
                        var b = this.Bounds;
                        this.PushMatrix(modelMatrix);
                        if (OnHitTest(context, rayWS, ref hits))
                        {
                            hit = true;
                            var lastHit = hits[hits.Count - 1];
                            lastHit.Tag          = idx;
                            hits[hits.Count - 1] = lastHit;
                        }
                        this.PopMatrix();
                        ++idx;
                    }

                    return(hit);
                }
                else
                {
                    return(OnHitTest(context, rayWS, ref hits));
                }
            }
            else
            {
                return(false);
            }
        }
 protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
 {
     if (ray.Intersects(boundsWithTransform) && ray.Intersects(boundsSphereWithTransform))
     {
         if (BatchedGeometryOctree != null && BatchedGeometryOctree.TreeBuilt)
         {
             return(BatchedGeometryOctree.HitTest(context, WrapperSource, null, totalModelMatrix, ray, ref hits));
         }
         else
         {
             bool isHit = false;
             foreach (var geo in Geometries)
             {
                 if (geo.Geometry is MeshGeometry3D mesh)
                 {
                     isHit |= mesh.HitTest(context, geo.ModelTransform * totalModelMatrix, ref ray, ref hits, WrapperSource);
                 }
             }
             return(isHit);
         }
     }
     else
     {
         return(false);
     }
 }
            public override bool HitTestCurrentNodeExcludeChild(IRenderMatrices context, object model, Geometry3D geometry, Matrix modelMatrix, ref Ray rayWS, ref Ray rayModel,
                                                                ref List <HitTestResult> hits, ref bool isIntersect, float hitThickness)
            {
                isIntersect = false;
                if (!this.treeBuilt)
                {
                    return(false);
                }
                bool isHit = false;
                //var bound = Bound.Transform(modelMatrix);// BoundingBox.FromPoints(Bound.GetCorners().Select(x => Vector3.TransformCoordinate(x, modelMatrix)).ToArray());
                var bound    = Bound;
                var tempHits = new List <HitTestResult>();

                if (rayWS.Intersects(ref bound))
                {
                    isIntersect = true;
                    foreach (var r in this.Objects)
                    {
                        isHit |= r.HitTest(context, rayWS, ref tempHits);
                        hits.AddRange(tempHits);
                        tempHits.Clear();
                    }
                }
                return(isHit);
            }
        /// <summary>
        /// Compute hit-testing for all children
        /// </summary>
        protected override bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits)
        {
            bool hit = false;

            foreach (var item in this.children)
            {
                var hc = item as IHitable;
                if (hc != null)
                {
                    var tc = item as ITransformable;
                    if (tc != null)
                    {
                        tc.PushMatrix(this.modelMatrix);
                        if (hc.HitTest(context, ray, ref hits))
                        {
                            hit = true;
                        }
                        tc.PopMatrix();
                    }
                    else
                    {
                        if (hc.HitTest(context, ray, ref hits))
                        {
                            hit = true;
                        }
                    }
                }
            }
            return(hit);
        }
예제 #5
0
            private bool CreateRelativeScreenModeRay(IRenderMatrices context, ref Ray ray, out Ray newRay)
            {
                var p = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix);
                var screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore;

                screenSpacedContext.IsPerspective = screenSpaceCore.IsPerspective;
                float viewportSize = screenSpaceCore.Size * screenSpaceCore.SizeScale * context.DpiScale;

                float offx = (float)(context.ActualWidth / 2 * (1 + screenSpaceCore.RelativeScreenLocationX) - viewportSize / 2);
                float 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)
                {
                    newRay = new Ray();
                    return(false);
                }

                var viewMatrix = screenSpaceCore.GlobalTransform.View;
                var projMatrix = screenSpaceCore.GlobalTransform.Projection;

                newRay = RayExtensions.UnProject(new Vector2(px, py), ref viewMatrix, ref projMatrix,
                                                 screenSpaceCore.NearPlane, viewportSize, viewportSize, screenSpaceCore.IsPerspective);
                screenSpacedContext.ViewMatrix       = viewMatrix;
                screenSpacedContext.ProjectionMatrix = projMatrix;
                screenSpacedContext.ActualWidth      = screenSpacedContext.ActualHeight = viewportSize;
                screenSpacedContext.UpdateScreenViewProjectionMatrix();
                return(true);
            }
예제 #6
0
            protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
            {
                Ray  newRay = ray;
                bool preHit = false;

                switch (Mode)
                {
                case ScreenSpacedMode.RelativeScreenSpaced:
                    preHit = CreateRelativeScreenModeRay(context, ref ray, out newRay);
                    break;

                case ScreenSpacedMode.AbsolutePosition3D:
                    preHit = CreateAbsoluteModeRay(context, ref ray, out newRay);
                    break;
                }
                if (!preHit)
                {
                    return(false);
                }
                screenSpaceHits.Clear();
                if (base.OnHitTest(screenSpacedContext, totalModelMatrix, ref newRay, ref screenSpaceHits))
                {
                    if (hits == null)
                    {
                        hits = new List <HitTestResult>();
                    }
                    hits.Clear();
                    hits.AddRange(screenSpaceHits);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
예제 #7
0
 protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
 {
     //Set hit distance to 0 so event manipulator is inside the model, hit test still works
     if (base.OnHitTest(context, totalModelMatrix, ref ray, ref hits))
     {
         if (hits.Count > 0)
         {
             HitTestResult res = new HitTestResult()
             {
                 Distance = int.MaxValue
             };
             foreach (var hit in hits)
             {
                 if (hit.ModelHit == cornerHandle || hit.ModelHit == edgeHandle)
                 {
                     if (res.Distance > hit.Distance)
                     {
                         res = hit;
                     }
                 }
             }
             res.Distance = 0;
         }
         return(true);
     }
     else
     {
         return(false);
     }
 }
예제 #8
0
        protected virtual bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits)
        {
            bool hit = false;

            foreach (var c in this.Items)
            {
                var hc = c as IHitable;
                if (hc != null)
                {
                    var tc = c as ITransformable;
                    if (tc != null)
                    {
                        tc.PushMatrix(this.modelMatrix);
                        if (hc.HitTest(context, ray, ref hits))
                        {
                            hit = true;
                        }
                        tc.PopMatrix();
                    }
                    else
                    {
                        if (hc.HitTest(context, ray, ref hits))
                        {
                            hit = true;
                        }
                    }
                }
            }
            if (hit)
            {
                hits = hits.OrderBy(x => Vector3.DistanceSquared(ray.Position, x.PointHit.ToVector3())).ToList();
            }
            return(hit);
        }
예제 #9
0
 /// <summary>
 ///
 /// </summary>
 public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
 {
     if (CanHitTest(context) && PreHitTestOnBounds(ref rayWS))
     {
         if (this.InstanceBuffer.HasElements)
         {
             bool hit = false;
             int  idx = 0;
             foreach (var modelMatrix in InstanceBuffer.Elements)
             {
                 if (OnHitTest(context, modelMatrix * TotalModelMatrixInternal, ref rayWS, ref hits))
                 {
                     hit = true;
                     var lastHit = hits[hits.Count - 1];
                     lastHit.Tag          = idx;
                     hits[hits.Count - 1] = lastHit;
                 }
                 ++idx;
             }
             return(hit);
         }
         else
         {
             return(OnHitTest(context, TotalModelMatrixInternal, ref rayWS, ref hits));
         }
     }
     else
     {
         return(false);
     }
 }
        /// <summary>
        /// Checks if the ray hits the geometry of the model.
        /// If there a more than one hit, result returns the hit which is nearest to the ray origin.
        /// </summary>
        /// <param name="rayWS">Hitring ray from the camera.</param>
        /// <param name="hits">results of the hit.</param>
        /// <returns>True if the ray hits one or more times.</returns>
        protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
        {
            if (geometryInternal.Octree != null)
            {
                return(geometryInternal.Octree.HitTest(context, this, ModelMatrix, rayWS, ref hits));
            }
            else
            {
                PointGeometry3D pointGeometry3D = this.geometryInternal as PointGeometry3D;
                var             svpm            = context.ScreenViewProjectionMatrix;
                var             smvpm           = this.modelMatrix * svpm;

                var clickPoint4 = new Vector4(rayWS.Position + rayWS.Direction, 1);
                var pos4        = new Vector4(rayWS.Position, 1);
                // var dir3 = new Vector3();
                Vector4.Transform(ref clickPoint4, ref svpm, out clickPoint4);
                Vector4.Transform(ref pos4, ref svpm, out pos4);
                //Vector3.TransformNormal(ref rayWS.Direction, ref svpm, out dir3);
                //dir3.Normalize();

                var clickPoint = clickPoint4.ToVector3();

                var result = new HitTestResult {
                    IsValid = false, Distance = double.MaxValue
                };
                var maxDist  = this.HitTestThickness;
                var lastDist = double.MaxValue;
                var index    = 0;

                foreach (var point in pointGeometry3D.Positions)
                {
                    var p0   = Vector3.TransformCoordinate(point, smvpm);
                    var pv   = p0 - clickPoint;
                    var dist = pv.Length();
                    if (dist < lastDist && dist <= maxDist)
                    {
                        lastDist = dist;
                        Vector4 res;
                        var     lp0 = point;
                        Vector3.Transform(ref lp0, ref this.modelMatrix, out res);
                        var pvv = res.ToVector3();
                        result.Distance = (rayWS.Position - res.ToVector3()).Length();
                        result.PointHit = pvv.ToPoint3D();
                        result.ModelHit = this;
                        result.IsValid  = true;
                        result.Tag      = index;
                    }

                    index++;
                }

                if (result.IsValid)
                {
                    hits.Add(result);
                }

                return(result.IsValid);
            }
        }
예제 #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HitTestContext"/> class.
 /// This calculates screen hit point automatically from metrices and world space ray.
 /// </summary>
 /// <param name="metrices">The render metrices.</param>
 /// <param name="rayWS">The ray in world space.</param>
 public HitTestContext(IRenderMatrices metrices, ref Ray rayWS)
 {
     RenderMatrices = metrices;
     RayWS          = rayWS;
     if (metrices != null)
     {
         HitPointSP = metrices.Project(rayWS.Position);
     }
 }
        public static Vector2 Project(this IRenderMatrices renderMatrices, Vector3 point)
        {
            renderMatrices.Update();
            var matrix           = renderMatrices.ScreenViewProjectionMatrix;
            var pointTransformed = Vector3.TransformCoordinate(point, matrix);
            var pt = new Vector2(pointTransformed.X, pointTransformed.Y) / renderMatrices.DpiScale;

            return(pt);
        }
예제 #13
0
        public virtual bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, float hitTestThickness)
        {
            if (Positions == null || Positions.Count == 0 ||
                Indices == null || Indices.Count == 0)
            {
                return(false);
            }

            if (Octree != null)
            {
                return(Octree.HitTest(context, originalSource, this, modelMatrix, rayWS, ref hits, hitTestThickness));
            }
            else
            {
                var result = new LineHitTestResult {
                    IsValid = false, Distance = double.MaxValue
                };
                var lastDist  = double.MaxValue;
                var lineIndex = 0;
                foreach (var line in Lines)
                {
                    var t0 = Vector3.TransformCoordinate(line.P0, modelMatrix);
                    var t1 = Vector3.TransformCoordinate(line.P1, modelMatrix);
                    var rayToLineDistance = LineBuilder.GetRayToLineDistance(rayWS, t0, t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc);
                    var svpm = context.ScreenViewProjectionMatrix;
                    Vector3.TransformCoordinate(ref sp, ref svpm, out var sp3);
                    Vector3.TransformCoordinate(ref tp, ref svpm, out var tp3);
                    var tv2  = new Vector2(tp3.X - sp3.X, tp3.Y - sp3.Y);
                    var dist = tv2.Length() / context.DpiScale;
                    if (dist < lastDist && dist <= hitTestThickness)
                    {
                        lastDist                  = dist;
                        result.PointHit           = sp;
                        result.NormalAtHit        = sp - tp; // not normalized to get length
                        result.Distance           = (rayWS.Position - sp).Length();
                        result.RayToLineDistance  = rayToLineDistance;
                        result.ModelHit           = originalSource;
                        result.IsValid            = true;
                        result.Tag                = lineIndex; // For compatibility
                        result.LineIndex          = lineIndex;
                        result.TriangleIndices    = null;      // Since triangles are shader-generated
                        result.RayHitPointScalar  = sc;
                        result.LineHitPointScalar = tc;
                        result.Geometry           = this;
                    }

                    lineIndex++;
                }

                if (result.IsValid)
                {
                    hits.Add(result);
                }
                return(result.IsValid);
            }
        }
예제 #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HitTestContext"/> class.
 /// This calculates ray in world space automatically from metrices and hit point.
 /// </summary>
 /// <param name="metrices">The render metrices.</param>
 /// <param name="hitSP">Screen hit point. Pass in the hit point on viewport region directly.
 /// <para>Do not scale with DpiScale factor.</para></param>
 public HitTestContext(IRenderMatrices metrices, ref Vector2 hitSP)
 {
     RenderMatrices = metrices;
     HitPointSP     = hitSP;
     if (metrices != null)
     {
         metrices.UnProject(hitSP, out var ray);
         RayWS = ray;
     }
 }
예제 #15
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);
        }
예제 #16
0
        public override bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits,
                                     object originalSource, bool fixedSize)
        {
            if (!IsInitialized || context == null || Width == 0 || Height == 0 || (!fixedSize && !BoundingSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS)))
            {
                return(false);
            }

            return(fixedSize ? HitTestFixedSize(context, ref modelMatrix, ref rayWS, ref hits, originalSource, textInfo.Count)
                : HitTestNonFixedSize(context, ref modelMatrix, ref rayWS, ref hits, originalSource, textInfo.Count));
        }
예제 #17
0
        public virtual bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, float hitThickness)
        {
            if (Positions == null || Positions.Count == 0)
            {
                return(false);
            }
            if (Octree != null)
            {
                return(Octree.HitTest(context, originalSource, this, modelMatrix, rayWS, ref hits, hitThickness));
            }
            else
            {
                var svpm  = context.ScreenViewProjectionMatrix;
                var smvpm = modelMatrix * svpm;

                var clickPoint3 = rayWS.Position + rayWS.Direction;
                Vector3.TransformCoordinate(ref clickPoint3, ref svpm, out var clickPoint);

                var result = new HitTestResult {
                    IsValid = false, Distance = double.MaxValue
                };
                var maxDist  = hitThickness;
                var lastDist = double.MaxValue;
                var index    = 0;

                foreach (var point in Positions)
                {
                    var p0   = Vector3.TransformCoordinate(point, smvpm);
                    var pv   = p0 - clickPoint;
                    var dist = pv.Length() / context.DpiScale;
                    if (dist < lastDist && dist <= maxDist)
                    {
                        lastDist = dist;
                        var lp0 = point;
                        Vector3.TransformCoordinate(ref lp0, ref modelMatrix, out var pvv);
                        result.Distance = (rayWS.Position - pvv).Length();
                        result.PointHit = pvv;
                        result.ModelHit = originalSource;
                        result.IsValid  = true;
                        result.Tag      = index;
                        result.Geometry = this;
                    }

                    index++;
                }

                if (result.IsValid)
                {
                    hits.Add(result);
                }

                return(result.IsValid);
            }
        }
예제 #18
0
 /// <summary>
 /// Checks if the ray hits the geometry of the model.
 /// If there a more than one hit, result returns the hit which is nearest to the ray origin.
 /// </summary>
 /// <param name="context">Render context from viewport</param>
 /// <param name="rayWS">Hitring ray from the camera.</param>
 /// <param name="hits">results of the hit.</param>
 /// <returns>True if the ray hits one or more times.</returns>
 public virtual bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
 {
     if (CanHitTest(context))
     {
         return(OnHitTest(context, rayWS, ref hits));
     }
     else
     {
         return(false);
     }
 }
예제 #19
0
 /// <summary>
 /// Called when [hit test].
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="totalModelMatrix">The total model matrix.</param>
 /// <param name="ray">The ray.</param>
 /// <param name="hits">The hits.</param>
 /// <returns></returns>
 protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
 {
     if (Material is BillboardMaterialCore c)
     {
         return((Geometry as BillboardBase).HitTest(context, totalModelMatrix, ref ray, ref hits, this.WrapperSource, c.FixedSize));
     }
     else
     {
         return(false);
     }
 }
예제 #20
0
            /// <summary>
            /// Called when [hit test].
            /// </summary>
            /// <param name="context">The context.</param>
            /// <param name="totalModelMatrix">The total model matrix.</param>
            /// <param name="ray">The ray.</param>
            /// <param name="hits">The hits.</param>
            /// <returns></returns>
            protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
            {
                bool hit = false;

                foreach (var c in this.ItemsInternal)
                {
                    if (c.HitTest(context, ray, ref hits))
                    {
                        hit = true;
                    }
                }
                return(hit);
            }
예제 #21
0
        protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
        {
            var lineGeometry3D = this.geometryInternal as LineGeometry3D;
            var result         = new LineHitTestResult {
                IsValid = false, Distance = double.MaxValue
            };
            var lastDist  = double.MaxValue;
            var lineIndex = 0;

            foreach (var line in lineGeometry3D.Lines)
            {
                var     t0 = Vector3.TransformCoordinate(line.P0, this.ModelMatrix);
                var     t1 = Vector3.TransformCoordinate(line.P1, this.ModelMatrix);
                Vector3 sp, tp;
                float   sc, tc;
                var     rayToLineDistance = LineBuilder.GetRayToLineDistance(rayWS, t0, t1, out sp, out tp, out sc, out tc);
                var     svpm = context.ScreenViewProjectionMatrix;
                Vector4 sp4;
                Vector4 tp4;
                Vector3.Transform(ref sp, ref svpm, out sp4);
                Vector3.Transform(ref tp, ref svpm, out tp4);
                var sp3  = sp4.ToVector3();
                var tp3  = tp4.ToVector3();
                var tv2  = new Vector2(tp3.X - sp3.X, tp3.Y - sp3.Y);
                var dist = tv2.Length();
                if (dist < lastDist && dist <= this.HitTestThickness)
                {
                    lastDist                  = dist;
                    result.PointHit           = sp.ToPoint3D();
                    result.NormalAtHit        = (sp - tp).ToVector3D(); // not normalized to get length
                    result.Distance           = (rayWS.Position - sp).Length();
                    result.RayToLineDistance  = rayToLineDistance;
                    result.ModelHit           = this;
                    result.IsValid            = true;
                    result.Tag                = lineIndex; // For compatibility
                    result.LineIndex          = lineIndex;
                    result.TriangleIndices    = null;      // Since triangles are shader-generated
                    result.RayHitPointScalar  = sc;
                    result.LineHitPointScalar = tc;
                }

                lineIndex++;
            }

            if (result.IsValid)
            {
                hits.Add(result);
            }

            return(result.IsValid);
        }
예제 #22
0
            public override bool HitTest(IRenderMatrices context, object model, Matrix modelMatrix, Ray rayWS, ref List <HitTestResult> hits)
            {
                if (Octree == null)
                {
                    return(false);
                }
                var hit = Octree.HitTest(context, model, null, modelMatrix, rayWS, ref hits);

                foreach (var item in NonBoundableItems)
                {
                    hit |= item.HitTest(context, rayWS, ref hits);
                }
                return(hit);
            }
예제 #23
0
            private bool CreateAbsoluteModeRay(IRenderMatrices context, ref Ray ray, out Ray newRay)
            {
                var screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore;

                screenSpacedContext.IsPerspective = screenSpaceCore.IsPerspective;
                var viewMatrix = screenSpaceCore.GlobalTransform.View;
                var projMatrix = screenSpaceCore.GlobalTransform.Projection;

                screenSpacedContext.ViewMatrix       = viewMatrix;
                screenSpacedContext.ProjectionMatrix = projMatrix;
                if (context.IsPerspective)
                {
                    var point2d = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix);
                    newRay = RayExtensions.UnProject(new Vector2(point2d.X, point2d.Y), ref viewMatrix, ref projMatrix,
                                                     screenSpaceCore.NearPlane,
                                                     context.ActualWidth, context.ActualHeight, screenSpaceCore.IsPerspective);
                    screenSpacedContext.ActualWidth  = context.ActualWidth;
                    screenSpacedContext.ActualHeight = context.ActualHeight;
                    screenSpacedContext.UpdateScreenViewProjectionMatrix();
                    return(true);
                }
                else
                {
                    var   p            = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix);
                    float viewportSize = screenSpaceCore.Size * screenSpaceCore.SizeScale * context.DpiScale;

                    var   abs  = Vector3.TransformCoordinate(AbsolutePosition3D, context.ScreenViewProjectionMatrix);
                    float offx = (float)(abs.X - viewportSize / 2);
                    float offy = (float)(abs.Y - viewportSize / 2);

                    var px = p.X - offx;
                    var py = p.Y - offy;

                    if (px < 0 || py < 0 || px > viewportSize || py > viewportSize)
                    {
                        newRay = new Ray();
                        return(false);
                    }

                    newRay = RayExtensions.UnProject(new Vector2(px, py), ref viewMatrix, ref projMatrix,
                                                     screenSpaceCore.NearPlane, viewportSize, viewportSize, screenSpaceCore.IsPerspective);
                    screenSpacedContext.ActualWidth      = viewportSize;
                    screenSpacedContext.ActualHeight     = viewportSize;
                    screenSpacedContext.ViewMatrix       = viewMatrix;
                    screenSpacedContext.ProjectionMatrix = projMatrix;
                    screenSpacedContext.UpdateScreenViewProjectionMatrix();
                    return(true);
                }
            }
예제 #24
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(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 viewMatrix    = context.ViewMatrix;
            var viewMatrixInv = viewMatrix.PsudoInvert();

            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);
                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);
        }
예제 #25
0
 protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits)
 {
     if (base.OnHitTest(context, totalModelMatrix, ref ray, ref hits))
     {
         Debug.WriteLine("View box hit.");
         var     hit    = hits[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();
         hit.NormalAtHit = normal;
         return(true);
     }
     else
     {
         return(false);
     }
 }
        public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits)
        {
            if (initialColor == null)
            {
                initialColor = this.Color;
            }

            var result = base.HitTest(context, rayWS, ref hits); // this.HitTest2D(rayWS, ref hits);
            var pressedMouseButtons = Viewport3DX.GetPressedMouseButtons();

            if (pressedMouseButtons == 0 || pressedMouseButtons.HasFlag(MouseButtons.Left))
            {
                this.Color = result ? Color.Red : this.initialColor.Value;
            }

            return(result);
        }
예제 #27
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ray"></param>
        /// <param name="hits"></param>
        /// <returns></returns>
        protected override bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits)
        {
            bool hit = false;

            foreach (var c in this.Children)
            {
                var hc = c as IHitable;
                if (hc != null)
                {
                    if (hc.HitTest(context, ray, ref hits))
                    {
                        hit = true;
                    }
                }
            }
            return(hit);
        }
 protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray rayWS, ref List <HitTestResult> hits)
 {
     if (BoneMatrices.Length > 0 && Geometry is BoneSkinnedMeshGeometry3D skGeometry)
     {
         if (RenderCore is BoneSkinRenderCore skCore)
         {
             if (skinnedVerticesCache.Length < skGeometry.Positions.Count)
             {
                 skinnedVerticesCache = new Vector3[skGeometry.Positions.Count];
             }
             if (skCore.CopySkinnedToArray(context.RenderHost.ImmediateDeviceContext, skinnedVerticesCache) > 0)
             {
                 return(skGeometry.HitTestWithSkinnedVertices(context, skinnedVerticesCache,
                                                              totalModelMatrix, ref rayWS, ref hits, WrapperSource));
             }
         }
     }
     return(base.OnHitTest(context, totalModelMatrix, ref rayWS, ref hits));
 }
        /// <summary>
        /// Un-project 2D screen point onto 3D space by camera.
        /// </summary>
        /// <param name="renderMatrices">The renderMatrices.</param>
        /// <param name="point2d">The point2d.</param>
        /// <param name="ray">The ray.</param>
        /// <returns></returns>
        public static bool UnProject(this IRenderMatrices renderMatrices, Vector2 point2d, out Ray ray)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            if (renderMatrices == null)
            {
                ray = new Ray();
                return(false);
            }

            renderMatrices.Update();
            var px = point2d.X;
            var py = point2d.Y;

            var viewInv    = renderMatrices.ViewMatrixInv;
            var projMatrix = renderMatrices.ProjectionMatrix;

            var w = renderMatrices.ActualWidth / renderMatrices.DpiScale;
            var h = renderMatrices.ActualHeight / renderMatrices.DpiScale;

            var 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 viewInv, out var zf);
            Vector3 zn;

            if (renderMatrices.IsPerspective)
            {
                zn = viewInv.Row4.ToVector3();
            }
            else
            {
                v.Z = 0;
                Vector3.TransformCoordinate(ref v, ref viewInv, out zn);
            }
            var r = zf - zn;

            r.Normalize();
            ray = new Ray(zn + r * renderMatrices.CameraParams.ZNear, r);
            return(true);
        }
예제 #30
0
            /// <summary>
            /// Called when [hit test].
            /// </summary>
            /// <param name="context">The context.</param>
            /// <param name="totalModelMatrix">The total model matrix.</param>
            /// <param name="ray">The ray.</param>
            /// <param name="hits">The hits.</param>
            /// <returns></returns>
            protected override bool OnHitTest(IRenderMatrices context, global::SharpDX.Matrix totalModelMatrix, ref global::SharpDX.Ray ray, ref List <HitTestResult> hits)
            {
                bool isHit = false;

                if (octreeManager != null)
                {
                    isHit = octreeManager.HitTest(context, this.WrapperSource, totalModelMatrix, ray, ref hits);
    #if DEBUG
                    if (isHit)
                    {
                        Debug.WriteLine("Octree hit test, hit at " + hits[0].PointHit);
                    }
    #endif
                }
                else
                {
                    isHit = base.OnHitTest(context, totalModelMatrix, ref ray, ref hits);
                }
                return(isHit);
            }