3using System.Runtime.CompilerServices;
17 public static int LargestAbsoluteComponentIndex(Vector4 value, out
float largestAbs, out Vector3 withoutLargest)
20 Vector4 abs =
new Vector4(Mathf.Abs(value.x), Mathf.Abs(value.y), Mathf.Abs(value.z), Mathf.Abs(value.w));
24 withoutLargest =
new Vector3(value.y, value.z, value.w);
31 if (abs.y > largestAbs)
35 withoutLargest =
new Vector3(value.x, value.z, value.w);
37 if (abs.z > largestAbs)
41 withoutLargest =
new Vector3(value.x, value.y, value.w);
43 if (abs.w > largestAbs)
47 withoutLargest =
new Vector3(value.x, value.y, value.z);
55 public static ushort ScaleFloatToUShort(
float value,
float minValue,
float maxValue, ushort minTarget, ushort maxTarget)
59 int targetRange = maxTarget - minTarget;
60 float valueRange = maxValue - minValue;
61 float valueRelative = value - minValue;
62 return (ushort)(minTarget + (ushort)(valueRelative / valueRange * targetRange));
67 public static float ScaleUShortToFloat(ushort value, ushort minValue, ushort maxValue,
float minTarget,
float maxTarget)
70 float targetRange = maxTarget - minTarget;
71 ushort valueRange = (ushort)(maxValue - minValue);
72 ushort valueRelative = (ushort)(value - minValue);
73 return minTarget + (valueRelative / (float)valueRange * targetRange);
76 const float QuaternionMinRange = -0.707107f;
77 const float QuaternionMaxRange = 0.707107f;
78 const ushort TenBitsMax = 0x3FF;
81 [MethodImpl(MethodImplOptions.AggressiveInlining)]
82 static float QuaternionElement(Quaternion q,
int element)
95 public static uint CompressQuaternion(Quaternion q)
101 int largestIndex = LargestAbsoluteComponentIndex(
new Vector4(q.x, q.y, q.z, q.w), out
float _, out Vector3 withoutLargest);
110 if (QuaternionElement(q, largestIndex) < 0)
111 withoutLargest = -withoutLargest;
127 ushort aScaled = ScaleFloatToUShort(withoutLargest.x, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
128 ushort bScaled = ScaleFloatToUShort(withoutLargest.y, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
129 ushort cScaled = ScaleFloatToUShort(withoutLargest.z, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
136 return (uint)(largestIndex << 30 | aScaled << 20 | bScaled << 10 | cScaled);
142 [MethodImpl(MethodImplOptions.AggressiveInlining)]
143 static Quaternion QuaternionNormalizeSafe(Quaternion value)
146 const float FLT_MIN_NORMAL = 1.175494351e-38F;
148 Vector4 v =
new Vector4(value.x, value.y, value.z, value.w);
149 float length = Vector4.Dot(v, v);
150 return length > FLT_MIN_NORMAL
152 : Quaternion.identity;
156 public static Quaternion DecompressQuaternion(uint data)
159 ushort cScaled = (ushort)(data & TenBitsMax);
162 ushort bScaled = (ushort)((data >> 10) & TenBitsMax);
165 ushort aScaled = (ushort)((data >> 20) & TenBitsMax);
168 int largestIndex = (int)(data >> 30);
171 float a = ScaleUShortToFloat(aScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
172 float b = ScaleUShortToFloat(bScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
173 float c = ScaleUShortToFloat(cScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
176 float d = Mathf.Sqrt(1 - a*a - b*b - c*c);
180 switch (largestIndex)
182 case 0: value =
new Vector4(d, a, b, c);
break;
183 case 1: value =
new Vector4(a, d, b, c);
break;
184 case 2: value =
new Vector4(a, b, d, c);
break;
185 default: value =
new Vector4(a, b, c, d);
break;
193 return QuaternionNormalizeSafe(
new Quaternion(value.x, value.y, value.z, value.w));
200 public static void CompressVarUInt(
NetworkWriter writer, ulong value)
204 writer.WriteByte((
byte)value);
209 writer.WriteByte((
byte)(((value - 240) >> 8) + 241));
210 writer.WriteByte((
byte)((value - 240) & 0xFF));
215 writer.WriteByte((
byte)249);
216 writer.WriteByte((
byte)((value - 2288) >> 8));
217 writer.WriteByte((
byte)((value - 2288) & 0xFF));
220 if (value <= 16777215)
222 writer.WriteByte((
byte)250);
223 writer.WriteByte((
byte)(value & 0xFF));
224 writer.WriteByte((
byte)((value >> 8) & 0xFF));
225 writer.WriteByte((
byte)((value >> 16) & 0xFF));
228 if (value <= 4294967295)
230 writer.WriteByte((
byte)251);
231 writer.WriteByte((
byte)(value & 0xFF));
232 writer.WriteByte((
byte)((value >> 8) & 0xFF));
233 writer.WriteByte((
byte)((value >> 16) & 0xFF));
234 writer.WriteByte((
byte)((value >> 24) & 0xFF));
237 if (value <= 1099511627775)
239 writer.WriteByte((
byte)252);
240 writer.WriteByte((
byte)(value & 0xFF));
241 writer.WriteByte((
byte)((value >> 8) & 0xFF));
242 writer.WriteByte((
byte)((value >> 16) & 0xFF));
243 writer.WriteByte((
byte)((value >> 24) & 0xFF));
244 writer.WriteByte((
byte)((value >> 32) & 0xFF));
247 if (value <= 281474976710655)
249 writer.WriteByte((
byte)253);
250 writer.WriteByte((
byte)(value & 0xFF));
251 writer.WriteByte((
byte)((value >> 8) & 0xFF));
252 writer.WriteByte((
byte)((value >> 16) & 0xFF));
253 writer.WriteByte((
byte)((value >> 24) & 0xFF));
254 writer.WriteByte((
byte)((value >> 32) & 0xFF));
255 writer.WriteByte((
byte)((value >> 40) & 0xFF));
258 if (value <= 72057594037927935)
260 writer.WriteByte((
byte)254);
261 writer.WriteByte((
byte)(value & 0xFF));
262 writer.WriteByte((
byte)((value >> 8) & 0xFF));
263 writer.WriteByte((
byte)((value >> 16) & 0xFF));
264 writer.WriteByte((
byte)((value >> 24) & 0xFF));
265 writer.WriteByte((
byte)((value >> 32) & 0xFF));
266 writer.WriteByte((
byte)((value >> 40) & 0xFF));
267 writer.WriteByte((
byte)((value >> 48) & 0xFF));
273 writer.WriteByte((
byte)255);
274 writer.WriteByte((
byte)(value & 0xFF));
275 writer.WriteByte((
byte)((value >> 8) & 0xFF));
276 writer.WriteByte((
byte)((value >> 16) & 0xFF));
277 writer.WriteByte((
byte)((value >> 24) & 0xFF));
278 writer.WriteByte((
byte)((value >> 32) & 0xFF));
279 writer.WriteByte((
byte)((value >> 40) & 0xFF));
280 writer.WriteByte((
byte)((value >> 48) & 0xFF));
281 writer.WriteByte((
byte)((value >> 56) & 0xFF));
286 [MethodImpl(MethodImplOptions.AggressiveInlining)]
287 public static void CompressVarInt(
NetworkWriter writer,
long i)
289 ulong zigzagged = (ulong)((i >> 63) ^ (i << 1));
290 CompressVarUInt(writer, zigzagged);
296 byte a0 = reader.ReadByte();
302 byte a1 = reader.ReadByte();
305 return 240 + ((a0 - (ulong)241) << 8) + a1;
308 byte a2 = reader.ReadByte();
311 return 2288 + ((ulong)a1 << 8) + a2;
314 byte a3 = reader.ReadByte();
317 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16);
320 byte a4 = reader.ReadByte();
323 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24);
326 byte a5 = reader.ReadByte();
329 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32);
332 byte a6 = reader.ReadByte();
335 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40);
338 byte a7 = reader.ReadByte();
341 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48);
344 byte a8 = reader.ReadByte();
347 return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56);
350 throw new IndexOutOfRangeException($
"DecompressVarInt failure: {a0}");
354 [MethodImpl(MethodImplOptions.AggressiveInlining)]
357 ulong data = DecompressVarUInt(reader);
358 return ((
long)(data >> 1)) ^ -((long)data & 1);
Functions to Compress Quaternions and Floats
Network Reader for most simple types like floats, ints, buffers, structs, etc. Use NetworkReaderPool....
Network Writer for most simple types like floats, ints, buffers, structs, etc. Use NetworkWriterPool....