diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs
index ef5b8e1..1ce7fa2 100644
--- a/AssetStudio/Classes/Mesh.cs
+++ b/AssetStudio/Classes/Mesh.cs
@@ -1413,7 +1413,7 @@ namespace AssetStudio
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
break;
case VertexFormat.Float16:
- result[i] = Half.ToHalf(inputBytes, i * 2);
+ result[i] = (float)HalfHelper.ToHalf(inputBytes, i * 2);
break;
case VertexFormat.UNorm8:
result[i] = inputBytes[i] / 255f;
diff --git a/AssetStudio/Math/Half.cs b/AssetStudio/Math/Half.cs
index 45efd92..26b361f 100644
--- a/AssetStudio/Math/Half.cs
+++ b/AssetStudio/Math/Half.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Globalization;
+#if NETFRAMEWORK
namespace AssetStudio
{
///
@@ -35,27 +36,27 @@ namespace AssetStudio
///
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
///
- public static readonly Half Epsilon = Half.ToHalf(0x0001);
+ public static readonly Half Epsilon = HalfHelper.ToHalf(0x0001);
///
/// Represents the largest possible value of System.Half. This field is constant.
///
- public static readonly Half MaxValue = Half.ToHalf(0x7bff);
+ public static readonly Half MaxValue = HalfHelper.ToHalf(0x7bff);
///
/// Represents the smallest possible value of System.Half. This field is constant.
///
- public static readonly Half MinValue = Half.ToHalf(0xfbff);
+ public static readonly Half MinValue = HalfHelper.ToHalf(0xfbff);
///
/// Represents not a number (NaN). This field is constant.
///
- public static readonly Half NaN = Half.ToHalf(0xfe00);
+ public static readonly Half NaN = HalfHelper.ToHalf(0xfe00);
///
/// Represents negative infinity. This field is constant.
///
- public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);
+ public static readonly Half NegativeInfinity = HalfHelper.ToHalf(0xfc00);
///
/// Represents positive infinity. This field is constant.
///
- public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);
+ public static readonly Half PositiveInfinity = HalfHelper.ToHalf(0x7c00);
#endregion
#region Constructors
@@ -63,7 +64,7 @@ namespace AssetStudio
/// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.
///
/// The value to represent as a System.Half.
- public Half(float value) { this = HalfHelper.SingleToHalf(value); }
+ public Half(float value) { this = HalfHelper.ToHalf(value); }
///
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
///
@@ -314,7 +315,7 @@ namespace AssetStudio
///
/// A System.Half to convert.
/// A single-precision floating-point number that represents the converted System.Half.
- public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }
+ public static implicit operator float(Half value) { return value.ToSingle(); }
///
/// Converts a System.Half to a double-precision floating-point number.
///
@@ -508,32 +509,6 @@ namespace AssetStudio
{
return value.value;
}
- ///
- /// Returns a half-precision floating point number converted from two bytes
- /// at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A half-precision floating point number formed by two bytes beginning at startIndex.
- ///
- /// startIndex is greater than or equal to the length of value minus 1, and is
- /// less than or equal to the length of value minus 1.
- ///
- /// value is null.
- /// startIndex is less than zero or greater than the length of value minus 1.
- public static Half ToHalf(byte[] value, int startIndex)
- {
- return Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));
- }
- ///
- /// Returns a half-precision floating point number converted from its binary representation.
- ///
- /// Binary representation of System.Half value
- /// A half-precision floating point number formed by its binary representation.
- public static Half ToHalf(ushort bits)
- {
- return new Half { value = bits };
- }
///
/// Returns a value indicating the sign of a half-precision floating-point number.
@@ -886,3 +861,4 @@ namespace AssetStudio
#endregion
}
}
+#endif
diff --git a/AssetStudio/Math/HalfHelper.cs b/AssetStudio/Math/HalfHelper.cs
index 82e46b4..5e05b1c 100644
--- a/AssetStudio/Math/HalfHelper.cs
+++ b/AssetStudio/Math/HalfHelper.cs
@@ -1,18 +1,32 @@
using System;
+using System.Buffers.Binary;
using System.Runtime.InteropServices;
namespace AssetStudio
{
+#if NET
+ public static class HalfHelper
+ {
+ public static Half ToHalf(ushort bits)
+ {
+ return (Half)bits;
+ }
+
+ public static Half ToHalf(ReadOnlySpan bytes, int startIndex)
+ {
+ return BinaryPrimitives.ReadHalfLittleEndian(bytes[startIndex..]);
+ }
+ }
+#else
///
/// Helper class for Half conversions and some low level operations.
- /// This class is internally used in the Half class.
///
///
/// References:
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
///
[ComVisible(false)]
- internal static class HalfHelper
+ public static class HalfHelper
{
private static uint[] mantissaTable = GenerateMantissaTable();
private static uint[] exponentTable = GenerateExponentTable();
@@ -169,27 +183,54 @@ namespace AssetStudio
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return Half.ToHalf(result);
}*/
- public static float HalfToSingle(Half half)
+
+ ///
+ /// Returns a half-precision floating point number converted from two bytes
+ /// at a specified position in a byte array.
+ ///
+ /// An array of bytes.
+ /// The starting position within value.
+ /// A half-precision floating point number formed by two bytes beginning at startIndex.
+ ///
+ /// startIndex is greater than or equal to the length of value minus 1, and is
+ /// less than or equal to the length of value minus 1.
+ ///
+ /// value is null.
+ /// startIndex is less than zero or greater than the length of value minus 1.
+ public static Half ToHalf(ReadOnlySpan value, int startIndex)
+ {
+ return ToHalf((ushort)BinaryPrimitives.ReadInt16LittleEndian(value.Slice(startIndex)));
+ }
+ ///
+ /// Returns a half-precision floating point number converted from its binary representation.
+ ///
+ /// Binary representation of System.Half value
+ /// A half-precision floating point number formed by its binary representation.
+ public static Half ToHalf(ushort bits)
+ {
+ return new Half { value = bits };
+ }
+ public static Half ToHalf(float single)
+ {
+ byte[] singleBytes = BitConverter.GetBytes(single);
+ uint value = BitConverter.ToUInt32(singleBytes, 0);
+ ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
+ return ToHalf(result);
+ }
+ public static float ToSingle(this Half half)
{
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
byte[] uintBytes = BitConverter.GetBytes(result);
return BitConverter.ToSingle(uintBytes, 0);
}
- public static Half SingleToHalf(float single)
- {
- byte[] singleBytes = BitConverter.GetBytes(single);
- uint value = BitConverter.ToUInt32(singleBytes, 0);
- ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
- return Half.ToHalf(result);
- }
public static Half Negate(Half half)
{
- return Half.ToHalf((ushort)(half.value ^ 0x8000));
+ return ToHalf((ushort)(half.value ^ 0x8000));
}
public static Half Abs(Half half)
{
- return Half.ToHalf((ushort)(half.value & 0x7fff));
+ return ToHalf((ushort)(half.value & 0x7fff));
}
public static bool IsNaN(Half half)
@@ -209,4 +250,5 @@ namespace AssetStudio
return (half.value == 0xfc00);
}
}
+#endif
}
diff --git a/AssetStudioUtility/Texture2DConverter.cs b/AssetStudioUtility/Texture2DConverter.cs
index 8e39187..34675f5 100644
--- a/AssetStudioUtility/Texture2DConverter.cs
+++ b/AssetStudioUtility/Texture2DConverter.cs
@@ -440,7 +440,7 @@ namespace AssetStudio
{
buff[i] = 0;
buff[i + 1] = 0;
- buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i / 2) * 255f);
+ buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i / 2) * 255f);
buff[i + 3] = 255;
}
return true;
@@ -451,8 +451,8 @@ namespace AssetStudio
for (var i = 0; i < outPutDataSize; i += 4)
{
buff[i] = 0;
- buff[i + 1] = (byte)MathF.Round(Half.ToHalf(image_data, i + 2) * 255f);
- buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i) * 255f);
+ buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i + 2) * 255f);
+ buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i) * 255f);
buff[i + 3] = 255;
}
return true;
@@ -462,10 +462,10 @@ namespace AssetStudio
{
for (var i = 0; i < outPutDataSize; i += 4)
{
- buff[i] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
- buff[i + 1] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);
- buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2) * 255f);
- buff[i + 3] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);
+ buff[i] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 4) * 255f);
+ buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 2) * 255f);
+ buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2) * 255f);
+ buff[i + 3] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 6) * 255f);
}
return true;
}