diff --git a/Principia.sln.DotSettings b/Principia.sln.DotSettings index 8e3ebf1027..d0847f8a02 100644 --- a/Principia.sln.DotSettings +++ b/Principia.sln.DotSettings @@ -221,6 +221,7 @@ True True True + True True True True diff --git a/benchmarks/planetarium_benchmark.cpp b/benchmarks/planetarium_benchmark.cpp index 3300b98d29..a052220081 100644 --- a/benchmarks/planetarium_benchmark.cpp +++ b/benchmarks/planetarium_benchmark.cpp @@ -331,6 +331,7 @@ void BM_PlanetariumPlotMethod3( satellites.goes_8_trajectory().end(), now, /*t_max=*/InfiniteFuture, + /*tan_angular_resolution=*/0.00080, /*reverse=*/false, /*add_point=*/ [&line](ScaledSpacePoint const& point) { line.push_back(point); }, diff --git a/ksp_plugin/interface_planetarium.cpp b/ksp_plugin/interface_planetarium.cpp index b09912c08c..ae5e876281 100644 --- a/ksp_plugin/interface_planetarium.cpp +++ b/ksp_plugin/interface_planetarium.cpp @@ -50,6 +50,7 @@ Planetarium* __cdecl principia__PlanetariumCreate( double const focal, double const field_of_view, double const inverse_scale_factor, + double const tan_angular_resolution, XYZ const scaled_space_origin) { journal::Method m({plugin, sun_world_position, @@ -60,6 +61,7 @@ Planetarium* __cdecl principia__PlanetariumCreate( focal, field_of_view, inverse_scale_factor, + tan_angular_resolution, scaled_space_origin}); Renderer const& renderer = CHECK_NOTNULL(plugin)->renderer(); @@ -88,9 +90,13 @@ Planetarium* __cdecl principia__PlanetariumCreate( FromXYZ>(sun_world_position), plugin->PlanetariumRotation()); + // Angular resolution: My display has a height of 401 mm and 1600 pixels + // vertically. My eye is at least 550 mm from the centre. Hence the + // wolframalpha.com query: "ArcTan[(401/1600)/550] in arcmin" which yields + // 1.567'. Planetarium::Parameters parameters( /*sphere_radius_multiplier=*/1.0, - /*angular_resolution=*/0.4 * ArcMinute, + /*angular_resolution=*/1.567 * ArcMinute, field_of_view * Radian); Perspective perspective( world_to_plotting_affine_map * @@ -130,11 +136,19 @@ void __cdecl principia__PlanetariumPlotFlightPlanSegment( char const* const vessel_guid, int const index, double const* const t_max, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, int* const vertex_count) { journal::Method m( - {planetarium, plugin, vessel_guid, index, t_max, vertices, vertices_size}, + {planetarium, + plugin, + vessel_guid, + index, + t_max, + tan_angular_resolution, + vertices, + vertices_size}, {vertex_count}); CHECK_NOTNULL(plugin); CHECK_NOTNULL(planetarium); @@ -156,6 +170,7 @@ void __cdecl principia__PlanetariumPlotFlightPlanSegment( segment->end(), plugin->CurrentTime(), t_max == nullptr ? InfiniteFuture : FromGameTime(*plugin, *t_max), + tan_angular_resolution, /*reverse=*/false, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; @@ -172,11 +187,18 @@ void __cdecl principia__PlanetariumPlotPrediction( Plugin const* const plugin, char const* const vessel_guid, double const* const t_max, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, int* const vertex_count) { journal::Method m( - {planetarium, plugin, vessel_guid, t_max, vertices, vertices_size}, + {planetarium, + plugin, + vessel_guid, + t_max, + tan_angular_resolution, + vertices, + vertices_size}, {vertex_count}); CHECK_NOTNULL(plugin); CHECK_NOTNULL(planetarium); @@ -189,6 +211,7 @@ void __cdecl principia__PlanetariumPlotPrediction( prediction->end(), plugin->CurrentTime(), t_max == nullptr ? InfiniteFuture : FromGameTime(*plugin, *t_max), + tan_angular_resolution, /*reverse=*/false, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; @@ -207,6 +230,7 @@ void __cdecl principia__PlanetariumPlotPsychohistory( char const* const vessel_guid, double const max_history_length, double const* const t_max, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, int* const vertex_count) { @@ -216,6 +240,7 @@ void __cdecl principia__PlanetariumPlotPsychohistory( vessel_guid, max_history_length, t_max, + tan_angular_resolution, vertices, vertices_size}, {vertex_count}); @@ -246,6 +271,7 @@ void __cdecl principia__PlanetariumPlotPsychohistory( psychohistory->end(), /*now=*/plugin->CurrentTime(), t_max == nullptr ? InfiniteFuture : FromGameTime(*plugin, *t_max), + tan_angular_resolution, /*reverse=*/true, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; @@ -264,6 +290,7 @@ void __cdecl principia__PlanetariumPlotCelestialPastTrajectory( Plugin const* const plugin, int const celestial_index, double const max_history_length, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, double* const minimal_distance_from_camera, @@ -273,6 +300,7 @@ void __cdecl principia__PlanetariumPlotCelestialPastTrajectory( plugin, celestial_index, max_history_length, + tan_angular_resolution, vertices, vertices_size}, {minimal_distance_from_camera, vertex_count}); @@ -303,6 +331,7 @@ void __cdecl principia__PlanetariumPlotCelestialPastTrajectory( first_time, /*last_time=*/plugin->CurrentTime(), /*now=*/plugin->CurrentTime(), + tan_angular_resolution, /*reverse=*/true, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; @@ -323,6 +352,7 @@ void __cdecl principia__PlanetariumPlotCelestialFutureTrajectory( Plugin const* const plugin, int const celestial_index, char const* const vessel_guid, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, double* const minimal_distance_from_camera, @@ -332,6 +362,7 @@ void __cdecl principia__PlanetariumPlotCelestialFutureTrajectory( plugin, celestial_index, vessel_guid, + tan_angular_resolution, vertices, vertices_size}, {minimal_distance_from_camera, vertex_count}); @@ -362,6 +393,7 @@ void __cdecl principia__PlanetariumPlotCelestialFutureTrajectory( /*first_time=*/plugin->CurrentTime(), /*last_time=*/final_time, /*now=*/plugin->CurrentTime(), + tan_angular_resolution, /*reverse=*/false, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; @@ -379,11 +411,17 @@ void __cdecl principia__PlanetariumPlotEquipotential( Planetarium const* const planetarium, Plugin const* const plugin, int const index, + double const tan_angular_resolution, ScaledSpacePoint* const vertices, int const vertices_size, int* const vertex_count) { journal::Method m( - {planetarium, plugin, index, vertices, vertices_size}, + {planetarium, + plugin, + index, + tan_angular_resolution, + vertices, + vertices_size}, {vertex_count}); CHECK_NOTNULL(plugin); CHECK_NOTNULL(planetarium); @@ -401,6 +439,7 @@ void __cdecl principia__PlanetariumPlotEquipotential( equipotential.front().time, equipotential.back().time, plugin->CurrentTime(), + tan_angular_resolution, /*reverse=*/false, [vertices, vertex_count](ScaledSpacePoint const& vertex) { vertices[(*vertex_count)++] = vertex; diff --git a/ksp_plugin/planetarium.cpp b/ksp_plugin/planetarium.cpp index 2d57ff0633..bd14f36be9 100644 --- a/ksp_plugin/planetarium.cpp +++ b/ksp_plugin/planetarium.cpp @@ -271,6 +271,7 @@ void Planetarium::PlotMethod3( DiscreteTrajectory::iterator end, Instant const& now, Instant const& t_max, + double const tan_angular_resolution, bool const reverse, std::function const& add_point, int max_points) const { @@ -281,8 +282,14 @@ void Planetarium::PlotMethod3( auto const begin_time = std::max(begin->time, plotting_frame_->t_min()); auto const last_time = std::min({last->time, plotting_frame_->t_max(), t_max}); - PlotMethod3( - trajectory, begin_time, last_time, now, reverse, add_point, max_points); + PlotMethod3(trajectory, + begin_time, + last_time, + now, + tan_angular_resolution, + reverse, + add_point, + max_points); } std::vector> Planetarium::ComputePlottableSpheres( diff --git a/ksp_plugin/planetarium.hpp b/ksp_plugin/planetarium.hpp index 334786406d..c52d342c27 100644 --- a/ksp_plugin/planetarium.hpp +++ b/ksp_plugin/planetarium.hpp @@ -60,9 +60,10 @@ class Planetarium { class Parameters final { public: // `sphere_radius_multiplier` defines the "dark area" around a celestial - // where we don't draw trajectories. `angular_resolution` defines the limit - // beyond which spheres don't participate in hiding. `field_of_view` - // is the half-angle of a cone outside of which not plotting takes place. + // where we don't draw trajectories. For methods 0 to 2, + // `angular_resolution` defines the limit beyond which spheres don't + // participate in hiding. `field_of_view` is the half-angle of a cone + // outside of which not plotting takes place. explicit Parameters(double sphere_radius_multiplier, Angle const& angular_resolution, Angle const& field_of_view); @@ -124,13 +125,16 @@ class Planetarium { Length* minimal_distance = nullptr) const; // A method similar to PlotMethod2, but which produces a three-dimensional - // trajectory in scaled space instead of projecting and hiding. + // trajectory in scaled space instead of projecting and hiding. Note that the + // angular resolution passed at construction is ignored and the parameter + // `tan_angular_resolution` is used instead. void PlotMethod3( Trajectory const& trajectory, DiscreteTrajectory::iterator begin, DiscreteTrajectory::iterator end, Instant const& now, Instant const& t_max, + double tan_angular_resolution, bool reverse, std::function const& add_point, int max_points) const; @@ -143,6 +147,7 @@ class Planetarium { Instant const& first_time, Instant const& last_time, Instant const& now, + double tan_angular_resolution, bool reverse, std::function const& add_point, int max_points, diff --git a/ksp_plugin/planetarium_body.hpp b/ksp_plugin/planetarium_body.hpp index 66cd491916..0027e63e42 100644 --- a/ksp_plugin/planetarium_body.hpp +++ b/ksp_plugin/planetarium_body.hpp @@ -54,12 +54,12 @@ void Planetarium::PlotMethod3( Instant const& first_time, Instant const& last_time, Instant const& now, + double const tan_angular_resolution, bool const reverse, std::function const& add_point, int const max_points, Length* const minimal_distance) const { - double const tan²_angular_resolution = - Pow<2>(parameters_.tan_angular_resolution_); + double const tan²_angular_resolution = Pow<2>(tan_angular_resolution); auto const final_time = reverse ? first_time : last_time; auto previous_time = reverse ? last_time : first_time; diff --git a/ksp_plugin_adapter/gl_lines.cs b/ksp_plugin_adapter/gl_lines.cs index 3621c1a44f..684894f7b9 100644 --- a/ksp_plugin_adapter/gl_lines.cs +++ b/ksp_plugin_adapter/gl_lines.cs @@ -75,6 +75,7 @@ public static DisposablePlanetarium NewPlanetarium(IntPtr plugin, focal:1, field_of_view, ScaledSpace.InverseScaleFactor, + Plotter.TanAngularResolution(), scaled_space_origin: (XYZ)ScaledSpace.ScaledToLocalSpace( Vector3d.zero)); } diff --git a/ksp_plugin_adapter/main_window.cs b/ksp_plugin_adapter/main_window.cs index 742f3960bf..1c5d87ea7f 100644 --- a/ksp_plugin_adapter/main_window.cs +++ b/ksp_plugin_adapter/main_window.cs @@ -25,6 +25,8 @@ public MainWindow(PrincipiaPluginAdapter adapter, flight_planner_ = flight_planner; orbit_analyser_ = orbit_analyser; plotting_frame_selector_ = plotting_frame_selector; + cheeze_c.value = 0.65; + cheeze_x.value = -0.31; Show(); } @@ -167,8 +169,28 @@ public override void Save(ConfigNode node) { protected override string Title => "Principia"; - protected override void RenderWindowContents(int window_id) { + public static DifferentialSlider cheeze_c = new DifferentialSlider("c", "", -5, -1, + (x) => x.ToString("0.000"), zero_value: 0.65, min_value: 0.1, max_value: 4); + public static DifferentialSlider cheeze_x = new DifferentialSlider("x", "", -5, -1, + (x) => x.ToString("0.000"), zero_value: -0.31, min_value: -2, max_value: 0); + + protected override void RenderWindowContents(int window_id) { using (new UnityEngine.GUILayout.VerticalScope()) { + UnityEngine.GUILayout.Label("Cheeze constants: "); + cheeze_c.Render(true); + cheeze_x.Render(true); + + UnityEngine.Camera camera = PlanetariumCamera.Camera; + float vertical_fov = camera.fieldOfView; + float horizontal_fov = + UnityEngine.Camera.VerticalToHorizontalFieldOfView( + vertical_fov, + camera.aspect); + UnityEngine.GUILayout.Label("vfov=" + vertical_fov); + UnityEngine.GUILayout.Label("hfov=" + horizontal_fov); + UnityEngine.GUILayout.Label("pixh=" + camera.pixelHeight); + UnityEngine.GUILayout.Label("pixw=" + camera.pixelWidth); + if (!adapter_.PluginRunning()) { UnityEngine.GUILayout.Label( text : L10N.CacheFormat("#Principia_MainWindow_PluginNotStarted"), diff --git a/ksp_plugin_adapter/plotter.cs b/ksp_plugin_adapter/plotter.cs index f5659c60ab..1597204281 100644 --- a/ksp_plugin_adapter/plotter.cs +++ b/ksp_plugin_adapter/plotter.cs @@ -10,6 +10,37 @@ public Plotter(PrincipiaPluginAdapter adapter) { adapter_ = adapter; } + public static double lightness(UnityEngine.Color colour) { + var linear_colour = colour.linear; + var rgb_linear = new UnityEngine.Vector3(linear_colour.r, linear_colour.g, linear_colour.b); + double y = UnityEngine.Vector3.Dot(new UnityEngine.Vector3(0.2126f,0.7152f,0.0722f), rgb_linear); + double δ = 6.0 / 29; + double f = y > δ * δ * δ ? Math.Pow(y, 1.0 / 3) + : y * (1 / (3 * δ * δ)) + (4.0 / 29); + return (116 * f - 16) / 100; + } + + public static double TanAngularResolution() { + const double degree = Math.PI / 180; + UnityEngine.Camera camera = PlanetariumCamera.Camera; + float vertical_fov = camera.fieldOfView; + float horizontal_fov = + UnityEngine.Camera.VerticalToHorizontalFieldOfView( + vertical_fov, + camera.aspect); + // The angle subtended by the pixel closest to the centre of the viewport. + return Math.Min( + Math.Tan(vertical_fov * degree / 2) / (camera.pixelHeight / 2), + Math.Tan(horizontal_fov * degree / 2) / + (camera.pixelWidth / 2)); + } + + public static double angular_resolution_for_colour(UnityEngine.Color colour) { + return MainWindow.cheeze_c.value * + Math.Pow(lightness(colour), MainWindow.cheeze_x.value) * + TanAngularResolution(); + } + public void PlotEquipotentials(DisposablePlanetarium planetarium) { int number_of_equipotentials = Plugin.EquipotentialCount(); if (number_of_equipotentials == 0) { @@ -26,6 +57,7 @@ public void PlotEquipotentials(DisposablePlanetarium planetarium) { planetarium.PlanetariumPlotEquipotential( Plugin, i, + angular_resolution_for_colour(colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); @@ -56,6 +88,7 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, main_vessel_guid, history_length, prediction_t_max, + angular_resolution_for_colour(adapter_.history_colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); @@ -68,6 +101,7 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, planetarium.PlanetariumPlotPrediction(Plugin, main_vessel_guid, prediction_t_max, + angular_resolution_for_colour(adapter_.prediction_colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); @@ -88,20 +122,22 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, } for (int i = 0; i < number_of_segments; ++i) { bool is_burn = i % 2 == 1; + var colour = is_burn + ? adapter_.burn_colour + : adapter_.flight_plan_colour; planetarium.PlanetariumPlotFlightPlanSegment( Plugin, main_vessel_guid, i, flight_plan_t_max, + angular_resolution_for_colour(colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); // No need for dynamic initialization, that was done above. DrawLineMesh(flight_plan_segment_meshes_[i], vertex_count, - is_burn - ? adapter_.burn_colour - : adapter_.flight_plan_colour, + colour, is_burn ? adapter_.burn_style : adapter_.flight_plan_style); @@ -122,6 +158,7 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, target_id, history_length, t_max: null, + angular_resolution_for_colour(adapter_.target_history_colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); @@ -135,6 +172,7 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, Plugin, target_id, t_max: null, + angular_resolution_for_colour(adapter_.target_prediction_colour), VertexBuffer.data, VertexBuffer.size, out int vertex_count); @@ -149,18 +187,8 @@ private void PlotVesselTrajectories(DisposablePlanetarium planetarium, private void PlotCelestialTrajectories(DisposablePlanetarium planetarium, string main_vessel_guid, double history_length) { - const double degree = Math.PI / 180; - UnityEngine.Camera camera = PlanetariumCamera.Camera; - float vertical_fov = camera.fieldOfView; - float horizontal_fov = - UnityEngine.Camera.VerticalToHorizontalFieldOfView( - vertical_fov, camera.aspect); - // The angle subtended by the pixel closest to the centre of the viewport. - double tan_angular_resolution = Math.Min( - Math.Tan(vertical_fov * degree / 2) / (camera.pixelHeight / 2), - Math.Tan(horizontal_fov * degree / 2) / (camera.pixelWidth / 2)); PlotSubtreeTrajectories(planetarium, main_vessel_guid, history_length, - Planetarium.fetch.Sun, tan_angular_resolution); + Planetarium.fetch.Sun, TanAngularResolution()); } // Plots the trajectories of `root` and its natural satellites. @@ -188,6 +216,7 @@ private void PlotSubtreeTrajectories(DisposablePlanetarium planetarium, Plugin, root.flightGlobalsIndex, history_length, + angular_resolution_for_colour(colour), VertexBuffer.data, VertexBuffer.size, out double min_past_distance, @@ -205,6 +234,7 @@ private void PlotSubtreeTrajectories(DisposablePlanetarium planetarium, Plugin, root.flightGlobalsIndex, main_vessel_guid, + angular_resolution_for_colour(colour), VertexBuffer.data, VertexBuffer.size, out double min_future_distance, diff --git a/ksp_plugin_adapter/reference_frame_selector.cs b/ksp_plugin_adapter/reference_frame_selector.cs index e52b9090a7..08d3469a47 100644 --- a/ksp_plugin_adapter/reference_frame_selector.cs +++ b/ksp_plugin_adapter/reference_frame_selector.cs @@ -611,7 +611,7 @@ private void RenderSubtree(CelestialBody celestial, int depth) { expanded_[celestial] = !expanded_[celestial]; } } - UnityEngine.GUILayout.Label(celestial.StandaloneName()); + UnityEngine.GUILayout.Label(celestial.StandaloneName() + " L=" + Plotter.lightness(celestial.orbitDriver?.Renderer?.orbitColor ?? XKCDColors.SunshineYellow)); UnityEngine.GUILayout.FlexibleSpace(); if (celestial.is_root()) { UnityEngine.GUILayout.Label( diff --git a/ksp_plugin_test/interface_planetarium_test.cpp b/ksp_plugin_test/interface_planetarium_test.cpp index 63fe392d86..4d3b595dbb 100644 --- a/ksp_plugin_test/interface_planetarium_test.cpp +++ b/ksp_plugin_test/interface_planetarium_test.cpp @@ -78,6 +78,7 @@ TEST_F(InterfacePlanetariumTest, ConstructionDestruction) { 10, 90, 1.0 / 6000, + 0.00080, {4, 5, 6}); principia__PlanetariumDelete(&planetarium); EXPECT_THAT(planetarium, IsNull()); diff --git a/serialization/journal.proto b/serialization/journal.proto index 23527cb612..8ecbe2f62b 100644 --- a/serialization/journal.proto +++ b/serialization/journal.proto @@ -2115,6 +2115,7 @@ message PlanetariumCreate { required double focal = 7; required double field_of_view = 8; required double inverse_scale_factor = 9; + required double tan_angular_resolution = 11; // Added in خوارزمی. required XYZ scaled_space_origin = 10; } message Return { @@ -2152,6 +2153,7 @@ message PlanetariumPlotCelestialFutureTrajectory { required fixed64 plugin = 2 [(pointer_to) = "Plugin const"]; required int32 celestial_index = 3; required string vessel_guid = 4; + required double tan_angular_resolution = 7; // Added in خوارزمی. required fixed64 vertices = 5 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 6 [(size_of) = "vertices"]; @@ -2175,6 +2177,7 @@ message PlanetariumPlotCelestialPastTrajectory { required fixed64 plugin = 2 [(pointer_to) = "Plugin const"]; required int32 celestial_index = 3; required double max_history_length = 4; + required double tan_angular_resolution = 7; // Added in خوارزمی. required fixed64 vertices = 5 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 6 [(size_of) = "vertices"]; @@ -2197,6 +2200,7 @@ message PlanetariumPlotEquipotential { (is_subject) = true]; required fixed64 plugin = 2 [(pointer_to) = "Plugin const"]; required int32 index = 3; + required double tan_angular_resolution = 6; // Added in خوارزمی. required fixed64 vertices = 4 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 5 [(size_of) = "vertices"]; @@ -2220,6 +2224,7 @@ message PlanetariumPlotFlightPlanSegment { required string vessel_guid = 4; required int32 index = 5; optional double t_max = 8; // Added in von Koch. + required double tan_angular_resolution = 9; // Added in خوارزمی. required fixed64 vertices = 6 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 7 [(size_of) = "vertices"]; @@ -2242,6 +2247,7 @@ message PlanetariumPlotPrediction { required fixed64 plugin = 2 [(pointer_to) = "Plugin const"]; required string vessel_guid = 4; optional double t_max = 7; // Added in von Koch. + required double tan_angular_resolution = 8; // Added in خوارزمی. required fixed64 vertices = 5 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 6 [(size_of) = "vertices"]; @@ -2265,6 +2271,7 @@ message PlanetariumPlotPsychohistory { required string vessel_guid = 4; required double max_history_length = 5; optional double t_max = 8; // Added in von Koch. + required double tan_angular_resolution = 9; // Added in خوارزمی. required fixed64 vertices = 6 [(pointer_to) = "ScaledSpacePoint", (is_csharp_owned) = true]; required int32 vertices_size = 7 [(size_of) = "vertices"];