private void grdViewPort_MouseMove(object sender, MouseEventArgs e) { try { if (_clickPlane == null) { return; } // Fire a ray at the mouse point Point clickPoint2D = e.GetPosition(grdViewPort); RayHitTestParameters clickRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, clickPoint2D); Point3D?hitPoint = Math3D.GetIntersection_Plane_Line(_clickPlane, clickRay.Origin, clickRay.Direction); if (hitPoint == null) { return; } _strokes.AddPointToStroke(hitPoint.Value); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
private static Point3D?CastRay_Plane(ITriangle plane, RayHitTestParameters mouseDownClickRay, RayHitTestParameters mouseDownCenterRay, RayHitTestParameters currentClickRay) { // This is the offset along the drag plane from the center to mouse down click Vector3D offset; Point3D?mouseDownClickPoint = Math3D.GetIntersection_Plane_Line(plane, mouseDownClickRay.Origin, mouseDownClickRay.Direction); Point3D?mouseDownCenterPoint = Math3D.GetIntersection_Plane_Line(plane, mouseDownCenterRay.Origin, mouseDownCenterRay.Direction); if (mouseDownClickPoint != null && mouseDownCenterPoint != null) { offset = mouseDownCenterPoint.Value - mouseDownClickPoint.Value; } else { // The click ray is parallel to the drag plane. This should be extremely rare offset = new Vector3D(0, 0, 0); } // Now that the offset is known, project the current click ray onto the drag plane Point3D?retVal = Math3D.GetIntersection_Plane_Line(plane, currentClickRay.Origin, currentClickRay.Direction); if (retVal != null) { return(retVal.Value + offset); } else { return(null); } }
/// <summary> /// Orbits around a point that is OrbitRadius away. If they are holding in shift, it will /// fire a cone ray and orbit around what they are looking at /// </summary> /// <remarks> /// Got this here /// http://wiki.unity3d.com/index.php?title=MouseOrbitImproved#Code_C.23 /// </remarks> private void OrbitCamera(bool isRightDown, bool isShiftDown, float mouseX, float mouseY) { if (isRightDown) { float deltaTime = Math.Min(Time.deltaTime, MAXDELTA); _eulerX += mouseX * MouseSensitivity_Orbit * deltaTime; // the example multiplies this by orbit radius, but not Y _eulerY -= mouseY * MouseSensitivity_Orbit * deltaTime; _eulerY = UtilityMath.ClampAngle(_eulerY, MinAngle_Y, MaxAngle_Y); Quaternion rotation = Quaternion.Euler(_eulerY, _eulerX, 0); Vector3 lookAtPoint; float radius; if (_isLookAtPointSet) { lookAtPoint = _lookAtPoint; radius = (transform.position - lookAtPoint).magnitude; } else { lookAtPoint = transform.position + (transform.forward * OrbitRadius); radius = OrbitRadius; } if (isShiftDown && !_isLookAtPointSet) { Ray lookRay = new Ray(transform.position, transform.forward); var coneHits = UtilityUnity.ConeCastAll(lookRay, radius, MaxOrbitRadius, 12). Select(o => new { hit = o, //intersect = Math3D.GetClosestPoint_Line_Point(lookRay, o.point), // this finds the closest point on the look ray, perpendicular to the look ray intersect = Math3D.GetIntersection_Plane_Line(new Plane(lookRay.origin - o.point, o.point), lookRay), // this finds a point on the look ray, perpendicular to the cone match ray (using this because it gives a better indication of what is "closest". something that is closer to the camera, but higher angle from the look ray could project to be farther away than something that is lower angle, but slightly farther from the camera) }). Where(o => o.intersect != null). // it should never be null Select(o => new { o.hit, intersect = o.intersect.Value, distance = (o.intersect.Value - lookRay.origin).sqrMagnitude, }). ToArray(); if (coneHits.Length > 0) { var closest = coneHits. OrderBy(o => o.distance). First(); radius = (float)Math.Sqrt(closest.distance); lookAtPoint = closest.intersect; _lookAtPoint = lookAtPoint; _isLookAtPointSet = true; } } Vector3 negRadius = new Vector3(0.0f, 0.0f, -radius); Vector3 position = rotation * negRadius + lookAtPoint; transform.rotation = rotation; transform.position = position; } else { _isLookAtPointSet = false; } }
/// <summary> /// This overload is a straight ray cast, nothing extra /// </summary> public Point3D?CastRay(RayHitTestParameters ray) { Point3D?retVal = null; switch (_shape) { case ShapeType.Line: #region Line Point3D?point1, point2; if (Math3D.GetClosestPoints_Line_Line(out point1, out point2, _point, _direction, ray.Origin, ray.Direction)) { retVal = point1.Value; } #endregion break; case ShapeType.Lines: #region Lines retVal = CastRay_LinesCircles(_lines, null, ray); #endregion break; case ShapeType.Plane: #region Plane retVal = Math3D.GetIntersection_Plane_Line(_plane, ray.Origin, ray.Direction); #endregion break; case ShapeType.Circle: #region Circle Point3D[] nearestCirclePoints, nearestLinePoints; if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, _plane, _point, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay)) { retVal = nearestCirclePoints[0]; } #endregion break; case ShapeType.Circles: #region Circles retVal = CastRay_LinesCircles(null, _circles, ray); #endregion break; case ShapeType.LinesCircles: #region LinesCircles retVal = CastRay_LinesCircles(_lines, _circles, ray); #endregion break; case ShapeType.Cylinder: #region Cylinder Point3D[] nearestCylinderPoints, nearestLinePoints2; if (Math3D.GetClosestPoints_Cylinder_Line(out nearestCylinderPoints, out nearestLinePoints2, _point, _direction, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay)) { retVal = nearestCylinderPoints[0]; } #endregion break; case ShapeType.Sphere: #region Sphere Point3D[] nearestSpherePoints, nearestLinePoints3; Math3D.GetClosestPoints_Sphere_Line(out nearestSpherePoints, out nearestLinePoints3, _point, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay); { retVal = nearestSpherePoints[0]; } #endregion break; case ShapeType.Mesh: throw new ApplicationException("finish this"); case ShapeType.None: retVal = null; break; default: throw new ApplicationException("Unknown ShapeType: " + _shape.ToString()); } return(retVal); }