using XFEExtension.NetCore.XUnit.Attributes; using XFEEDToolBox.Core.Galaxy; using XFEEDToolBox.Core.Models; namespace XFEEDToolBox.Test; [TestFixture] public class GalaxyOriginalProjectionTests { static void Near(double expected, double actual) => Check.That(Math.Abs(expected - actual) < 1e-10, $"Expected {expected}, actual {actual}"); [Test] public void FlatViewPreservesWideScreenVerticalAngleAndNarrowViewPreservesHorizontalAngle() { var aspect = GalaxyOriginalProjection.ReferenceAspectRatio; var original = GalaxyOriginalProjection.StackFieldOfViewRadians; Near(original, GalaxyOriginalProjection.VerticalFieldOfView(aspect)); Near(original, GalaxyOriginalProjection.VerticalFieldOfView(21d / 9)); var narrow = GalaxyOriginalProjection.VerticalFieldOfView(4d / 3); Check.That(narrow > original); Near(Math.Tan(original / 2) * aspect, Math.Tan(narrow / 2) * 4d / 3); Near(original, GalaxyOriginalProjection.VerticalFieldOfView(4d / 3, compensateNarrowViewport: false)); } [Test] public void FocalLengthProjectsVerticalEdgeAndScalesWithActualViewportPixels() { var vertical = GalaxyOriginalProjection.VerticalFieldOfView(1920d / 1080); var focal = GalaxyOriginalProjection.FocalLength(1920, 1080); var depth = 17.75; var topWorldOffset = Math.Tan(vertical / 2) * depth; Near(540, topWorldOffset * focal / depth); Near(focal * 2, GalaxyOriginalProjection.FocalLength(3840, 2160)); var narrowFocal = GalaxyOriginalProjection.FocalLength(1440, 1080); Near(focal * .75, narrowFocal); } [Test] public void InfiniteReverseDepthDoesNotConfuseStoredFarMetadataWithProjectionOrQueryCoverage() { Near(1, GalaxyOriginalProjection.ReverseDepth(GalaxyOriginalProjection.NearPlane)); Near(.01, GalaxyOriginalProjection.ReverseDepth(GalaxyOriginalProjection.NearPlane * 100)); var beyondStoredFar = GalaxyOriginalProjection.StoredFarPlane * 2; Check.That(GalaxyOriginalProjection.ReverseDepth(beyondStoredFar) > 0); Near(GalaxyOriginalProjection.NearPlane / beyondStoredFar, GalaxyOriginalProjection.ReverseDepth(beyondStoredFar)); } [Test] public void InvalidLensAndBehindCameraInputsAreRejected() { foreach (var bad in new[] { double.NaN, double.PositiveInfinity, 0d, -1d }) { var rejected = 0; try { GalaxyOriginalProjection.VerticalFieldOfView(bad); } catch (ArgumentOutOfRangeException) { rejected++; } try { GalaxyOriginalProjection.FocalLength(bad, 1080); } catch (ArgumentOutOfRangeException) { rejected++; } try { GalaxyOriginalProjection.ReverseDepth(bad); } catch (ArgumentOutOfRangeException) { rejected++; } Check.That(rejected == 3); } } [Test] public void ProductionCameraUsesRecoveredLensAndNearPlaneAtEveryViewportAspect() { foreach (var width in new[] { 1440d, 1920d, 2560d }) { var focal = GalaxyOriginalProjection.FocalLength(width, 1080); var camera = GalaxyCamera.Create(new(0, 0, 0), width, 1080, 0, 0, focal / 17.75); Near(GalaxyOriginalProjection.VerticalFieldOfView(width / 1080), camera.VerticalFieldOfView); Near(focal, camera.FocalLength); Near(17.75, camera.Distance); Near(GalaxyOriginalProjection.NearPlane, camera.Near); var beforeNear = new Coordinates(camera.Eye.X, camera.Eye.Y, camera.Eye.Z + camera.Near * .5); var afterNear = new Coordinates(camera.Eye.X, camera.Eye.Y, camera.Eye.Z + camera.Near * 1.01); Check.That(!camera.Project(beforeNear).IsVisible && !camera.ToViewport().Contains(beforeNear)); Check.That(camera.Project(afterNear).IsVisible && camera.ToViewport().Contains(afterNear)); } } [Test] public void OriginalLensDoesNotExpandNearViewCatalogueQueriesToStoredFarOrWholeGalaxy() { var focal = GalaxyOriginalProjection.FocalLength(1920, 1080); var camera = GalaxyCamera.Create(new(0, 0, 0), 1920, 1080, 0, 0, focal / 6); var viewport = camera.ToViewport(); var bounds = GalaxyQueryBounds.FromViewport(viewport); Near(24, camera.QueryFar); Near(camera.QueryFar, bounds.Maximum.Z - camera.Eye.Z); Check.That(double.IsPositiveInfinity(camera.ProjectionFar)); Check.That(viewport.Radius < 100 && bounds.Radius < 100); Check.That(!bounds.Contains(new(0, 0, 26000)) && !viewport.Contains(new(0, 0, 26000))); var plan = new GalaxyQueryPlan(viewport); var count = 0; while (plan.TryTake(out var tile)) { Check.That(tile.Radius < 100); Check.That(++count < 128, "A6ly camera view must remain a bounded local query after lens integration."); } Check.That(count > 0 && plan.OmittedTiles == 0); } [Test] public void InfiniteVisualProjectionCannotPublishOrSelectAStarOutsideTheFiniteCatalogueView() { var focal=GalaxyOriginalProjection.FocalLength(1920,1080); var camera=GalaxyCamera.Create(new(0,0,0),1920,1080,0,0,focal/6); var distant=new Coordinates(0,0,camera.Eye.Z+GalaxyOriginalProjection.StoredFarPlane*2); var projected=camera.Project(distant); Check.That(projected.IsVisible&&projected.Depth>GalaxyOriginalProjection.StoredFarPlane); Near(960,projected.X);Near(540,projected.Y); Check.That(!camera.ProjectForCatalogue(distant).IsVisible); Check.That(!camera.Contains(distant)&&!camera.ToViewport().Contains(distant)); Check.That(!GalaxyQueryBounds.FromViewport(camera.ToViewport()).Contains(distant)); Check.That(camera.TryProjectSegment(distant,new(10,0,distant.Z+100),out var a,out var b)); Check.That(double.IsFinite(a.X+a.Y+b.X+b.Y)); } }