StarSim

StarSim.git
git clone git://git.lenczewski.org/StarSim.git
Log | Files | Refs | README | LICENSE

commit e5f9bdf8cecc39a39e252dc3eb0c6f3958f54be2
parent 6677c4e4e86fadc41ed4d09c28a80f1d2b1bc7e8
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date:   Mon, 21 Oct 2019 10:01:55 +0100

Added chromaticity (read: Rainbows)

Diffstat:
MStarSim/StarSim/Program.cs | 7++-----
MStarSim/StarSimGui/ViewModels/SimulationViewModel.cs | 6++++--
MStarSim/StarSimLib/Graphics/SimulationDrawer.cs | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
MStarSim/StarSimLib/Physics/BodyGenerator.cs | 49+++++++++++++++++++++++++++++++++++++++++++++++++
MStarSim/StarSimLib/StarSimLib.xml | 35+++++++++++++++++++++++++++++++++++
5 files changed, 176 insertions(+), 8 deletions(-)

diff --git a/StarSim/StarSim/Program.cs b/StarSim/StarSim/Program.cs @@ -11,6 +11,7 @@ using StarSimLib.UI; using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; namespace StarSim { @@ -48,13 +49,9 @@ namespace StarSim ReadConfigFile(); bodies = BodyGenerator.GenerateBodies(configuration.BodyCount, true); - bodyShapeMap = BodyGenerator.GenerateShapes(bodies); + bodyShapeMap = BodyGenerator.GenerateShapes(bodies, BodyGenerator.DefaultRadiusDelegate, BodyGenerator.RainbowColourDelegate); -#if DEBUG - UpdateDelegate bodyPositionUpdater = BodyUpdater.UpdateBodiesBruteForce; -#else UpdateDelegate bodyPositionUpdater = BodyUpdater.UpdateBodiesBarnesHut; -#endif ContextSettings customContextSettings = new ContextSettings { AntialiasingLevel = 8, DepthBits = 24, StencilBits = 8 }; diff --git a/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs b/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs @@ -44,7 +44,7 @@ namespace StarSimGui.ViewModels /// <summary> /// The delegate method to use to derive the colour of a body's shape from the body's mass. /// </summary> - private readonly MassToColourDelegate bodyMassToColourDelegate = BodyGenerator.DefaultColourDelegate; + private readonly MassToColourDelegate bodyMassToColourDelegate = BodyGenerator.RainbowColourDelegate; /// <summary> /// The delegate method to use to derive the radius of a body's shape from the body's mass. @@ -507,8 +507,10 @@ namespace StarSimGui.ViewModels SimulatedBodies.Load(BodyGenerator.GenerateBodies(SimulatedBodyCount, SimulateCentralAttractor)); + /* simulatedBodyShapes = - BodyGenerator.GenerateShapes(SimulatedBodies, bodyMassToRadiusDelegate, bodyMassToColourDelegate); + BodyGenerator.GenerateShapes(SimulatedBodies, bodyMassToRadiusDelegate, bodyMassToColourDelegate)); + */ } /// <summary> diff --git a/StarSim/StarSimLib/Graphics/SimulationDrawer.cs b/StarSim/StarSimLib/Graphics/SimulationDrawer.cs @@ -5,6 +5,7 @@ using StarSimLib.Data_Structures; using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace StarSimLib.Graphics { @@ -261,12 +262,64 @@ namespace StarSimLib.Graphics } /// <summary> + /// Creates a new ARGB colour from a HSV colour. + /// </summary> + /// <param name="hue">The hue value for the new colour, between 0-360.</param> + /// <param name="saturation">The saturation value for the new colour, between 0-1.</param> + /// <param name="value">The value for the new colour, between 0-1.</param> + /// <returns>The created ARGB colour.</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Color ColorFromHSV(double hue, double saturation, double value) + { + double c = value * saturation; + double k = hue / 60; + double x = c * (1 - Math.Abs(k % 2 - 1)); + double m = value - c; + + double baseRed = 0, baseGreen = 0, baseBlue = 0; + + if (0 <= k && k <= 1) + { + baseRed = c; + baseGreen = x; + } + else if (1 < k && k <= 2) + { + baseRed = x; + baseGreen = c; + } + else if (2 < k && k <= 3) + { + baseGreen = c; + baseBlue = x; + } + else if (3 < k && k <= 4) + { + baseGreen = x; + baseBlue = c; + } + else if (4 < k && k <= 5) + { + baseRed = x; + baseBlue = c; + } + else if (5 < k && k <= 6) + { + baseRed = c; + baseBlue = x; + } + + return new Color((byte)((baseRed + m) * 255), (byte)((baseGreen + m) * 255), (byte)((baseBlue + m) * 255), 255); + } + + /// <summary> /// Linearly interpolates between a and b by the given percentage dt (0 = 100% a, 1 = 100% b). /// </summary> /// <param name="a">One of the starting values between which to interpolate.</param> /// <param name="b">One of the starting values between which to interpolate.</param> /// <param name="dt">The percentage by which to interpolate, capped between 0 and 1.</param> /// <returns>The interpolated value.</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector4 LinearInterpolate(Vector4 a, Vector4 b, double dt) { // caps the percentage first between 1 and -Infinity, and then between 1 and 0, and reverses it such @@ -282,10 +335,37 @@ namespace StarSimLib.Graphics } /// <summary> + /// Maps a value in the given input range to a new value in the gieen output range. + /// </summary> + /// <param name="value">The value that should be mapped.</param> + /// <param name="minimumInputRange">The lower bound of the input range.</param> + /// <param name="maximumInputRange">The upper bound of the input range.</param> + /// <param name="minimumOutputRange">The lower bound of the output range.</param> + /// <param name="maximumOutputRange">The upper bound of the output range.</param> + /// <returns>The projected value.</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double Map(double value, double minimumInputRange, double maximumInputRange, double minimumOutputRange, double maximumOutputRange) + { + double clampedInput = value < maximumInputRange ? value : + value < minimumInputRange ? minimumInputRange : maximumInputRange; + + double inputRange = maximumInputRange - minimumInputRange, + outputRange = maximumOutputRange - minimumOutputRange; + + double percentIntoRange = clampedInput / inputRange; + + double output = outputRange * percentIntoRange; + + return output < maximumOutputRange ? output : + output < minimumOutputRange ? minimumOutputRange : maximumOutputRange; + } + + /// <summary> /// Projects the given <see cref="Vector4"/> point from world space into screen space. /// </summary> /// <param name="point">The point to project.</param> /// <returns>The projected point.</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] private Vector4 ProjectPoint(Vector4 point) { // rotations should happen before the point is translated into camera space @@ -369,8 +449,13 @@ namespace StarSimLib.Graphics { Vector4[] orbitTracerPositions = body.OrbitTracer.PreviousPositions.ToArray(); + double minimumSpeed = 0, maximumSpeed = 75000; + double clampedSpeed = body.Velocity.Abs() < maximumSpeed ? body.Velocity.Abs() : + body.Velocity.Abs() < minimumSpeed ? minimumSpeed : maximumSpeed; + double clampedRainbowColour = Map(clampedSpeed, minimumSpeed, maximumSpeed, 0, 360); + // we cache the colours used for the orbit tracers and the background, and pack them into a 4D vector - Color tracerColour = Color.Cyan, bgColour = Color.Transparent; + Color tracerColour = ColorFromHSV(clampedRainbowColour, 1, 1), bgColour = Color.Transparent; Vector4 tracerVector = new Vector4(tracerColour.R, tracerColour.G, tracerColour.B, tracerColour.A); Vector4 bgVector = new Vector4(bgColour.R, bgColour.G, bgColour.B, bgColour.A); diff --git a/StarSim/StarSimLib/Physics/BodyGenerator.cs b/StarSim/StarSimLib/Physics/BodyGenerator.cs @@ -5,6 +5,7 @@ using StarSimLib.Data_Structures; using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace StarSimLib.Physics { @@ -45,11 +46,59 @@ namespace StarSimLib.Physics mass => mass >= Constants.CentralBodyMass ? 4f : 2f; /// <summary> + /// Implementation of the <see cref="MassToColourDelegate"/> that creates a range of colours for + /// bodies of differing mass. + /// </summary> + public static readonly MassToColourDelegate RainbowColourDelegate = + mass => ColorFromHSV(mass % 360, 1, 1); + + /// <summary> /// The current generation of <see cref="Body"/> instances that the generator is on. /// </summary> public static uint CurrentGeneration { get; private set; } /// <summary> + /// Creates a new ARGB colour from a HSV colour. + /// </summary> + /// <param name="hue">The hue value for the new colour, between 0-360.</param> + /// <param name="saturation">The saturation value for the new colour, between 0-1.</param> + /// <param name="value">The value for the new colour, between 0-1.</param> + /// <returns>The created ARGB colour.</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Color ColorFromHSV(double hue, double saturation, double value) + { + int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; + double f = hue / 60 - Math.Floor(hue / 60); + + value *= 255; + int v = Convert.ToInt32(value); + int p = Convert.ToInt32(value * (1 - saturation)); + int q = Convert.ToInt32(value * (1 - f * saturation)); + int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); + + switch (hi) + { + case 0: + return new Color(255, (byte)v, (byte)t, (byte)p); + + case 1: + return new Color(255, (byte)q, (byte)v, (byte)p); + + case 2: + return new Color(255, (byte)p, (byte)v, (byte)t); + + case 3: + return new Color(255, (byte)p, (byte)q, (byte)v); + + case 4: + return new Color(255, (byte)t, (byte)p, (byte)v); + + default: + return new Color(255, (byte)v, (byte)p, (byte)q); + } + } + + /// <summary> /// Generates an array of <see cref="Body"/> instances, possibly including a central attractor. /// </summary> /// <param name="bodyCount">The number of <see cref="Body"/> instances to generate.</param> diff --git a/StarSim/StarSimLib/StarSimLib.xml b/StarSim/StarSimLib/StarSimLib.xml @@ -1418,6 +1418,15 @@ Current zoom level of the drawer. </summary> </member> + <member name="M:StarSimLib.Graphics.SimulationDrawer.ColorFromHSV(System.Double,System.Double,System.Double)"> + <summary> + Creates a new ARGB colour from a HSV colour. + </summary> + <param name="hue">The hue value for the new colour, between 0-360.</param> + <param name="saturation">The saturation value for the new colour, between 0-1.</param> + <param name="value">The value for the new colour, between 0-1.</param> + <returns>The created ARGB colour.</returns> + </member> <member name="M:StarSimLib.Graphics.SimulationDrawer.LinearInterpolate(StarSimLib.Data_Structures.Vector4,StarSimLib.Data_Structures.Vector4,System.Double)"> <summary> Linearly interpolates between a and b by the given percentage dt (0 = 100% a, 1 = 100% b). @@ -1427,6 +1436,17 @@ <param name="dt">The percentage by which to interpolate, capped between 0 and 1.</param> <returns>The interpolated value.</returns> </member> + <member name="M:StarSimLib.Graphics.SimulationDrawer.Map(System.Double,System.Double,System.Double,System.Double,System.Double)"> + <summary> + Maps a value in the given input range to a new value in the gieen output range. + </summary> + <param name="value">The value that should be mapped.</param> + <param name="minimumInputRange">The lower bound of the input range.</param> + <param name="maximumInputRange">The upper bound of the input range.</param> + <param name="minimumOutputRange">The lower bound of the output range.</param> + <param name="maximumOutputRange">The upper bound of the output range.</param> + <returns>The projected value.</returns> + </member> <member name="M:StarSimLib.Graphics.SimulationDrawer.ProjectPoint(StarSimLib.Data_Structures.Vector4)"> <summary> Projects the given <see cref="T:StarSimLib.Data_Structures.Vector4"/> point from world space into screen space. @@ -1805,11 +1825,26 @@ Default implementation of the <see cref="T:StarSimLib.Physics.MassToRadiusDelegate"/>. </summary> </member> + <member name="F:StarSimLib.Physics.BodyGenerator.RainbowColourDelegate"> + <summary> + Implementation of the <see cref="T:StarSimLib.Physics.MassToColourDelegate"/> that creates a range of colours for + bodies of differing mass. + </summary> + </member> <member name="P:StarSimLib.Physics.BodyGenerator.CurrentGeneration"> <summary> The current generation of <see cref="T:StarSimLib.Data_Structures.Body"/> instances that the generator is on. </summary> </member> + <member name="M:StarSimLib.Physics.BodyGenerator.ColorFromHSV(System.Double,System.Double,System.Double)"> + <summary> + Creates a new ARGB colour from a HSV colour. + </summary> + <param name="hue">The hue value for the new colour, between 0-360.</param> + <param name="saturation">The saturation value for the new colour, between 0-1.</param> + <param name="value">The value for the new colour, between 0-1.</param> + <returns>The created ARGB colour.</returns> + </member> <member name="M:StarSimLib.Physics.BodyGenerator.GenerateBodies(System.Int32,System.Boolean)"> <summary> Generates an array of <see cref="T:StarSimLib.Data_Structures.Body"/> instances, possibly including a central attractor.