123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- using System;
- using UnityEngine;
- namespace Mirror
- {
-
- public static class Compression
- {
-
-
-
-
-
- public static int LargestAbsoluteComponentIndex(Vector4 value, out float largestAbs, out Vector3 withoutLargest)
- {
-
- Vector4 abs = new Vector4(Mathf.Abs(value.x), Mathf.Abs(value.y), Mathf.Abs(value.z), Mathf.Abs(value.w));
-
- largestAbs = abs.x;
- withoutLargest = new Vector3(value.y, value.z, value.w);
- int largestIndex = 0;
-
-
-
-
- if (abs.y > largestAbs)
- {
- largestIndex = 1;
- largestAbs = abs.y;
- withoutLargest = new Vector3(value.x, value.z, value.w);
- }
- if (abs.z > largestAbs)
- {
- largestIndex = 2;
- largestAbs = abs.z;
- withoutLargest = new Vector3(value.x, value.y, value.w);
- }
- if (abs.w > largestAbs)
- {
- largestIndex = 3;
- largestAbs = abs.w;
- withoutLargest = new Vector3(value.x, value.y, value.z);
- }
- return largestIndex;
- }
-
-
- public static ushort ScaleFloatToUShort(float value, float minValue, float maxValue, ushort minTarget, ushort maxTarget)
- {
-
-
- int targetRange = maxTarget - minTarget;
- float valueRange = maxValue - minValue;
- float valueRelative = value - minValue;
- return (ushort)(minTarget + (ushort)(valueRelative / valueRange * targetRange));
- }
-
-
- public static float ScaleUShortToFloat(ushort value, ushort minValue, ushort maxValue, float minTarget, float maxTarget)
- {
-
- float targetRange = maxTarget - minTarget;
- ushort valueRange = (ushort)(maxValue - minValue);
- ushort valueRelative = (ushort)(value - minValue);
- return minTarget + (valueRelative / (float)valueRange * targetRange);
- }
- const float QuaternionMinRange = -0.707107f;
- const float QuaternionMaxRange = 0.707107f;
- const ushort TenBitsMax = 0x3FF;
-
- static float QuaternionElement(Quaternion q, int element)
- {
- switch (element)
- {
- case 0: return q.x;
- case 1: return q.y;
- case 2: return q.z;
- case 3: return q.w;
- default: return 0;
- }
- }
-
- public static uint CompressQuaternion(Quaternion q)
- {
-
-
-
- int largestIndex = LargestAbsoluteComponentIndex(new Vector4(q.x, q.y, q.z, q.w), out float _, out Vector3 withoutLargest);
-
-
-
-
-
-
- if (QuaternionElement(q, largestIndex) < 0)
- withoutLargest = -withoutLargest;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ushort aScaled = ScaleFloatToUShort(withoutLargest.x, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
- ushort bScaled = ScaleFloatToUShort(withoutLargest.y, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
- ushort cScaled = ScaleFloatToUShort(withoutLargest.z, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
-
-
-
-
-
- return (uint)(largestIndex << 30 | aScaled << 20 | bScaled << 10 | cScaled);
- }
-
-
-
- static Quaternion QuaternionNormalizeSafe(Quaternion value)
- {
-
- const float FLT_MIN_NORMAL = 1.175494351e-38F;
- Vector4 v = new Vector4(value.x, value.y, value.z, value.w);
- float length = Vector4.Dot(v, v);
- return length > FLT_MIN_NORMAL
- ? value.normalized
- : Quaternion.identity;
- }
-
- public static Quaternion DecompressQuaternion(uint data)
- {
-
- ushort cScaled = (ushort)(data & TenBitsMax);
-
- ushort bScaled = (ushort)((data >> 10) & TenBitsMax);
-
- ushort aScaled = (ushort)((data >> 20) & TenBitsMax);
-
- int largestIndex = (int)(data >> 30);
-
- float a = ScaleUShortToFloat(aScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
- float b = ScaleUShortToFloat(bScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
- float c = ScaleUShortToFloat(cScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
-
- float d = Mathf.Sqrt(1 - a*a - b*b - c*c);
-
- Vector4 value;
- switch (largestIndex)
- {
- case 0: value = new Vector4(d, a, b, c); break;
- case 1: value = new Vector4(a, d, b, c); break;
- case 2: value = new Vector4(a, b, d, c); break;
- default: value = new Vector4(a, b, c, d); break;
- }
-
-
-
-
-
- return QuaternionNormalizeSafe(new Quaternion(value.x, value.y, value.z, value.w));
- }
-
-
-
-
- public static void CompressVarUInt(NetworkWriter writer, ulong value)
- {
- if (value <= 240)
- {
- writer.Write((byte)value);
- return;
- }
- if (value <= 2287)
- {
- writer.Write((byte)(((value - 240) >> 8) + 241));
- writer.Write((byte)((value - 240) & 0xFF));
- return;
- }
- if (value <= 67823)
- {
- writer.Write((byte)249);
- writer.Write((byte)((value - 2288) >> 8));
- writer.Write((byte)((value - 2288) & 0xFF));
- return;
- }
- if (value <= 16777215)
- {
- writer.Write((byte)250);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- return;
- }
- if (value <= 4294967295)
- {
- writer.Write((byte)251);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- writer.Write((byte)((value >> 24) & 0xFF));
- return;
- }
- if (value <= 1099511627775)
- {
- writer.Write((byte)252);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- writer.Write((byte)((value >> 24) & 0xFF));
- writer.Write((byte)((value >> 32) & 0xFF));
- return;
- }
- if (value <= 281474976710655)
- {
- writer.Write((byte)253);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- writer.Write((byte)((value >> 24) & 0xFF));
- writer.Write((byte)((value >> 32) & 0xFF));
- writer.Write((byte)((value >> 40) & 0xFF));
- return;
- }
- if (value <= 72057594037927935)
- {
- writer.Write((byte)254);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- writer.Write((byte)((value >> 24) & 0xFF));
- writer.Write((byte)((value >> 32) & 0xFF));
- writer.Write((byte)((value >> 40) & 0xFF));
- writer.Write((byte)((value >> 48) & 0xFF));
- return;
- }
-
- {
- writer.Write((byte)255);
- writer.Write((byte)(value & 0xFF));
- writer.Write((byte)((value >> 8) & 0xFF));
- writer.Write((byte)((value >> 16) & 0xFF));
- writer.Write((byte)((value >> 24) & 0xFF));
- writer.Write((byte)((value >> 32) & 0xFF));
- writer.Write((byte)((value >> 40) & 0xFF));
- writer.Write((byte)((value >> 48) & 0xFF));
- writer.Write((byte)((value >> 56) & 0xFF));
- }
- }
-
- public static void CompressVarInt(NetworkWriter writer, long i)
- {
- ulong zigzagged = (ulong)((i >> 63) ^ (i << 1));
- CompressVarUInt(writer, zigzagged);
- }
-
- public static ulong DecompressVarUInt(NetworkReader reader)
- {
- byte a0 = reader.ReadByte();
- if (a0 < 241)
- {
- return a0;
- }
- byte a1 = reader.ReadByte();
- if (a0 >= 241 && a0 <= 248)
- {
- return 240 + ((a0 - (ulong)241) << 8) + a1;
- }
- byte a2 = reader.ReadByte();
- if (a0 == 249)
- {
- return 2288 + ((ulong)a1 << 8) + a2;
- }
- byte a3 = reader.ReadByte();
- if (a0 == 250)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16);
- }
- byte a4 = reader.ReadByte();
- if (a0 == 251)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24);
- }
- byte a5 = reader.ReadByte();
- if (a0 == 252)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32);
- }
- byte a6 = reader.ReadByte();
- if (a0 == 253)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40);
- }
- byte a7 = reader.ReadByte();
- if (a0 == 254)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48);
- }
- byte a8 = reader.ReadByte();
- if (a0 == 255)
- {
- return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56);
- }
- throw new IndexOutOfRangeException("DecompressVarInt failure: " + a0);
- }
-
- public static long DecompressVarInt(NetworkReader reader)
- {
- ulong data = DecompressVarUInt(reader);
- return ((long)(data >> 1)) ^ -((long)data & 1);
- }
- }
- }
|