using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Galaxy;
namespace XFEEDToolBox.Test;
[TestFixture]
public class GalaxyOriginalCameraSmoothingTests
{
static void Near(double expected, double actual, double tolerance = 1e-9) =>
Check.That(Math.Abs(expected - actual) <= tolerance, $"Expected {expected}, actual {actual}");
[Test]
public void OriginalNormalUpdateUsesFourIndependentChannelsAndGeometricZoom()
{
var actual = new GalaxyCameraPose(new(100, -2, 300), -.5, .25, 10);
var target = new GalaxyCameraPose(new(120, 3, 260), .5, -.75, 320);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(106.00000023841858, next.Focus.X);
Near(-.4999999403953552, next.Focus.Y);
Near(287.99999952316284, next.Focus.Z);
Near(-.29999999701976776, next.Yaw);
Near(.04999999701976776, next.Pitch);
Near(20.00000020657396, next.Distance, 1e-8);
Check.That(next.Distance < 30); // Arithmetic-distance interpolation would be 72.
}
[Test]
public void TargetFloorSettlesWhileActualHeightRemainsContinuous()
{
var actual = new GalaxyCameraPose(new(4, 2.75, 6), 0, 0, 20);
var target = GalaxyOriginalCameraControls.PrepareTarget(actual, false, 0);
Near(3, target.Focus.Y);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(2.8250000029802322, next.Focus.Y);
Check.That(next.Focus.Y != target.Focus.Y);
Check.That(GalaxyOriginalCameraControls.PrepareTarget(actual, true, 0).Focus == actual.Focus);
Check.That(GalaxyOriginalCameraControls.PrepareTarget(actual, false, -.01).Focus == actual.Focus);
}
[Test]
public void OriginalDegreeMetadataClampsPitchAndLightYearDistanceOnlyOnTarget()
{
var high = GalaxyOriginalCameraControls.PrepareTarget(new(new(1, 0, 2), 100, 2, 100000), false, 0);
var low = GalaxyOriginalCameraControls.PrepareTarget(new(new(1, 0, 2), -100, -2, .1), false, 0);
Near((double)(80f * .01745329238474369f), high.Pitch);
Near(-high.Pitch, low.Pitch);
Near(25000, high.Distance); Near(6, low.Distance);
Near(100, high.Yaw); Near(-100, low.Yaw);
Near((double)(45f * .01745329238474369f), GalaxyOriginalCameraControls.DefaultPitch);
}
[Test]
public void YawFollowsOriginalUnwrappedDeltaAndCallerToleranceIsExplicit()
{
var actual = new GalaxyCameraPose(new(0, 0, 0), 6, 0, 20);
var target = new GalaxyCameraPose(new(1, 0, 0), 0, 1, 21);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(4.799999982118607, next.Yaw);
Check.That(next.Focus != target.Focus && next.Distance != target.Distance);
Check.That(GalaxyOriginalCameraControls.Smooth(actual, target, new(1, 7, 2)) == target);
Check.That(GalaxyOriginalCameraControls.Smooth(target, target) == target);
}
[Test]
public void MultipleUpdatesApplyPerTickFactorsWithoutElapsedTimeScaling()
{
var actual = new GalaxyCameraPose(new(0, 0, 0), 0, 0, 10);
var target = new GalaxyCameraPose(new(100, 0, 0), 1, 1, 1000);
for (var index = 0; index < 5; index++) actual = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(100 * (1 - Math.Pow(1 - (double).3f, 5)), actual.Focus.X);
var angular = 1 - Math.Pow(1 - (double).2f, 5);
Near(angular, actual.Yaw); Near(angular, actual.Pitch);
Near(10 * Math.Pow(100, angular), actual.Distance, 1e-8);
}
[Test]
public void InvalidPoseAndInventedNegativeStopThresholdCannotEnterCameraState()
{
var valid = new GalaxyCameraPose(new(0, 0, 0), 0, 0, 10);
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(default, valid));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid with { Distance = 0 }));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid with { Pitch = double.NaN }));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid, new(-1, 0, 0)));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.PrepareTarget(valid, false, double.NaN));
}
}
using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Galaxy;
namespace XFEEDToolBox.Test;
[TestFixture]
public class GalaxyOriginalCameraSmoothingTests
{
static void Near(double expected, double actual, double tolerance = 1e-9) =>
Check.That(Math.Abs(expected - actual) <= tolerance, $"Expected {expected}, actual {actual}");
[Test]
public void OriginalNormalUpdateUsesFourIndependentChannelsAndGeometricZoom()
{
var actual = new GalaxyCameraPose(new(100, -2, 300), -.5, .25, 10);
var target = new GalaxyCameraPose(new(120, 3, 260), .5, -.75, 320);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(106.00000023841858, next.Focus.X);
Near(-.4999999403953552, next.Focus.Y);
Near(287.99999952316284, next.Focus.Z);
Near(-.29999999701976776, next.Yaw);
Near(.04999999701976776, next.Pitch);
Near(20.00000020657396, next.Distance, 1e-8);
Check.That(next.Distance < 30); // Arithmetic-distance interpolation would be 72.
}
[Test]
public void TargetFloorSettlesWhileActualHeightRemainsContinuous()
{
var actual = new GalaxyCameraPose(new(4, 2.75, 6), 0, 0, 20);
var target = GalaxyOriginalCameraControls.PrepareTarget(actual, false, 0);
Near(3, target.Focus.Y);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(2.8250000029802322, next.Focus.Y);
Check.That(next.Focus.Y != target.Focus.Y);
Check.That(GalaxyOriginalCameraControls.PrepareTarget(actual, true, 0).Focus == actual.Focus);
Check.That(GalaxyOriginalCameraControls.PrepareTarget(actual, false, -.01).Focus == actual.Focus);
}
[Test]
public void OriginalDegreeMetadataClampsPitchAndLightYearDistanceOnlyOnTarget()
{
var high = GalaxyOriginalCameraControls.PrepareTarget(new(new(1, 0, 2), 100, 2, 100000), false, 0);
var low = GalaxyOriginalCameraControls.PrepareTarget(new(new(1, 0, 2), -100, -2, .1), false, 0);
Near((double)(80f * .01745329238474369f), high.Pitch);
Near(-high.Pitch, low.Pitch);
Near(25000, high.Distance); Near(6, low.Distance);
Near(100, high.Yaw); Near(-100, low.Yaw);
Near((double)(45f * .01745329238474369f), GalaxyOriginalCameraControls.DefaultPitch);
}
[Test]
public void YawFollowsOriginalUnwrappedDeltaAndCallerToleranceIsExplicit()
{
var actual = new GalaxyCameraPose(new(0, 0, 0), 6, 0, 20);
var target = new GalaxyCameraPose(new(1, 0, 0), 0, 1, 21);
var next = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(4.799999982118607, next.Yaw);
Check.That(next.Focus != target.Focus && next.Distance != target.Distance);
Check.That(GalaxyOriginalCameraControls.Smooth(actual, target, new(1, 7, 2)) == target);
Check.That(GalaxyOriginalCameraControls.Smooth(target, target) == target);
}
[Test]
public void MultipleUpdatesApplyPerTickFactorsWithoutElapsedTimeScaling()
{
var actual = new GalaxyCameraPose(new(0, 0, 0), 0, 0, 10);
var target = new GalaxyCameraPose(new(100, 0, 0), 1, 1, 1000);
for (var index = 0; index < 5; index++) actual = GalaxyOriginalCameraControls.Smooth(actual, target);
Near(100 * (1 - Math.Pow(1 - (double).3f, 5)), actual.Focus.X);
var angular = 1 - Math.Pow(1 - (double).2f, 5);
Near(angular, actual.Yaw); Near(angular, actual.Pitch);
Near(10 * Math.Pow(100, angular), actual.Distance, 1e-8);
}
[Test]
public void InvalidPoseAndInventedNegativeStopThresholdCannotEnterCameraState()
{
var valid = new GalaxyCameraPose(new(0, 0, 0), 0, 0, 10);
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(default, valid));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid with { Distance = 0 }));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid with { Pitch = double.NaN }));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.Smooth(valid, valid, new(-1, 0, 0)));
Check.Throws<ArgumentException>(() => GalaxyOriginalCameraControls.PrepareTarget(valid, false, double.NaN));
}
}