Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: never compare equality of floating numbers #157

Merged
merged 5 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Prowl.Editor/Assets/Importers/ModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public override void Import(SerializedAsset ctx, FileInfo assetPath)
}

GameObject rootNode = GOs[0].Item1;
if (UnitScale != 1f)
if (Mathf.ApproximatelyEquals(UnitScale , 1f))
rootNode.Transform.localScale = Vector3.one * UnitScale;

// Add Animation Component with all the animations assigned
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Editor/Editor/GameWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ protected override void Draw()
var renderSize = innerRect.Size;
renderSize.x = MathD.Max(renderSize.x, 1);
renderSize.y = MathD.Max(renderSize.y, 1);
if (renderSize.x != RenderTarget.Width || renderSize.y != RenderTarget.Height)
if (MathD.ApproximatelyEquals(renderSize.x, RenderTarget.Width) || MathD.ApproximatelyEquals(renderSize.y, RenderTarget.Height))
{
GeneralPreferences.Instance.CurrentWidth = (int)renderSize.x;
GeneralPreferences.Instance.CurrentHeight = (int)renderSize.y;
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Editor/Editor/NodeEditor/NodeEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ public Texture2D Update(Gui windowGui, bool focused, Vector2 screenPos, uint wid

gui.PointerWheel = Input.MouseWheelDelta;

if ((RenderTarget == null) || (MathD.Max(width, 1) != RenderTarget.Width || MathD.Max(height, 1) != RenderTarget.Height))
if ((RenderTarget == null) || (MathD.ApproximatelyEquals(MathD.Max(width, 1), RenderTarget.Width) || MathD.ApproximatelyEquals(MathD.Max(height, 1), RenderTarget.Height)))
RefreshRenderTexture(new(MathD.Max(width, 1), MathD.Max(height, 1)));

Veldrid.CommandList commandList = Graphics.GetCommandList();
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Editor/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static int Run(CliOpenOptions options)
else if (Hotkeys.IsHotkeyDown("SaveScene", new() { Key = Key.S, Ctrl = true }))
EditorGuiManager.SaveScene();

Application.isPlaying = PlayMode.Current == PlayMode.Mode.Playing;
Application.IsPlaying = PlayMode.Current == PlayMode.Mode.Playing;


try
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Players/Prowl.Desktop/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal class Program
public static int Main(string[] args)
{

Application.isPlaying = true;
Application.IsPlaying = true;
Application.DataPath = Data.FullName;


Expand Down
10 changes: 5 additions & 5 deletions Prowl.Runtime/AnimationCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,10 @@ public KeyFrame(double position, double value, double tangentIn = 0, double tang
if (Equals(value2, null))
return Equals(value1, null);

return (value1.Position == value2.Position)
&& (value1.Value == value2.Value)
&& (value1.TangentIn == value2.TangentIn)
&& (value1.TangentOut == value2.TangentOut)
return (MathD.ApproximatelyEquals(value1.Position, value2.Position))
&& (MathD.ApproximatelyEquals(value1.Value, value2.Value))
&& (MathD.ApproximatelyEquals(value1.TangentIn, value2.TangentIn))
&& (MathD.ApproximatelyEquals(value1.TangentOut, value2.TangentOut))
&& (value1.Continuity == value2.Continuity);
}

Expand Down Expand Up @@ -453,7 +453,7 @@ public KeyFrame this[int index]
if (index >= _keys.Count)
throw new IndexOutOfRangeException();

if (_keys[index].Position == value.Position)
if (MathD.ApproximatelyEquals(_keys[index].Position, value.Position))
_keys[index] = value;
else
{
Expand Down
32 changes: 16 additions & 16 deletions Prowl.Runtime/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Prowl.Runtime;

public static class Application
{
public static bool isRunning;
public static bool isPlaying = false;
public static bool isEditor { get; private set; }
public static bool IsRunning;
public static bool IsPlaying = false;
public static bool IsEditor { get; private set; }

public static string? DataPath = null;

Expand All @@ -25,24 +25,24 @@ public static class Application
public static event Action Render;
public static event Action Quitting;

private static readonly TimeData AppTime = new();
private static readonly TimeData s_appTime = new();

private static readonly GraphicsBackend[] preferredWindowsBackends = // Covers Windows/UWP
private static readonly GraphicsBackend[] s_preferredWindowsBackends = // Covers Windows/UWP
[
GraphicsBackend.Vulkan,
GraphicsBackend.OpenGL,
GraphicsBackend.Direct3D11,
GraphicsBackend.OpenGLES,
];

private static readonly GraphicsBackend[] preferredUnixBackends = // Cover Unix-like (Linux, FreeBSD, OpenBSD)
private static readonly GraphicsBackend[] s_preferredUnixBackends = // Cover Unix-like (Linux, FreeBSD, OpenBSD)
[
GraphicsBackend.Vulkan,
GraphicsBackend.OpenGL,
GraphicsBackend.OpenGLES,
];

private static readonly GraphicsBackend[] preferredMacBackends = // Covers MacOS/Apple
private static readonly GraphicsBackend[] s_preferredMacBackends = // Covers MacOS/Apple
[
GraphicsBackend.Metal,
GraphicsBackend.OpenGL,
Expand All @@ -53,20 +53,20 @@ public static GraphicsBackend GetBackend()
{
if (RuntimeUtils.IsWindows())
{
return preferredWindowsBackends[0];
return s_preferredWindowsBackends[0];
}
else if (RuntimeUtils.IsMac())
{
return preferredMacBackends[0];
return s_preferredMacBackends[0];
}

return preferredUnixBackends[0];
return s_preferredUnixBackends[0];
}

public static void Run(string title, int width, int height, IAssetProvider assetProvider, bool editor)
{
AssetProvider = assetProvider;
isEditor = editor;
IsEditor = editor;

Debug.Log("Initializing...");

Expand All @@ -76,8 +76,8 @@ public static void Run(string title, int width, int height, IAssetProvider asset

Screen.Closing += AppClose;

isRunning = true;
isPlaying = true; // Base application is not the editor, isplaying is always true
IsRunning = true;
IsPlaying = true; // Base application is not the editor, isplaying is always true

Screen.Start($"{title} - {GetBackend()}", new Vector2Int(width, height), new Vector2Int(100, 100), WindowState.Normal);
}
Expand All @@ -103,9 +103,9 @@ static void AppUpdate()
{
AudioSystem.UpdatePool();

AppTime.Update();
s_appTime.Update();

Time.TimeStack.Push(AppTime);
Time.TimeStack.Push(s_appTime);

Update?.Invoke();
Render?.Invoke();
Expand All @@ -120,7 +120,7 @@ static void AppUpdate()

static void AppClose()
{
isRunning = false;
IsRunning = false;
Quitting?.Invoke();
Graphics.Dispose();
Physics.Dispose();
Expand Down
6 changes: 4 additions & 2 deletions Prowl.Runtime/Components/Audio/AudioSource.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.

using System;

using Prowl.Icons;
using Prowl.Runtime.Audio;

Expand Down Expand Up @@ -72,13 +74,13 @@ public override void Update()
_looping = Looping;
}

if (_gain != Volume)
if (Mathf.ApproximatelyEquals(_gain , Volume))
{
_source.Gain = Volume;
_gain = Volume;
}

if (_maxDistance != MaxDistance)
if (Mathf.ApproximatelyEquals(_maxDistance , MaxDistance))
{
_source.MaxDistance = MaxDistance;
_maxDistance = MaxDistance;
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Runtime/Components/Physics/Rigidbody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public float SleepThreshold
get => _sleepThreshold;
set
{
if (_sleepThreshold == value)
if (MathD.ApproximatelyEquals(_sleepThreshold, value))
return;

_sleepThreshold = value;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.

using System;
using System.Runtime.CompilerServices;

using BepuPhysics;
Expand Down Expand Up @@ -48,7 +49,7 @@ public unsafe bool ConfigureContactManifold<TManifold>(int workerIndex, Collidab
var b = CollidableMaterials[pair.B];
pairMaterial.FrictionCoefficient = a.FrictionCoefficient * b.FrictionCoefficient;
pairMaterial.MaximumRecoveryVelocity = (float)MathD.Max(a.MaximumRecoveryVelocity, b.MaximumRecoveryVelocity);
pairMaterial.SpringSettings = pairMaterial.MaximumRecoveryVelocity == a.MaximumRecoveryVelocity ? a.SpringSettings : b.SpringSettings;
pairMaterial.SpringSettings = MathD.ApproximatelyEquals(pairMaterial.MaximumRecoveryVelocity, a.MaximumRecoveryVelocity) ? a.SpringSettings : b.SpringSettings;
//For the purposes of the demo, contact constraints are always generated.
ContactEvents.HandleManifold(workerIndex, pair, ref manifold);
Physics.Characters.TryReportContacts(pair, ref manifold, workerIndex, ref pairMaterial);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ void AnalyzeContactsForCharacterRegion(int start, int exclusiveEnd, int workerIn
//2) The character was previously supported by a body, and is now supported by a different body.
//3) The character was previously supported by a static, and is now supported by a body.
//4) The character was previously supported by a body, and is now supported by a static.
var shouldRemove = character.Supported && (character.TryJump || supportCandidate.Depth == float.MinValue || character.Support.Packed != supportCandidate.Support.Packed);
var shouldRemove = character.Supported && (character.TryJump || MathD.ApproximatelyEquals(supportCandidate.Depth, float.MinValue) || character.Support.Packed != supportCandidate.Support.Packed);
if (shouldRemove)
{
//Mark the constraint for removal.
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Runtime/GUI/Graphics/UIDrawList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ public void PathLineTo(Vector2 pos)

public void PathLineToMergeDuplicate(Vector2 pos)
{
if (_buildingPath.Count == 0 || _buildingPath[_buildingPath.Count - 1].x != pos.x || _buildingPath[_buildingPath.Count - 1].y != pos.y)
if (_buildingPath.Count == 0 || MathD.ApproximatelyEquals(_buildingPath[ 1].x, pos.x) || MathD.ApproximatelyEquals(_buildingPath[^1].y, pos.y))
_buildingPath.Add(pos);
}

Expand Down
11 changes: 6 additions & 5 deletions Prowl.Runtime/GUI/Gui.Animation.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.

using System;
using System.Collections.Generic;

using Prowl.Runtime.Utils;
Expand Down Expand Up @@ -184,8 +185,8 @@ static double GetEase(double time, EaseType type)
static double QuintInOut(double time) => time < 0.5 ? 16 * time * time * time * time * time : 1 - MathD.Pow(-2 * time + 2, 5) / 2;

static double ExpoIn(double time) => time == 0 ? 0 : MathD.Pow(2, 10 * time - 10);
static double ExpoOut(double time) => time == 1 ? 1 : 1 - MathD.Pow(2, -10 * time);
static double ExpoInOut(double time) => time == 0 ? 0 : time == 1 ? 1 : time < 0.5 ? MathD.Pow(2, 20 * time - 10) / 2 : (2 - MathD.Pow(2, -20 * time + 10)) / 2;
static double ExpoOut(double time) => MathD.ApproximatelyEquals(time, 1) ? 1 : 1 - MathD.Pow(2, -10 * time);
static double ExpoInOut(double time) => time == 0 ? 0 : MathD.ApproximatelyEquals(time, 1) ? 1 : time < 0.5 ? MathD.Pow(2, 20 * time - 10) / 2 : (2 - MathD.Pow(2, -20 * time + 10)) / 2;

static double CircIn(double time) => 1 - MathD.Sqrt(1 - MathD.Pow(time, 2));
static double CircOut(double time) => MathD.Sqrt(1 - MathD.Pow(time - 1, 2));
Expand All @@ -197,9 +198,9 @@ static double BackInOut(double time) => time < 0.5 ?
MathD.Pow(2 * time, 2) * ((ConstantB + 1) * 2 * time - ConstantB) / 2 :
(MathD.Pow(2 * time - 2, 2) * ((ConstantB + 1) * (time * 2 - 2) + ConstantB) + 2) / 2;

static double ElasticIn(double time) => time == 0 ? 0 : time == 1 ? 1 : -MathD.Pow(2, 10 * time - 10) * MathD.Sin((time * 10.0 - 10.75) * ConstantD);
static double ElasticOut(double time) => time == 0 ? 0 : time == 1 ? 1 : MathD.Pow(2, -10 * time) * MathD.Sin((time * 10 - 0.75) * ConstantD) + 1;
static double ElasticInOut(double time) => time == 0 ? 0 : time == 1 ? 1 : time < 0.5 ? -(MathD.Pow(2, 20 * time - 10) * MathD.Sin((20 * time - 11.125) * ConstantE)) / 2 : MathD.Pow(2, -20 * time + 10) * MathD.Sin((20 * time - 11.125) * ConstantE) / 2 + 1;
static double ElasticIn(double time) => time == 0 ? 0 : MathD.ApproximatelyEquals(time, 1) ? 1 : -MathD.Pow(2, 10 * time - 10) * MathD.Sin((time * 10.0 - 10.75) * ConstantD);
static double ElasticOut(double time) => time == 0 ? 0 : MathD.ApproximatelyEquals(time, 1) ? 1 : MathD.Pow(2, -10 * time) * MathD.Sin((time * 10 - 0.75) * ConstantD) + 1;
static double ElasticInOut(double time) => time == 0 ? 0 : MathD.ApproximatelyEquals(time, 1) ? 1 : time < 0.5 ? -(MathD.Pow(2, 20 * time - 10) * MathD.Sin((20 * time - 11.125) * ConstantE)) / 2 : MathD.Pow(2, -20 * time + 10) * MathD.Sin((20 * time - 11.125) * ConstantE) / 2 + 1;

static double BounceIn(double t) => 1 - BounceOut(1 - t);
static double BounceOut(double t)
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Runtime/GUI/Gui.Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void ProcessFrame(Veldrid.CommandList commandList, Rect screenRect, doubl
layoutDirty = true;
_computedNodeHashes = newNodeHashes;

if (lastUIScale == uiScale)
if (MathD.ApproximatelyEquals(lastUIScale, uiScale))
layoutDirty = true;

// Now that we have the nodes we can properly process their LayoutNode
Expand Down
3 changes: 2 additions & 1 deletion Prowl.Runtime/GUI/Gui.Interaction.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.

using System;
using System.Collections.Generic;

using Prowl.Runtime.GUI.Layout;
Expand Down Expand Up @@ -123,7 +124,7 @@ public Interactable GetInteractable(LayoutNode target, Rect? interactArea = null
/// </summary>
public bool IsBlockedByInteractable(Vector2 pos, double zIndex = -1, ulong ignoreID = 0)
{
if (zIndex == -1)
if (MathD.ApproximatelyEquals(zIndex, -1))
{
if (!_zInteractableCounter.TryGetValue(CurrentZIndex, out int count))
count = 0;
Expand Down
18 changes: 10 additions & 8 deletions Prowl.Runtime/GUI/Layout/Spacing.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.

using System;

namespace Prowl.Runtime.GUI;

public struct Spacing
Expand Down Expand Up @@ -29,18 +31,18 @@ public Spacing(double left, double right, double top, double bottom)

public static bool operator ==(Spacing s1, Spacing s2)
{
return s1.Left == s2.Left &&
s1.Right == s2.Right &&
s1.Top == s2.Top &&
s1.Bottom == s2.Bottom;
return MathD.ApproximatelyEquals(s1.Left, s2.Left) &&
MathD.ApproximatelyEquals(s1.Right, s2.Right) &&
MathD.ApproximatelyEquals(s1.Top, s2.Top) &&
MathD.ApproximatelyEquals(s1.Bottom, s2.Bottom);
}

public static bool operator !=(Spacing s1, Spacing s2)
{
return s1.Left != s2.Left ||
s1.Right != s2.Right ||
s1.Top != s2.Top ||
s1.Bottom != s2.Bottom;
return MathD.ApproximatelyEquals(s1.Left , s2.Left) ||
MathD.ApproximatelyEquals(s1.Right , s2.Right) ||
MathD.ApproximatelyEquals(s1.Top , s2.Top) ||
MathD.ApproximatelyEquals(s1.Bottom , s2.Bottom);
}

public override bool Equals(object obj)
Expand Down
2 changes: 1 addition & 1 deletion Prowl.Runtime/GameObject/MonoBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ internal void Do(Action action)

try
{
if (Application.isPlaying || always)
if (Application.IsPlaying || always)
action();
}
catch (Exception e)
Expand Down
12 changes: 6 additions & 6 deletions Prowl.Runtime/Math/Bounds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,12 @@ public void Contains(ref Vector3 point, out ContainmentType result)
{
result = ContainmentType.Disjoint;
}//or if point is on box because coordonate of point is lesser or equal
else if (point.x == min.x
|| point.x == max.x
|| point.y == min.y
|| point.y == max.y
|| point.z == min.z
|| point.z == max.z)
else if (MathD.ApproximatelyEquals(point.x, min.x)
|| MathD.ApproximatelyEquals(point.x, max.x)
|| MathD.ApproximatelyEquals(point.y, min.y)
|| MathD.ApproximatelyEquals(point.y, max.y)
|| MathD.ApproximatelyEquals(point.z, min.z)
|| MathD.ApproximatelyEquals(point.z, max.z))
result = ContainmentType.Intersects;
else
result = ContainmentType.Contains;
Expand Down
7 changes: 2 additions & 5 deletions Prowl.Runtime/Math/MathD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Prowl.Runtime;

public static class MathD
{
private const MethodImplOptions IN = MethodImplOptions.AggressiveInlining;
public const MethodImplOptions IN = MethodImplOptions.AggressiveInlining;

#region Constants

Expand Down Expand Up @@ -38,9 +38,6 @@ public static class MathD
/// A small but not tiny value, Used in places like ApproximatelyEquals, where there is some tolerance (0.00001)
public static readonly double Small = 0.000001;

/// <inheritdoc cref="double.MinValue"/>
public static readonly double Epsilon = double.MinValue;

/// <inheritdoc cref="double.PositiveInfinity"/>
public const double Infinity = double.PositiveInfinity;

Expand Down Expand Up @@ -194,7 +191,7 @@ public static double LerpAngle(double aRad, double bRad, double t)

[MethodImpl(IN)] public static int ComputeMipLevels(int width, int height) => (int)Math.Log2(Math.Max(width, height));

[MethodImpl(IN)] public static bool ApproximatelyEquals(double a, double b) => Abs(a - b) < 0.00001f;
[MethodImpl(IN)] public static bool ApproximatelyEquals(double a, double b) => Abs(a - b) < double.Epsilon;
[MethodImpl(IN)] public static bool ApproximatelyEquals(Vector2 a, Vector2 b) => ApproximatelyEquals(a.x, b.x) && ApproximatelyEquals(a.y, b.y);
[MethodImpl(IN)] public static bool ApproximatelyEquals(Vector3 a, Vector3 b) => ApproximatelyEquals(a.x, b.x) && ApproximatelyEquals(a.y, b.y) && ApproximatelyEquals(a.z, b.z);
[MethodImpl(IN)] public static bool ApproximatelyEquals(Vector4 a, Vector4 b) => ApproximatelyEquals(a.x, b.x) && ApproximatelyEquals(a.y, b.y) && ApproximatelyEquals(a.z, b.z) && ApproximatelyEquals(a.w, b.w);
Expand Down
Loading
Loading