public float DistanceToRayOrigin(PickRay pickRay)
        {
            var r = SpriteSize / 2;

            Vector3 m  = pickRay.Position - CurrentWorldMatrix.ExtractTranslation();
            float   b  = Vector3.Dot(m, pickRay.Direction);
            float   r2 = r * r;
            float   c  = Vector3.Dot(m, m) - r2;

            // Ray starting outside of the sphere and pointing away.
            if (c > 0 && b > 0)
            {
                return(float.MaxValue);
            }

            float discriminant = b * b - c;

            // Ray missing the sphere.
            if (discriminant < 0)
            {
                return(float.MaxValue);
            }

            float t = -b - (float)Math.Sqrt(discriminant);

            // Ray starting inside sphere.
            if (t < 0)
            {
                t = 0;
            }

            return(t);
        }
Example #2
0
        private bool TestIntersects(SceneNode node)
        {
            if (!(node is ShapeNode) && (node.BoundingBox == null || !node.BoundingBox.IsValid))
            {
                return(true);
            }

            Matrix4 trans  = node.GetWorldTransform(_root).Value;
            Vector3 max    = (trans * new Vector4(node.BoundingBox.Max.Value, 1.0f)).DivW.XYZ;
            Vector3 center = (trans * new Vector4(node.BoundingBox.Center.Value, 1.0f)).DivW.XYZ;
            float   radius = (center - max).Length;

            // plane equation
            float d = _pickRay.Direction.Dot(center);

            // intersection point on plane
            float s = (d - _pickRay.Direction.Dot(_pickRay.Origin)) / _pickRay.Direction.Dot(_pickRay.Direction);

            if (s >= 0 || (_pickRay.Origin - center).Length < radius)
            {
                Vector3 f    = _pickRay.Origin + (_pickRay.Direction * s);
                float   dist = (f - center).Length; // distance of ray from sphere center

                if (dist < radius)                  // ray intersects bounding sphere
                {
                    if (node is ShapeNode)
                    {
                        ShapeNode shapeNode = node as ShapeNode;

                        // transform pick ray to object space
                        Matrix4 invTrans     = node.GetInverseWorldTransform(_root).Value;
                        PickRay localPickRay = new PickRay();
                        localPickRay.Origin    = (invTrans * new Vector4(_pickRay.Origin, 1)).XYZ;
                        localPickRay.Direction = (invTrans * new Vector4(_pickRay.Direction, 0)).XYZ;

                        // pick triangles in geometry
                        Vector3?localPickPoint = shapeNode.Geometry.Pick(localPickRay);

                        if (localPickPoint != null)
                        {
                            Vector3 pickPoint = (trans * new Vector4(localPickPoint.Value, 1)).DivW.XYZ;
                            float   zDist     = (_pickRay.Origin - pickPoint).Length;
                            if (_closestNode == null || zDist < _closestZDist)
                            {
                                _closestZDist = zDist;
                                _closestNode  = shapeNode;
                                _pickPoint    = pickPoint;
                            }
                        }
                    }
                    return(true); // is in bounding sphere
                }
            }

            return(false);
        }
Example #3
0
        private PickingResult?Pick(SceneNode root, PickRay ray)
        {
            _pickRay      = ray;
            _root         = root;
            _closestNode  = null;
            _closestZDist = 0;

            root.Accept(this);

            if (_closestNode != null)
            {
                PickingResult result = new PickingResult();
                result.PickedNode   = _closestNode;
                result.PickingPoint = _pickPoint;
                return(result);
            }

            return(null);
        }
Example #4
0
        // Maybe even better if we could do this based on distance only, and not pointing.
        static List <Vector3> GetSnapTransforms(Matrix4 pointerTransform)
        {
            var gc = (GraphicControl)UIEnvironment.Windows.FirstOrDefault(w => w.Control is GraphicControl)?.Control;

            if (gc == null || gc.IsDisposed)
            {
                return new List <Vector3> {
                           Vector3.ZeroVector
                }
            }
            ;

            var result = new List <Vector3>();

            var pickManager = new PickManager();

            PickRay ray = new PickRay
            {
                Ray = new Ray
                {
                    origin    = pointerTransform.Translation,
                    direction = pointerTransform.UpperLeft.z
                }
            };

            PickData res = new PickData();
            // Ordered by priority
            var snapModes = new[] { SnapMode.Snap, SnapMode.Edge };

            foreach (var snapMode in snapModes)
            {
                pickManager.SnapMode = snapMode;

                pickManager.PickOneObject(gc, ray, true, out res);
                result.Add(res.snapPos);
            }
            // Add the raw hitpoint as well as the least prioritized point
            result.Add(res.rawPos);

            return(result);
        }
    }
Example #5
0
        public void CalculatesPickRay()
        {
            const int x = 100;
            const int y = 200;

            var cameraMock = new Mock <ICamera>();

            cameraMock.Setup(c => c.CurrentFrameViewMatrix).Returns(MathTestHelpers.BuildMatrix(new float[, ]
            {
                { 1, 2, 3, 0 },
                { 1, 2, 3, 0 },
                { 1, 2, 3, 0 },
                { 1, 2, 3, 1 }
            }));
            cameraMock.Setup(c => c.Position).Returns(new Vector3(10, 20, 30));

            ICamera camera = cameraMock.Object;

            var viewSize = new Size(1000, 600);

            Matrix4 projectionMatrix = MathTestHelpers.BuildMatrix(new float[, ]
            {
                { 4, 3, 2, 0 },
                { 4, 3, 2, 0 },
                { 4, 3, 2, 0 },
                { 4, 3, 2, 1 }
            });

            PickRay ray = PickRay.Pick(x, y, camera, viewSize, projectionMatrix);

            var expectedDirection = new Vector3(-0.26726f, -0.53452f, -0.80178f);

            Assert.Equal(camera.Position, ray.Position);

            CompareResult result = MathTestHelpers.VectorCompare(expectedDirection, ray.Direction, 1e-05f);

            Assert.True(result.AreEqual, result.DifferenceString);
        }