private void Trackball_GetOrbitRadius(object sender, GetOrbitRadiusArgs e) { //TODO: This isn't perfect. The camera isn't rotating around the ship, but where they clicked. It's subtle, but while the user is orbiting the camera, //the ship will drift relative to the camera if (_selectedBean != null) { e.Result = _selectedBean.CameraOffset.Length; } }
protected virtual double OnGetOrbitRadius() { //TODO: Don't just get the radius, get a live point to follow // Raise an event, requesting the radius if (this.GetOrbitRadius != null) { GetOrbitRadiusArgs args = new GetOrbitRadiusArgs(_camera.Position, _camera.LookDirection); this.GetOrbitRadius(this, args); if (args.Result != null) { // They set the value, return it return args.Result.Value; } } // If execution gets here, then the event never returned anything. Figure out the radius myself if (!_shouldHitTestOnOrbit) { // This works great when looking at the origin, but is really weird when offset from the orign return _camera.Position.ToVector().Length; } #region Ray Cast // If there are no hits when fired from the dead center, fire off some more rays a random offset from the center //TODO: See if there is a more efficient way of getting all 3D objects on screen double width = _eventSource.ActualWidth; double height = _eventSource.ActualHeight; double halfWidth = width * .5d; double halfHeight = height * .5d; for (int cntr = 0; cntr < 50; cntr++) { Vector3D rayVector = new Vector3D(0, 0, 0); if (cntr > 0) // the first attempt will be the center of the viewport { rayVector = Math3D.GetRandomVector_Circular(.25d); } double? distance = OrbitGetObjectDistance(_eventSource, new Point(halfWidth + (rayVector.X * width), halfHeight + (rayVector.Y * height))); if (distance != null && (distance.Value * distance.Value) < _camera.Position.ToVector().LengthSquared) // if it's greater than the distance to the origin, then I want to ignore it { return distance.Value; } } #endregion return _camera.Position.ToVector().Length; #region Wrong Idea //Vector3D position = _camera.Position.ToVector(); //if (Vector3D.DotProduct(_camera.LookDirection, position) >= 0) //{ // // They are looking away from the origin, so just use the distance to the origin // return position.Length; //} //else //{ // // Get a ray from the origin that intersects the look ray at 90 degrees // // This first orthogonal is a reference // Vector3D orth1 = Vector3D.CrossProduct(_camera.LookDirection, position); // // This second orthogonal is orthogonal to the look direction, but in the plane of the pos/look dir // Vector3D orth2 = Vector3D.CrossProduct(orth1, _camera.LookDirection); // // Now I need to intersect look direction with the line coming from the origin in the direction of the second orthogonal // Point3D? intersectPoint = Math3D.GetIntersectionOfTwoLines(new Point3D(0, 0, 0), orth2, _camera.Position, _camera.LookDirection); // if (intersectPoint == null) // { // // This should never happen? Only if math drift is too much? // return position.Length; // } // else // { // double retVal = (_camera.Position - intersectPoint.Value).Length; // double distToOrigin = position.Length; // return Math.Min(retVal, distToOrigin); // I can't just blindly return the calculated distance, because they could be looking nearly parallel to the line to the origin. In that case the distance returned would be huge // } //} #endregion }
private void Trackball_GetOrbitRadius(object sender, GetOrbitRadiusArgs e) { //TODO: e should also pass in the mouse click point, so there is camera position, and click position, this // listener can decide which they want (I can't reuse the same direction, because of the perspective) RayCastResult result = _world.CastRay(e.Position, e.Direction, 30d, World.BodyFilterType.ExcludeBodies); if (result != null) { e.Result = result.HitDistance; } }