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:
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.