Ensure a minimum height when going from perspective to ortho.

This commit is contained in:
fortsnek9348 2022-03-04 23:09:18 +00:00
parent 68a7e94edb
commit 6d2d6acc49
2 changed files with 37 additions and 5 deletions

View file

@ -43,9 +43,27 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
{
private const double PerspectiveMinZoomDist = 3;
private const double PerspectiveMaxZoomDist = 2300;
// Currently: 2.4852813742385704, 1905.3823869162372
private static readonly double OrthographicMinZoomWorldspaceHeight = PerspectiveMinZoomDist * Math.Tan(MathHelper.DegreesToRadians(WorldView.DefaultPerspectiveVFOVDegrees) / 2) * 2;
private static readonly double OrthographicMaxZoomWorldspaceHeight = PerspectiveMaxZoomDist * Math.Tan(MathHelper.DegreesToRadians(WorldView.DefaultPerspectiveVFOVDegrees) / 2) * 2;
// Currently 2.7614237491539679
private double OrthographicMinZoomWorldspaceHeight
{
get
{
// Get the Z plane height at the perspective limit.
// By coincidence, these are currently about the same, with byPerspectiveZoomLimit being slightly less at 2.4852813742385704.
double byPerspectiveZoomLimit = WorldView.CalcPerspectiveHeight(PerspectiveMinZoomDist, WorldView.DefaultPerspectiveVFOVDegrees);
double byWorldViewLimit = WorldView.OrthographicProjectionMinimumHeight * Vector3.UnitY.TransformVector(this.world.InverseModelviewMatrix).Length;
return Math.Max(byPerspectiveZoomLimit, byWorldViewLimit);
}
}
// Currently 1905.3823869162372
private double OrthographicMaxZoomWorldspaceHeight => WorldView.CalcPerspectiveHeight(PerspectiveMaxZoomDist, WorldView.DefaultPerspectiveVFOVDegrees);
// When switching the projection from perspective to orthographic, ensure this minimum height.
// Will tend to be used when fully zoomed into the hit plane, and then the ref position indicator will appear to drift during the animation.
// The resulting projection might be undesired, but at least it would be non-zero.
private double PerspectiveToOrthographicMinViewspaceHeight => WorldView.OrthographicProjectionMinimumHeight;
public NearFarAction GetNearFar;
private readonly MotionQueue motionQueue = new MotionQueue();
@ -685,6 +703,20 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
Vector3 viewspaceRefPosition = worldspaceRefPosition.TransformPosition(this.world.ModelviewMatrix);
// Don't let this become negative when the ref position is behind the camera.
double refPlaneHeightInViewspace = Math.Abs(this.world.GetViewspaceHeightAtPosition(viewspaceRefPosition));
double refViewspaceZ = viewspaceRefPosition.Z;
// Ensure a minimum when going from perspective (in case the camera is zoomed all the way into the hit plane).
if (toOrthographic)
{
double minViewspaceHeight = PerspectiveToOrthographicMinViewspaceHeight;
if (refPlaneHeightInViewspace < minViewspaceHeight)
{
// If this happens, the ref position indicator will appear to drift during the animation.
refPlaneHeightInViewspace = minViewspaceHeight;
refViewspaceZ = -WorldView.CalcPerspectiveDistance(minViewspaceHeight, this.world.VFovDegrees);
}
}
double refFOV = MathHelper.DegreesToRadians(
toOrthographic
@ -706,7 +738,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
double fov = toOrthographic ? refFOV * (1 - t) : refFOV * t;
double dist = refPlaneHeightInViewspace / 2 / Math.Tan(fov / 2);
double eyeZ = viewspaceRefPosition.Z + dist;
double eyeZ = refViewspaceZ + dist;
Vector3 viewspaceEyePosition = new Vector3(0, 0, eyeZ);

@ -1 +1 @@
Subproject commit 4c22416f074835246ab2b0f15f25356c02838b89
Subproject commit 992a40c44497b380e3cb2ece129ebed66f8838ba