From 722de03bd162eae6a43d8d6b19ee37766bf3b282 Mon Sep 17 00:00:00 2001 From: MeltyPlayer Date: Mon, 23 Oct 2023 00:57:13 -0500 Subject: [PATCH] Optimized how floats are calculated in Battalion Wars. --- .../Modl/Modl Tests/WeirdFloatMathTests.cs | 31 ++++++++++++++ .../Modl/src/schema/anim/WeirdFloatMath.cs | 42 +++++++++++++------ .../Modl/Modl/src/schema/anim/bw1/Bw1Anim.cs | 37 ++++++++-------- .../Modl/Modl/src/schema/modl/bw2/Bw2Modl.cs | 3 +- 4 files changed, 81 insertions(+), 32 deletions(-) create mode 100644 FinModelUtility/Formats/Modl/Modl Tests/WeirdFloatMathTests.cs diff --git a/FinModelUtility/Formats/Modl/Modl Tests/WeirdFloatMathTests.cs b/FinModelUtility/Formats/Modl/Modl Tests/WeirdFloatMathTests.cs new file mode 100644 index 000000000..36d007a78 --- /dev/null +++ b/FinModelUtility/Formats/Modl/Modl Tests/WeirdFloatMathTests.cs @@ -0,0 +1,31 @@ +namespace modl.schema.anim { + public class WeirdFloatMathTests { + [Test] + [TestCase(3100000000, -0.00009453f)] + [TestCase(3150000000, -0.005895f)] + [TestCase(3200000000, -0.367431f)] + [TestCase(3250000000, -22.883056f)] + [TestCase(3300000000, -1424.03125f)] + [TestCase((uint) 0x0229C4AB, WeirdFloatMath.C_ZERO)] + [TestCase((uint) 0x38800000, WeirdFloatMath.C_6_10351_EN5)] + [TestCase((uint) 0x3F000000, WeirdFloatMath.C_HALF)] + [TestCase((uint) 0x40400000, WeirdFloatMath.C_3)] + [TestCase((uint) 0x46800000, WeirdFloatMath.C_16384)] + public void TestInterpretAsSingle(uint input, float expectedOutput) + => Assert.AreEqual(expectedOutput, + WeirdFloatMath.InterpretAsSingle(input), + .000001f); + + [Test] + [TestCase(13746744073709551615, -2.6518952414567028E-06d)] + [TestCase(13796744073709551615, -0.0058304183539235046d)] + [TestCase(13846744073709551615, -12.758538758847861d)] + [TestCase(13896744073709551615, -27804.427732706066d)] + [TestCase(13946744073709551615, -60373745.84277343d)] + [TestCase((ulong) 0x4330000000000000, WeirdFloatMath.C_4503599627370496)] + public void TestInterpretAsDouble(ulong input, double expectedOutput) + => Assert.AreEqual(expectedOutput, + WeirdFloatMath.InterpretAsDouble(input), + .0000001); + } +} \ No newline at end of file diff --git a/FinModelUtility/Formats/Modl/Modl/src/schema/anim/WeirdFloatMath.cs b/FinModelUtility/Formats/Modl/Modl/src/schema/anim/WeirdFloatMath.cs index f249a27d4..45a9c8a5f 100644 --- a/FinModelUtility/Formats/Modl/Modl/src/schema/anim/WeirdFloatMath.cs +++ b/FinModelUtility/Formats/Modl/Modl/src/schema/anim/WeirdFloatMath.cs @@ -1,23 +1,41 @@ -namespace modl.schema.anim { +using System.Runtime.CompilerServices; + +namespace modl.schema.anim { public static class WeirdFloatMath { + /// 0x38800000 + public const float C_6_10351_EN5 = 6.103515625E-05f; + + /// 0x0229C4AB + public const float C_ZERO = 0; + + /// 0x3F000000 + public const float C_HALF = 0.5f; + + /// 0x40400000 + public const float C_3 = 3; + + /// 0x46800000 + public const float C_16384 = 16384f; + + /// 0x4330000000000000 + public const double C_4503599627370496 = 4503599627370496; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong Concat44(uint first, uint second) => ((ulong) first << 32) | second; - public static double InterpretAsDouble(ulong value) { - Span bytes = stackalloc byte[8]; - BitConverter.TryWriteBytes(bytes, value); - return BitConverter.ToDouble(bytes); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe double InterpretAsDouble(ulong value) + => *(double*) (&value); - public static float InterpretAsSingle(uint value) { - Span bytes = stackalloc byte[4]; - BitConverter.TryWriteBytes(bytes, value); - return BitConverter.ToSingle(bytes); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float InterpretAsSingle(uint value) + => *(float*) (&value); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double CreateWeirdDoubleFromUInt32(uint value) => WeirdFloatMath.InterpretAsDouble( WeirdFloatMath.Concat44(0x43300000, value)) - - WeirdFloatMath.InterpretAsDouble(0x4330000000000000); + C_4503599627370496; } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Modl/Modl/src/schema/anim/bw1/Bw1Anim.cs b/FinModelUtility/Formats/Modl/Modl/src/schema/anim/bw1/Bw1Anim.cs index 376df3b7b..c33ad65d9 100644 --- a/FinModelUtility/Formats/Modl/Modl/src/schema/anim/bw1/Bw1Anim.cs +++ b/FinModelUtility/Formats/Modl/Modl/src/schema/anim/bw1/Bw1Anim.cs @@ -128,27 +128,29 @@ public void Parse3PositionValuesFrom2UShorts_( public bool Parse4RotationValuesFrom3UShorts_(IBinaryReader br, Span outValues) { - var first_ushort = br.ReadUInt16(); - var second_ushort = br.ReadUInt16(); - var third_ushort = br.ReadUInt16(); + Span shorts = stackalloc ushort[3]; + br.ReadUInt16s(shorts); + var first_ushort = shorts[0]; + var second_ushort = shorts[1]; + var third_ushort = shorts[2]; - var const_for_out_value_2 = WeirdFloatMath.InterpretAsSingle(0x38000000); + var const_for_out_value_2 = WeirdFloatMath.C_6_10351_EN5; var out_x = - ((WeirdFloatMath.InterpretAsDouble(WeirdFloatMath.Concat44( - 0x43300000, - (uint) (first_ushort & - 0x7fff))) - - WeirdFloatMath.InterpretAsDouble(0x4330000000000000)) - - WeirdFloatMath.InterpretAsSingle(0x46800000)) * - WeirdFloatMath.InterpretAsSingle(0x38800000); + ((WeirdFloatMath.InterpretAsDouble( + WeirdFloatMath.Concat44( + 0x43300000, + (uint) (first_ushort & 0x7fff))) - + WeirdFloatMath.C_4503599627370496) - + WeirdFloatMath.C_16384) * + WeirdFloatMath.C_6_10351_EN5; var out_y = ((WeirdFloatMath.InterpretAsDouble( WeirdFloatMath.Concat44(0x43300000, (uint) (second_ushort & 0x7fff))) - - WeirdFloatMath.InterpretAsDouble(0x4330000000000000)) - - WeirdFloatMath.InterpretAsSingle(0x46800000)) * - WeirdFloatMath.InterpretAsSingle(0x38800000); + WeirdFloatMath.C_4503599627370496) - + WeirdFloatMath.C_16384) * + WeirdFloatMath.C_6_10351_EN5; var third_parsed_thing = WeirdFloatMath.CreateWeirdDoubleFromUInt32(third_ushort); @@ -163,17 +165,16 @@ public bool Parse4RotationValuesFrom3UShorts_(IBinaryReader br, ((1 - out_x * out_x) - out_y * out_y) - out_z * out_z; var out_w = 0d; if (out_w <= expected_normalized_w) { - if (WeirdFloatMath.InterpretAsSingle(0x0229C4AB) < - expected_normalized_w) { + if (WeirdFloatMath.C_ZERO < expected_normalized_w) { var inverse_sqrt_of_expected_normalized_w = 1.0 / Math.Sqrt(expected_normalized_w); out_w = (float) (-(inverse_sqrt_of_expected_normalized_w * inverse_sqrt_of_expected_normalized_w * expected_normalized_w - - WeirdFloatMath.InterpretAsSingle(0x40400000)) * + WeirdFloatMath.C_3) * inverse_sqrt_of_expected_normalized_w * - WeirdFloatMath.InterpretAsSingle(0x3F000000)); + WeirdFloatMath.C_HALF); if (out_w <= 0.0) { out_w = expected_normalized_w; } diff --git a/FinModelUtility/Formats/Modl/Modl/src/schema/modl/bw2/Bw2Modl.cs b/FinModelUtility/Formats/Modl/Modl/src/schema/modl/bw2/Bw2Modl.cs index ec7f4a805..cbda94768 100644 --- a/FinModelUtility/Formats/Modl/Modl/src/schema/modl/bw2/Bw2Modl.cs +++ b/FinModelUtility/Formats/Modl/Modl/src/schema/modl/bw2/Bw2Modl.cs @@ -1,5 +1,4 @@ -using fin.data; -using fin.data.dictionaries; +using fin.data.dictionaries; using fin.schema; using fin.util.asserts;