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); }
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); }
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); }
// 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); } }
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); }