commit 1a4451c46a11344ba76c2b8c98ed34c27022cc79
parent 7ec58227400e51bb5eed6b9022918c1d317ed4e5
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date: Tue, 2 Jul 2019 16:13:21 +0100
Refactored orbit tracers into separate class.
Diffstat:
14 files changed, 539 insertions(+), 364 deletions(-)
diff --git a/StarSim/StarSim.sln b/StarSim/StarSim.sln
@@ -12,21 +12,49 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|x64.ActiveCfg = Debug|x64
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|x64.Build.0 = Debug|x64
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|x86.ActiveCfg = Debug|x86
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Debug|x86.Build.0 = Debug|x86
{0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|x64.ActiveCfg = Release|x64
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|x64.Build.0 = Release|x64
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|x86.ActiveCfg = Release|x86
+ {0FA6CC2D-C2B7-461B-AADC-4E3AECD2C05C}.Release|x86.Build.0 = Release|x86
{E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|x64.ActiveCfg = Debug|x64
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|x64.Build.0 = Debug|x64
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|x86.ActiveCfg = Debug|x86
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Debug|x86.Build.0 = Debug|x86
{E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|x64.ActiveCfg = Release|x64
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|x64.Build.0 = Release|x64
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|x86.ActiveCfg = Release|x86
+ {E7DA74EF-E69A-4165-BF3D-5B641D991D75}.Release|x86.Build.0 = Release|x86
{83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|x64.ActiveCfg = Debug|x64
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|x64.Build.0 = Debug|x64
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|x86.ActiveCfg = Debug|x86
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Debug|x86.Build.0 = Debug|x86
{83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|Any CPU.Build.0 = Release|Any CPU
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|x64.ActiveCfg = Release|x64
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|x64.Build.0 = Release|x64
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|x86.ActiveCfg = Release|x86
+ {83F04A74-D9DB-4C8C-ABDC-3610099BCC51}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/StarSim/StarSim/Program.cs b/StarSim/StarSim/Program.cs
@@ -4,6 +4,7 @@ using SFML.Graphics;
using SFML.System;
using SFML.Window;
using StarSimLib;
+using StarSimLib.Data_Structures;
using StarSimLib.Graphics;
using StarSimLib.Physics;
using StarSimLib.UI;
diff --git a/StarSim/StarSim/StarSim.csproj b/StarSim/StarSim/StarSim.csproj
@@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
+ <Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
<ItemGroup>
diff --git a/StarSim/StarSimGui/StarSimGui.csproj b/StarSim/StarSimGui/StarSimGui.csproj
@@ -37,6 +37,46 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll</HintPath>
diff --git a/StarSim/StarSimLib/Constants.cs b/StarSim/StarSimLib/Constants.cs
@@ -1,4 +1,5 @@
-using StarSimLib.Physics;
+using StarSimLib.Data_Structures;
+using StarSimLib.Physics;
namespace StarSimLib
{
@@ -20,7 +21,7 @@ namespace StarSimLib
/// <summary>
/// The amount of degrees by which the view will be rotated in any given direction.
/// </summary>
- public const double EulerRotationStep = 1;
+ public const double EulerRotationStep = 0.5;
/// <summary>
/// The frame rate limit for the program.
diff --git a/StarSim/StarSimLib/Data Structures/Body.cs b/StarSim/StarSimLib/Data Structures/Body.cs
@@ -0,0 +1,237 @@
+using System;
+
+namespace StarSimLib.Data_Structures
+{
+ /// <summary>
+ /// Represents a stellar body.
+ /// </summary>
+ public class Body
+ {
+ /// <summary>
+ /// Describes how the <see cref="Body"/> instance should be formatted as a <see cref="string"/>.
+ /// </summary>
+ private const string BodyFormatString =
+ "Body {0,2}.{1,-4}: Pos-{2}, Vel-{3} Mass-{4,3}";
+
+ /// <summary>
+ /// The orbit tracers for this instance.
+ /// </summary>
+ private readonly OrbitTracer orbitTracer;
+
+ /// <summary>
+ /// The backing field for the <see cref="Force"/> property.
+ /// </summary>
+ private Vector4d force;
+
+ /// <summary>
+ /// Backing field for the <see cref="Mass"/> property.
+ /// </summary>
+ private double mass;
+
+ /// <summary>
+ /// Backing field for the <see cref="Position"/> property.
+ /// </summary>
+ private Vector4d position;
+
+ /// <summary>
+ /// Backing field for the <see cref="Velocity"/> property.
+ /// </summary>
+ private Vector4d velocity;
+
+ /// <summary>
+ /// The generation that this body belongs to.
+ /// </summary>
+ public readonly uint Generation;
+
+ /// <summary>
+ /// The unique id for this body.
+ /// </summary>
+ public readonly uint Id;
+
+ /// <summary>
+ /// Initialises a new instance of the <see cref="Body"/> class.
+ /// </summary>
+ /// <param name="position">The starting position of the <see cref="Body"/>.</param>
+ /// <param name="velocity">The starting velocity of the <see cref="Body"/>.</param>
+ /// <param name="mass">The starting mass of the <see cref="Body"/>.</param>
+ /// <param name="generation">The generation that this <see cref="Body"/> belongs to.</param>
+ /// <param name="id">The unique id for this body.</param>
+ public Body(Vector4d position, Vector4d velocity, double mass, uint generation = 1, uint id = 1)
+ {
+ Generation = generation;
+ Id = id;
+
+ this.position = position;
+ this.position.W = 1;
+ this.velocity = velocity;
+ this.mass = mass;
+
+ force = new Vector4d();
+ orbitTracer = new OrbitTracer();
+ }
+
+ /// <summary>
+ /// The current force on the <see cref="Body"/> in 3D space.
+ /// </summary>
+ public Vector4d Force
+ {
+ get { return force; }
+ }
+
+ /// <summary>
+ /// The mass of the <see cref="Body"/>.
+ /// </summary>
+ public double Mass
+ {
+ get { return mass; }
+ }
+
+ /// <summary>
+ /// The <see cref="Data_Structures.OrbitTracer"/> for this instance.
+ /// </summary>
+ public ref readonly OrbitTracer OrbitTracer
+ {
+ get { return ref orbitTracer; }
+ }
+
+ /// <summary>
+ /// The current position of the <see cref="Body"/> in 3D space.
+ /// </summary>
+ public Vector4d Position
+ {
+ get { return position; }
+ }
+
+ /// <summary>
+ /// Whether to record previous positions of this instance, to render an orbit tracer behind it.
+ /// </summary>
+ public bool RecordPreviousPositions { get; set; }
+
+ /// <summary>
+ /// The current velocity of the <see cref="Body"/> in 3D space.
+ /// </summary>
+ public Vector4d Velocity
+ {
+ get { return velocity; }
+ }
+
+ /// <summary>
+ /// Gets the force vector for the attraction between <see cref="Body"/> A and <see cref="Body"/> B.
+ /// </summary>
+ /// <param name="a">The first <see cref="Body"/> instance.</param>
+ /// <param name="b">The second <see cref="Body"/> instance.</param>
+ /// <returns></returns>
+ public static Vector4d GetForceBetween(Body a, Body b)
+ {
+ // Inlines the Body.DistanceTo(Body) as the position deltas need to be cached for later,
+ // as well as to gain a small performance increase
+ double dx = b.Position.X - a.Position.X,
+ dy = b.Position.Y - a.Position.Y,
+ dz = b.Position.Z - a.Position.Z;
+
+ // The distance between two bodies can be found via taking the magnitude of their displacements,
+ // as shown here via pythagoras
+ double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);
+
+ double numerator = Constants.G * a.Mass * b.Mass;
+ double denominator = distance * distance + Constants.SofteningFactor2;
+
+ // Using the equation Force = Gravitational Constant * Mass(a) * Mass(b) / distance(a, b)^2
+ // with a softening factor, we get the attraction force vector between the 2 bodies
+ double force = numerator / denominator;
+
+ return new Vector4d(force * dx / distance, force * dy / distance, force * dz / distance);
+ }
+
+ /// <summary>
+ /// Calculates the force between this instance and the given other body, and adds the resultant vector to the
+ /// internal total force vector.
+ /// </summary>
+ /// <param name="otherBody">The other body to calculate the force between.</param>
+ public void AddForce(Body otherBody)
+ {
+ force += GetForceBetween(this, otherBody);
+ }
+
+ /// <summary>
+ /// Collides this instance with the given <see cref="Body"/> instance.
+ /// </summary>
+ /// <param name="otherBody">The other instance with which to collide.</param>
+ public void Collide(Body otherBody)
+ {
+ mass += otherBody.Mass;
+ velocity += otherBody.Velocity;
+ }
+
+ /// <summary>
+ /// Finds and returns the distance between the current <see cref="Body"/> instance and the given <see cref="Body"/>.
+ /// In other words, it finds the magnitude of the translation vector between the two <see cref="Body"/> instances.
+ /// </summary>
+ /// <param name="body">The other <see cref="Body"/> instance to which to calculate the distance.</param>
+ /// <param name="displacement">The vector showing the displacement of the current body from the given one.</param>
+ /// <returns>The distance to the other <see cref="Body"/> as a <see cref="float"/>.</returns>
+ public double DistanceTo(Body body, out Vector4d displacement)
+ {
+ double dpx = body.Position.X - Position.X,
+ dpy = body.Position.Y - Position.Y,
+ dpz = body.Position.Z - Position.Z;
+
+ displacement = new Vector4d(dpx, dpy, dpz);
+
+ return Math.Sqrt(dpx * dpx + dpy * dpy + dpz * dpz);
+ }
+
+ /// <summary>
+ /// Resets the internal force vector.
+ /// </summary>
+ public void ResetForce()
+ {
+ force.X = 0;
+ force.Y = 0;
+ force.Z = 0;
+ }
+
+ /// <summary>
+ /// Updates the <see cref="Position"/> of the current body using the internal force vector and the given time step.
+ /// </summary>
+ /// <param name="deltaTime">The time step.</param>
+ public void Update(double deltaTime)
+ {
+ velocity += deltaTime * force / mass;
+
+ if (RecordPreviousPositions)
+ {
+ orbitTracer.Enqueue(position);
+ }
+
+ position += deltaTime * velocity;
+ }
+
+ /// <summary>
+ /// Updates the <see cref="Position"/> of the current body using the given force vector and time step.
+ /// </summary>
+ /// <param name="forceVector">The sum vector of all forces due to other <see cref="Body"/>s.</param>
+ /// <param name="deltaTime">The time step.</param>
+ public void Update(Vector4d forceVector, double deltaTime)
+ {
+ velocity += deltaTime * forceVector / mass;
+
+ if (RecordPreviousPositions)
+ {
+ orbitTracer.Enqueue(position);
+ }
+
+ position += deltaTime * velocity;
+ }
+
+ #region Overrides of Object
+
+ /// <inheritdoc />
+ public override string ToString()
+ {
+ return string.Format(BodyFormatString, Generation, Id, Position, Velocity, Mass);
+ }
+
+ #endregion Overrides of Object
+ }
+}
+\ No newline at end of file
diff --git a/StarSim/StarSimLib/Data Structures/EulerAngle.cs b/StarSim/StarSimLib/Data Structures/EulerAngle.cs
@@ -0,0 +1,36 @@
+namespace StarSimLib.Data_Structures
+{
+ /// <summary>
+ /// Represents a set of 3 angles, that together describe a 3D rotation.
+ /// </summary>
+ public struct EulerAngle
+ {
+ /// <summary>
+ /// Angle of rotation in the x axis.
+ /// </summary>
+ public double X;
+
+ /// <summary>
+ /// Angle of rotation in the y axis.
+ /// </summary>
+ public double Y;
+
+ /// <summary>
+ /// Angle of rotation in the z axis.
+ /// </summary>
+ public double Z;
+
+ /// <summary>
+ /// Initialises a new instance of the <see cref="EulerAngle"/> struct.
+ /// </summary>
+ /// <param name="x">The angle of rotation in the x axis.</param>
+ /// <param name="y">The angle of rotation in the y axis.</param>
+ /// <param name="z">The angle of rotation in the z axis.</param>
+ public EulerAngle(double x, double y, double z)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/StarSim/StarSimLib/Data Structures/EulerAngles.cs b/StarSim/StarSimLib/Data Structures/EulerAngles.cs
@@ -1,36 +0,0 @@
-namespace StarSimLib.Data_Structures
-{
- /// <summary>
- /// Represents a set of 3 angles, that together describe a 3D rotation.
- /// </summary>
- public struct EulerAngles
- {
- /// <summary>
- /// Angle of rotation in the x axis.
- /// </summary>
- public double X;
-
- /// <summary>
- /// Angle of rotation in the y axis.
- /// </summary>
- public double Y;
-
- /// <summary>
- /// Angle of rotation in the z axis.
- /// </summary>
- public double Z;
-
- /// <summary>
- /// Initialises a new instance of the <see cref="EulerAngles"/> struct.
- /// </summary>
- /// <param name="x">The angle of rotation in the x axis.</param>
- /// <param name="y">The angle of rotation in the y axis.</param>
- /// <param name="z">The angle of rotation in the z axis.</param>
- public EulerAngles(double x, double y, double z)
- {
- X = x;
- Y = y;
- Z = z;
- }
- }
-}
-\ No newline at end of file
diff --git a/StarSim/StarSimLib/Data Structures/OrbitTracer.cs b/StarSim/StarSimLib/Data Structures/OrbitTracer.cs
@@ -0,0 +1,93 @@
+using System.Collections.Generic;
+using StarSimLib.Physics;
+
+namespace StarSimLib.Data_Structures
+{
+ /// <summary>
+ /// Represents a series of points denoting the previous positions of a <see cref="Body"/> instance. Used to render
+ /// an orbit tracer behind the <see cref="Body"/>.
+ /// </summary>
+ public class OrbitTracer
+ {
+ /// <summary>
+ /// Sample rate for the previous position. Used to improve performance and get a longer orbit tracer tail
+ /// for less computation. The previous position will be saved once every 20 sampling opportunities.
+ /// </summary>
+ private const int PositionSampleRate = 20;
+
+ /// <summary>
+ /// Backing field for the <see cref="PreviousPositions"/> property.
+ /// </summary>
+ private readonly Queue<Vector4d> previousPositions;
+
+ /// <summary>
+ /// Due to the <see cref="Queue{T}"/>s inability to fetch the second-to-last element, we must explicitly
+ /// cache it in order to use it in interpolation calculations later.
+ /// </summary>
+ private Vector4d dequeuedPosition;
+
+ /// <summary>
+ /// Counts the number of sampling opportunities that have gone by since the last position sample. Resets once
+ /// it reaches the value of <see cref="PositionSampleRate"/>.
+ /// </summary>
+ private int positionSampleCounter;
+
+ /// <summary>
+ /// Initialises a new instance of the <see cref="OrbitTracer"/> class.
+ /// </summary>
+ public OrbitTracer()
+ {
+ previousPositions = new Queue<Vector4d>(Constants.StoredPreviousPositionCount);
+ }
+
+ /// <summary>
+ /// An <see cref="Queue{T}"/> containing previous <see cref="Vector4d"/> positions of the body.
+ /// </summary>
+ public ref readonly Queue<Vector4d> PreviousPositions
+ {
+ get { return ref previousPositions; }
+ }
+
+ /// <summary>
+ /// Clears the <see cref="Queue{T}"/> holding the previous positions.
+ /// </summary>
+ public void Clear()
+ {
+ previousPositions.Clear();
+ }
+
+ /// <summary>
+ /// Enqueues the current position on the <see cref="previousPositions"/> queue, to save it.
+ /// Will dequeue positions from the queue if the number of stored positions exceeds the
+ /// value in <see cref="Constants.StoredPreviousPositionCount"/>. Will only enqueue the
+ /// current position if the <see cref="PositionSampleRate"/> is met.
+ /// </summary>
+ public void Enqueue(Vector4d position)
+ {
+ // if the sample rate limit has not yet been met, don't sample a position but instead edit the last stored
+ // position using linear interpolation to give a smooth shrinking motion
+ if (++positionSampleCounter < PositionSampleRate)
+ {
+ /*
+ double interpolationPercentage = positionSampleCounter / (float)PositionSampleRate;
+
+ previousPositions[0].X = (1 - interpolationPercentage) * previousPositions[0].X + interpolationPercentage * previousPositions[1].X;
+ previousPositions[0].Y = (1 - interpolationPercentage) * previousPositions[0].Y + interpolationPercentage * previousPositions[1].Y;
+ previousPositions[0].Z = (1 - interpolationPercentage) * previousPositions[0].Z + interpolationPercentage * previousPositions[1].Z;
+ */
+
+ return;
+ }
+
+ previousPositions.Enqueue(position);
+
+ if (previousPositions.Count >= Constants.StoredPreviousPositionCount)
+ {
+ dequeuedPosition = previousPositions.Dequeue();
+ }
+
+ // reset the counter
+ positionSampleCounter = 0;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/StarSim/StarSimLib/Graphics/Drawer.cs b/StarSim/StarSimLib/Graphics/Drawer.cs
@@ -123,7 +123,7 @@ namespace StarSimLib.Graphics
/// <summary>
/// The 3D rotation.
/// </summary>
- private EulerAngles rotation;
+ private EulerAngle rotation;
/// <summary>
/// The rotation matrix for the x axis.
@@ -340,7 +340,7 @@ namespace StarSimLib.Graphics
// otherwise, we skip the relatively expensive rendering code
if (body.RecordPreviousPositions)
{
- Vector4d[] orbitTracerPositions = body.PreviousPositions.ToArray();
+ Vector4d[] orbitTracerPositions = body.OrbitTracer.PreviousPositions.ToArray();
for (uint i = 0; i < orbitTracerPositions.Length; i++)
{
@@ -415,7 +415,7 @@ namespace StarSimLib.Graphics
"The given rotation direction was not within the valid range.");
}
- // once we hit 360 (or -360) degrees of rotation, we wrap back around to 0 degrees
+ // once we hit 360 degrees of rotation, we wrap back around to 0 degrees
rotation.X %= 360;
rotation.Y %= 360;
rotation.Z %= 360;
diff --git a/StarSim/StarSimLib/Physics/Body.cs b/StarSim/StarSimLib/Physics/Body.cs
@@ -1,281 +0,0 @@
-using System;
-using System.Collections.Generic;
-using StarSimLib.Data_Structures;
-
-namespace StarSimLib.Physics
-{
- /// <summary>
- /// Represents a stellar body.
- /// </summary>
- public class Body
- {
- /// <summary>
- /// Describes how the <see cref="Body"/> instance should be formatted as a <see cref="string"/>.
- /// </summary>
- private const string BodyFormatString =
- "Body {0,2}.{1,-4}: Pos-{2}, Vel-{3} Mass-{4,3}";
-
- /// <summary>
- /// Sample rate for the previous position. Used to improve performance and get a longer orbit tracer tail
- /// for less computation. The previous position will be saved once every 20 sampling opportunities.
- /// </summary>
- private const int PositionSampleRate = 20;
-
- /// <summary>
- /// Backing field for the <see cref="PreviousPositions"/> property.
- /// </summary>
- private readonly Queue<Vector4d> previousPositions;
-
- /// <summary>
- /// The backing field for the <see cref="Force"/> property.
- /// </summary>
- private Vector4d force;
-
- /// <summary>
- /// Backing field for the <see cref="Mass"/> property.
- /// </summary>
- private double mass;
-
- /// <summary>
- /// Backing field for the <see cref="Position"/> property.
- /// </summary>
- private Vector4d position;
-
- /// <summary>
- /// Counts the number of sampling opportunities that have gone by since the last position sample. Resets once
- /// it reaches the value of <see cref="PositionSampleRate"/>.
- /// </summary>
- private int positionSampleCounter = 0;
-
- /// <summary>
- /// Backing field for the <see cref="Velocity"/> property.
- /// </summary>
- private Vector4d velocity;
-
- /// <summary>
- /// The generation that this body belongs to.
- /// </summary>
- public readonly uint Generation;
-
- /// <summary>
- /// The unique id for this body.
- /// </summary>
- public readonly uint Id;
-
- /// <summary>
- /// Initialises a new instance of the <see cref="Body"/> class.
- /// </summary>
- /// <param name="position">The starting position of the <see cref="Body"/>.</param>
- /// <param name="velocity">The starting velocity of the <see cref="Body"/>.</param>
- /// <param name="mass">The starting mass of the <see cref="Body"/>.</param>
- /// <param name="generation">The generation that this <see cref="Body"/> belongs to.</param>
- /// <param name="id">The unique id for this body.</param>
- public Body(Vector4d position, Vector4d velocity, double mass, uint generation = 1, uint id = 1)
- {
- Generation = generation;
- Id = id;
-
- this.position = position;
- this.position.W = 1;
- this.velocity = velocity;
- this.mass = mass;
-
- force = new Vector4d();
- previousPositions = new Queue<Vector4d>(Constants.StoredPreviousPositionCount + 1);
- }
-
- /// <summary>
- /// The current force on the <see cref="Body"/> in 3D space.
- /// </summary>
- public Vector4d Force
- {
- get { return force; }
- }
-
- /// <summary>
- /// The mass of the <see cref="Body"/>.
- /// </summary>
- public double Mass
- {
- get { return mass; }
- }
-
- /// <summary>
- /// The current position of the <see cref="Body"/> in 3D space.
- /// </summary>
- public Vector4d Position
- {
- get { return position; }
- }
-
- /// <summary>
- /// A <see cref="Queue{T}"/> containing previous positions of the body.
- /// </summary>
- public ref readonly Queue<Vector4d> PreviousPositions
- {
- get { return ref previousPositions; }
- }
-
- /// <summary>
- /// Whether to record previous positions of this instance, to render an orbit tracer behind it.
- /// </summary>
- public bool RecordPreviousPositions { get; set; }
-
- /// <summary>
- /// The current velocity of the <see cref="Body"/> in 3D space.
- /// </summary>
- public Vector4d Velocity
- {
- get { return velocity; }
- }
-
- /// <summary>
- /// Enqueues the current position on the <see cref="previousPositions"/> queue, to save it.
- /// Will dequeue positions from the queue if the number of stored positions exceeds the
- /// value in <see cref="Constants.StoredPreviousPositionCount"/>. Will only enqueue the
- /// current position if the <see cref="PositionSampleRate"/> is met.
- /// </summary>
- private void EnqueuePosition()
- {
- // if the sample rate limit has not yet been met, don't sample a position
- if (++positionSampleCounter < PositionSampleRate) return;
-
- previousPositions.Enqueue(position);
-
- if (previousPositions.Count > Constants.StoredPreviousPositionCount)
- {
- previousPositions.Dequeue();
- }
-
- // reset the counter
- positionSampleCounter = 0;
- }
-
- /// <summary>
- /// Gets the force vector for the attraction between <see cref="Body"/> A and <see cref="Body"/> B.
- /// </summary>
- /// <param name="a">The first <see cref="Body"/> instance.</param>
- /// <param name="b">The second <see cref="Body"/> instance.</param>
- /// <returns></returns>
- public static Vector4d GetForceBetween(Body a, Body b)
- {
- // Inlines the Body.DistanceTo(Body) as the position deltas need to be cached for later,
- // as well as to gain a small performance increase
- double dx = b.Position.X - a.Position.X,
- dy = b.Position.Y - a.Position.Y,
- dz = b.Position.Z - a.Position.Z;
-
- // The distance between two bodies can be found via taking the magnitude of their displacements,
- // as shown here via pythagoras
- double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);
-
- double numerator = Constants.G * a.Mass * b.Mass;
- double denominator = distance * distance + Constants.SofteningFactor2;
-
- // Using the equation Force = Gravitational Constant * Mass(a) * Mass(b) / distance(a, b)^2
- // with a softening factor, we get the attraction force vector between the 2 bodies
- double force = numerator / denominator;
-
- return new Vector4d(force * dx / distance, force * dy / distance, force * dz / distance);
- }
-
- /// <summary>
- /// Calculates the force between this instance and the given other body, and adds the resultant vector to the
- /// internal total force vector.
- /// </summary>
- /// <param name="otherBody">The other body to calculate the force between.</param>
- public void AddForce(Body otherBody)
- {
- force += GetForceBetween(this, otherBody);
- }
-
- /// <summary>
- /// Clears the <see cref="Queue{T}"/> holding the previous positions.
- /// </summary>
- public void ClearPreviousPositionQueue()
- {
- previousPositions.Clear();
- }
-
- /// <summary>
- /// Collides this instance with the given <see cref="Body"/> instance.
- /// </summary>
- /// <param name="otherBody">The other instance with which to collide.</param>
- public void Collide(Body otherBody)
- {
- mass += otherBody.Mass;
- velocity += otherBody.Velocity;
- }
-
- /// <summary>
- /// Finds and returns the distance between the current <see cref="Body"/> instance and the given <see cref="Body"/>.
- /// In other words, it finds the magnitude of the translation vector between the two <see cref="Body"/> instances.
- /// </summary>
- /// <param name="body">The other <see cref="Body"/> instance to which to calculate the distance.</param>
- /// <param name="displacement">The vector showing the displacement of the current body from the given one.</param>
- /// <returns>The distance to the other <see cref="Body"/> as a <see cref="float"/>.</returns>
- public double DistanceTo(Body body, out Vector4d displacement)
- {
- double dpx = body.Position.X - Position.X,
- dpy = body.Position.Y - Position.Y,
- dpz = body.Position.Z - Position.Z;
-
- displacement = new Vector4d(dpx, dpy, dpz);
-
- return Math.Sqrt(dpx * dpx + dpy * dpy + dpz * dpz);
- }
-
- /// <summary>
- /// Resets the internal force vector.
- /// </summary>
- public void ResetForce()
- {
- force.X = 0;
- force.Y = 0;
- force.Z = 0;
- }
-
- /// <summary>
- /// Updates the <see cref="Position"/> of the current body using the internal force vector and the given time step.
- /// </summary>
- /// <param name="deltaTime">The time step.</param>
- public void Update(double deltaTime)
- {
- velocity += deltaTime * force / mass;
-
- if (RecordPreviousPositions)
- {
- EnqueuePosition();
- }
-
- position += deltaTime * velocity;
- }
-
- /// <summary>
- /// Updates the <see cref="Position"/> of the current body using the given force vector and time step.
- /// </summary>
- /// <param name="forceVector">The sum vector of all forces due to other <see cref="Body"/>s.</param>
- /// <param name="deltaTime">The time step.</param>
- public void Update(Vector4d forceVector, double deltaTime)
- {
- velocity += deltaTime * forceVector / mass;
-
- if (RecordPreviousPositions)
- {
- EnqueuePosition();
- }
-
- position += deltaTime * velocity;
- }
-
- #region Overrides of Object
-
- /// <inheritdoc />
- public override string ToString()
- {
- return string.Format(BodyFormatString, Generation, Id, Position, Velocity, Mass);
- }
-
- #endregion Overrides of Object
- }
-}
-\ No newline at end of file
diff --git a/StarSim/StarSimLib/StarSimLib.csproj b/StarSim/StarSimLib/StarSimLib.csproj
@@ -2,16 +2,33 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
+ <Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>StarSimLib.xml</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
+ <DocumentationFile>StarSimLib.xml</DocumentationFile>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DocumentationFile>StarSimLib.xml</DocumentationFile>
+ </PropertyGroup>
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>StarSimLib.xml</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
+ <DocumentationFile>StarSimLib.xml</DocumentationFile>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DocumentationFile>StarSimLib.xml</DocumentationFile>
+ </PropertyGroup>
+
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.4" />
diff --git a/StarSim/StarSimLib/StarSimLib.xml b/StarSim/StarSimLib/StarSimLib.xml
@@ -106,29 +106,29 @@
<member name="M:StarSimLib.Contexts.SimulatorContext.OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder)">
<inheritdoc />
</member>
- <member name="T:StarSimLib.Data_Structures.EulerAngles">
+ <member name="T:StarSimLib.Data_Structures.EulerAngle">
<summary>
Represents a set of 3 angles, that together describe a 3D rotation.
</summary>
</member>
- <member name="F:StarSimLib.Data_Structures.EulerAngles.X">
+ <member name="F:StarSimLib.Data_Structures.EulerAngle.X">
<summary>
Angle of rotation in the x axis.
</summary>
</member>
- <member name="F:StarSimLib.Data_Structures.EulerAngles.Y">
+ <member name="F:StarSimLib.Data_Structures.EulerAngle.Y">
<summary>
Angle of rotation in the y axis.
</summary>
</member>
- <member name="F:StarSimLib.Data_Structures.EulerAngles.Z">
+ <member name="F:StarSimLib.Data_Structures.EulerAngle.Z">
<summary>
Angle of rotation in the z axis.
</summary>
</member>
- <member name="M:StarSimLib.Data_Structures.EulerAngles.#ctor(System.Double,System.Double,System.Double)">
+ <member name="M:StarSimLib.Data_Structures.EulerAngle.#ctor(System.Double,System.Double,System.Double)">
<summary>
- Initialises a new instance of the <see cref="T:StarSimLib.Data_Structures.EulerAngles"/> struct.
+ Initialises a new instance of the <see cref="T:StarSimLib.Data_Structures.EulerAngle"/> struct.
</summary>
<param name="x">The angle of rotation in the x axis.</param>
<param name="y">The angle of rotation in the y axis.</param>
@@ -234,6 +234,58 @@
<member name="M:StarSimLib.Data_Structures.Matrix4x4.ToString">
<inheritdoc />
</member>
+ <member name="T:StarSimLib.Data_Structures.OrbitTracer">
+ <summary>
+ Represents a series of points denoting the previous positions of a <see cref="T:StarSimLib.Physics.Body"/> instance. Used to render
+ an orbit tracer behind the <see cref="T:StarSimLib.Physics.Body"/>.
+ </summary>
+ </member>
+ <member name="F:StarSimLib.Data_Structures.OrbitTracer.PositionSampleRate">
+ <summary>
+ Sample rate for the previous position. Used to improve performance and get a longer orbit tracer tail
+ for less computation. The previous position will be saved once every 20 sampling opportunities.
+ </summary>
+ </member>
+ <member name="F:StarSimLib.Data_Structures.OrbitTracer.previousPositions">
+ <summary>
+ Backing field for the <see cref="P:StarSimLib.Data_Structures.OrbitTracer.PreviousPositions"/> property.
+ </summary>
+ </member>
+ <member name="F:StarSimLib.Data_Structures.OrbitTracer.dequeuedPosition">
+ <summary>
+ Due to the <see cref="T:System.Collections.Generic.Queue`1"/>s inability to fetch the second-to-last element, we must explicitly
+ cache it in order to use it in interpolation calculations later.
+ </summary>
+ </member>
+ <member name="F:StarSimLib.Data_Structures.OrbitTracer.positionSampleCounter">
+ <summary>
+ Counts the number of sampling opportunities that have gone by since the last position sample. Resets once
+ it reaches the value of <see cref="F:StarSimLib.Data_Structures.OrbitTracer.PositionSampleRate"/>.
+ </summary>
+ </member>
+ <member name="M:StarSimLib.Data_Structures.OrbitTracer.#ctor">
+ <summary>
+ Initialises a new instance of the <see cref="T:StarSimLib.Data_Structures.OrbitTracer"/> class.
+ </summary>
+ </member>
+ <member name="P:StarSimLib.Data_Structures.OrbitTracer.PreviousPositions">
+ <summary>
+ An <see cref="T:System.Collections.Generic.Queue`1"/> containing previous <see cref="T:StarSimLib.Data_Structures.Vector4d"/> positions of the body.
+ </summary>
+ </member>
+ <member name="M:StarSimLib.Data_Structures.OrbitTracer.Clear">
+ <summary>
+ Clears the <see cref="T:System.Collections.Generic.Queue`1"/> holding the previous positions.
+ </summary>
+ </member>
+ <member name="M:StarSimLib.Data_Structures.OrbitTracer.Enqueue(StarSimLib.Data_Structures.Vector4d)">
+ <summary>
+ Enqueues the current position on the <see cref="F:StarSimLib.Data_Structures.OrbitTracer.previousPositions"/> queue, to save it.
+ Will dequeue positions from the queue if the number of stored positions exceeds the
+ value in <see cref="F:StarSimLib.Constants.StoredPreviousPositionCount"/>. Will only enqueue the
+ current position if the <see cref="F:StarSimLib.Data_Structures.OrbitTracer.PositionSampleRate"/> is met.
+ </summary>
+ </member>
<member name="T:StarSimLib.Data_Structures.Quaternion">
<summary>
Represents a rotation as a set of 4 values.
@@ -707,7 +759,8 @@
<member name="M:StarSimLib.Graphics.Drawer.DrawBodies">
<summary>
Draws each <see cref="T:StarSimLib.Physics.Body"/> instance that is managed by this drawer to the <see cref="T:SFML.Graphics.RenderTarget"/> specified
- in the constructor.
+ in the constructor, using the current view settings (rotation, zoom, etc.) to project the positions from 3D to 2D.
+ This method should be called every frame, as without it the view isn't updated and neither are rotation or zoom.
</summary>
</member>
<member name="M:StarSimLib.Graphics.Drawer.Rotate(StarSimLib.Graphics.RotationDirection,System.Double)">
@@ -733,15 +786,9 @@
Describes how the <see cref="T:StarSimLib.Physics.Body"/> instance should be formatted as a <see cref="T:System.String"/>.
</summary>
</member>
- <member name="F:StarSimLib.Physics.Body.PositionSampleRate">
- <summary>
- Sample rate for the previous position. Used to improve performance and get a longer orbit tracer tail
- for less computation. The previous position will be saved once every 20 sampling opportunities.
- </summary>
- </member>
- <member name="F:StarSimLib.Physics.Body.previousPositions">
+ <member name="F:StarSimLib.Physics.Body.orbitTracer">
<summary>
- Backing field for the <see cref="P:StarSimLib.Physics.Body.PreviousPositions"/> property.
+ The orbit tracers for this instance.
</summary>
</member>
<member name="F:StarSimLib.Physics.Body.force">
@@ -759,12 +806,6 @@
Backing field for the <see cref="P:StarSimLib.Physics.Body.Position"/> property.
</summary>
</member>
- <member name="F:StarSimLib.Physics.Body.positionSampleCounter">
- <summary>
- Counts the number of sampling opportunities that have gone by since the last position sample. Resets once
- it reaches the value of <see cref="F:StarSimLib.Physics.Body.PositionSampleRate"/>.
- </summary>
- </member>
<member name="F:StarSimLib.Physics.Body.velocity">
<summary>
Backing field for the <see cref="P:StarSimLib.Physics.Body.Velocity"/> property.
@@ -800,14 +841,14 @@
The mass of the <see cref="T:StarSimLib.Physics.Body"/>.
</summary>
</member>
- <member name="P:StarSimLib.Physics.Body.Position">
+ <member name="P:StarSimLib.Physics.Body.OrbitTracer">
<summary>
- The current position of the <see cref="T:StarSimLib.Physics.Body"/> in 3D space.
+ The <see cref="T:StarSimLib.Data_Structures.OrbitTracer"/> for this instance.
</summary>
</member>
- <member name="P:StarSimLib.Physics.Body.PreviousPositions">
+ <member name="P:StarSimLib.Physics.Body.Position">
<summary>
- A <see cref="T:System.Collections.Generic.Queue`1"/> containing previous positions of the body.
+ The current position of the <see cref="T:StarSimLib.Physics.Body"/> in 3D space.
</summary>
</member>
<member name="P:StarSimLib.Physics.Body.RecordPreviousPositions">
@@ -820,14 +861,6 @@
The current velocity of the <see cref="T:StarSimLib.Physics.Body"/> in 3D space.
</summary>
</member>
- <member name="M:StarSimLib.Physics.Body.EnqueuePosition">
- <summary>
- Enqueues the current position on the <see cref="F:StarSimLib.Physics.Body.previousPositions"/> queue, to save it.
- Will dequeue positions from the queue if the number of stored positions exceeds the
- value in <see cref="F:StarSimLib.Constants.StoredPreviousPositionCount"/>. Will only enqueue the
- current position if the <see cref="F:StarSimLib.Physics.Body.PositionSampleRate"/> is met.
- </summary>
- </member>
<member name="M:StarSimLib.Physics.Body.GetForceBetween(StarSimLib.Physics.Body,StarSimLib.Physics.Body)">
<summary>
Gets the force vector for the attraction between <see cref="T:StarSimLib.Physics.Body"/> A and <see cref="T:StarSimLib.Physics.Body"/> B.
@@ -843,11 +876,6 @@
</summary>
<param name="otherBody">The other body to calculate the force between.</param>
</member>
- <member name="M:StarSimLib.Physics.Body.ClearPreviousPositionQueue">
- <summary>
- Clears the <see cref="T:System.Collections.Generic.Queue`1"/> holding the previous positions.
- </summary>
- </member>
<member name="M:StarSimLib.Physics.Body.Collide(StarSimLib.Physics.Body)">
<summary>
Collides this instance with the given <see cref="T:StarSimLib.Physics.Body"/> instance.
diff --git a/StarSim/StarSimLib/UI/InputHandler.cs b/StarSim/StarSimLib/UI/InputHandler.cs
@@ -1,5 +1,6 @@
using System;
using SFML.Window;
+using StarSimLib.Data_Structures;
using StarSimLib.Graphics;
using StarSimLib.Physics;
@@ -71,9 +72,9 @@ namespace StarSimLib.UI
{
// we want to clear the screen of any orbit tracers that still exist when we turn orbit tracing
// off, so we must clear the previous position queues of every managed object. this has the
- // effect of clearing the vertex arrays holding the orbit tracer vertices
+ // effect of clearing the vertex arrays holding the orbit tracer vertices during the next draw step
body.RecordPreviousPositions = RecordOrbitTracers;
- body.ClearPreviousPositionQueue();
+ body.OrbitTracer.Clear();
}
break;
@@ -120,6 +121,14 @@ namespace StarSimLib.UI
$"View Rotation: ({bodyDrawer.XAngle},{bodyDrawer.YAngle},{bodyDrawer.ZAngle})";
break;
+ case Keyboard.Key.Comma:
+ // decrease the simulation speed
+ break;
+
+ case Keyboard.Key.Period:
+ // increase the simulation speed
+ break;
+
default:
break;
}