1
Fork 0
mirror of https://github.com/Steffo99/better-tee.git synced 2024-11-22 23:34:18 +00:00
better-tee/Assets/Packages/Mirror/Runtime/FloatBytePacker.cs

61 lines
3.1 KiB
C#
Raw Normal View History

2019-09-17 15:43:32 +00:00
using UnityEngine;
namespace Mirror
{
public static class FloatBytePacker
{
// ScaleFloatToByte( -1f, -1f, 1f, byte.MinValue, byte.MaxValue) => 0
// ScaleFloatToByte( 0f, -1f, 1f, byte.MinValue, byte.MaxValue) => 127
// ScaleFloatToByte(0.5f, -1f, 1f, byte.MinValue, byte.MaxValue) => 191
// ScaleFloatToByte( 1f, -1f, 1f, byte.MinValue, byte.MaxValue) => 255
public static byte ScaleFloatToByte(float value, float minValue, float maxValue, byte minTarget, byte maxTarget)
{
// note: C# byte - byte => int, hence so many casts
int targetRange = maxTarget - minTarget; // max byte - min byte only fits into something bigger
float valueRange = maxValue - minValue;
float valueRelative = value - minValue;
return (byte)(minTarget + (byte)(valueRelative/valueRange * targetRange));
}
// ScaleByteToFloat( 0, byte.MinValue, byte.MaxValue, -1, 1) => -1
// ScaleByteToFloat(127, byte.MinValue, byte.MaxValue, -1, 1) => -0.003921569
// ScaleByteToFloat(191, byte.MinValue, byte.MaxValue, -1, 1) => 0.4980392
// ScaleByteToFloat(255, byte.MinValue, byte.MaxValue, -1, 1) => 1
public static float ScaleByteToFloat(byte value, byte minValue, byte maxValue, float minTarget, float maxTarget)
{
// note: C# byte - byte => int, hence so many casts
float targetRange = maxTarget - minTarget;
byte valueRange = (byte)(maxValue - minValue);
byte valueRelative = (byte)(value - minValue);
return minTarget + (valueRelative / (float)valueRange * targetRange);
}
// eulerAngles have 3 floats, putting them into 2 bytes of [x,y],[z,0]
// would be a waste. instead we compress into 5 bits each => 15 bits.
// so a ushort.
public static ushort PackThreeFloatsIntoUShort(float u, float v, float w, float minValue, float maxValue)
{
// 5 bits max value = 1+2+4+8+16 = 31 = 0x1F
byte lower = ScaleFloatToByte(u, minValue, maxValue, 0x00, 0x1F);
byte middle = ScaleFloatToByte(v, minValue, maxValue, 0x00, 0x1F);
byte upper = ScaleFloatToByte(w, minValue, maxValue, 0x00, 0x1F);
ushort combined = (ushort)(upper << 10 | middle << 5 | lower);
return combined;
}
// see PackThreeFloatsIntoUShort for explanation
public static Vector3 UnpackUShortIntoThreeFloats(ushort combined, float minTarget, float maxTarget)
{
byte lower = (byte)(combined & 0x1F);
byte middle = (byte)((combined >> 5) & 0x1F);
byte upper = (byte)(combined >> 10); // nothing on the left, no & needed
// note: we have to use 4 bits per float, so between 0x00 and 0x0F
float u = ScaleByteToFloat(lower, 0x00, 0x1F, minTarget, maxTarget);
float v = ScaleByteToFloat(middle, 0x00, 0x1F, minTarget, maxTarget);
float w = ScaleByteToFloat(upper, 0x00, 0x1F, minTarget, maxTarget);
return new Vector3(u, v, w);
}
}
}