/// <summary> /// Decompress position from the integers in the buffer, required bytes count: <see cref="PositionRequiredBytes"/> /// </summary> /// <param name="bytesStack">Buffer where position is pushed</param> /// <returns>Decompressed position</returns> public static Vector3 PopDecompressedPosition(this BytesStack bytesStack) { //Always use little-endian so compression and decompression are machines independent var intX = bytesStack.PopInt(PositionXRequiredBytes); var intY = bytesStack.PopInt(PositionYRequiredBytes); var intZ = bytesStack.PopInt(PositionZRequiredBytes); return(BitConverter.IsLittleEndian ? new Vector3(DecompressPositionX(intX), DecompressPositionY(intY), DecompressPositionZ(intZ)) : new Vector3(DecompressPositionX(SwapEndianness(intX)), DecompressPositionY(SwapEndianness(intY)), DecompressPositionZ(SwapEndianness(intZ)))); }
/// <summary> /// Decompress vector3 from the integers in the buffer /// </summary> /// <param name="bytesStack">Buffer where vector3 is pushed</param> /// <param name="minElementValue">Minimal value of the encoded vector3</param> /// <param name="maxElementValue">Maximal value of the encoded vector3</param> /// <param name="bytesPerElement">Bytes count that will be used per each element</param> /// <returns>Decompressed vector3</returns> public static Vector3 PopDecompressedVector3(this BytesStack bytesStack, float minElementValue, float maxElementValue, int bytesPerElement) { //Always use little-endian so compression and decompression are machines independent var intX = bytesStack.PopInt(bytesPerElement); var intY = bytesStack.PopInt(bytesPerElement); var intZ = bytesStack.PopInt(bytesPerElement); return(BitConverter.IsLittleEndian ? new Vector3(DecompressFloatFromInt(intX, minElementValue, maxElementValue, bytesPerElement), DecompressFloatFromInt(intY, minElementValue, maxElementValue, bytesPerElement), DecompressFloatFromInt(intZ, minElementValue, maxElementValue, bytesPerElement)) : new Vector3( DecompressFloatFromInt(SwapEndianness(intX), minElementValue, maxElementValue, bytesPerElement), DecompressFloatFromInt(SwapEndianness(intY), minElementValue, maxElementValue, bytesPerElement), DecompressFloatFromInt(SwapEndianness(intZ), minElementValue, maxElementValue, bytesPerElement))); }
/// <summary> /// Decompress color from the integers in the buffer /// </summary> /// <param name="bytesStack">Buffer where color is pushed</param> /// <param name="bytesPerElement">Bytes count that will be used per each element</param> /// <returns>Decompressed vector3</returns> public static Color PopDecompressedColor(this BytesStack bytesStack, int bytesPerElement) { //Always use little-endian so compression and decompression are machines independent var intR = bytesStack.PopInt(bytesPerElement); var intG = bytesStack.PopInt(bytesPerElement); var intB = bytesStack.PopInt(bytesPerElement); var intA = bytesStack.PopInt(bytesPerElement); return(BitConverter.IsLittleEndian ? new Color(DecompressFloatFromInt(intR, 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(intG, 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(intB, 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(intA, 0.0f, 1.0f, bytesPerElement)) : new Color( DecompressFloatFromInt(SwapEndianness(intR), 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(SwapEndianness(intG), 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(SwapEndianness(intB), 0.0f, 1.0f, bytesPerElement), DecompressFloatFromInt(SwapEndianness(intA), 0.0f, 1.0f, bytesPerElement))); }
/// <summary> /// Decompress rotation from the integers in the buffer, required bytes count: <see cref="RotationPrecision"/> /// </summary> /// <param name="bytesStack">Buffer where rotation is pushed</param> /// <returns>Decompressed rotation</returns> public static Quaternion PopDecompressedRotation(this BytesStack bytesStack) { // Read the index of the maximum element var maxIndex = bytesStack.Pop(); // Indexed 4-7 determine that maximum element is approximately equal to 1.0f and other elements are not encoded // Other elements are approximately equal to 0.0f; if (maxIndex >= 4 && maxIndex <= 7) { var x = (maxIndex == 4) ? 1f : 0f; var y = (maxIndex == 5) ? 1f : 0f; var z = (maxIndex == 6) ? 1f : 0f; var w = (maxIndex == 7) ? 1f : 0f; return(new Quaternion(x, y, z, w)); } // Read and decompress the "smallest three" values var a = DecompressFloatFromInt(bytesStack.PopInt(DefaultBytesForCompressedFloat), -1.0f, 1.0f, DefaultBytesForCompressedFloat); var b = DecompressFloatFromInt(bytesStack.PopInt(DefaultBytesForCompressedFloat), -1.0f, 1.0f, DefaultBytesForCompressedFloat); var c = DecompressFloatFromInt(bytesStack.PopInt(DefaultBytesForCompressedFloat), -1.0f, 1.0f, DefaultBytesForCompressedFloat); // Count the maximum value var d = Mathf.Sqrt(1f - (a * a + b * b + c * c)); // Reconstruct the quaternion from its elements if (maxIndex == 0) { return(new Quaternion(d, a, b, c)); } if (maxIndex == 1) { return(new Quaternion(a, d, b, c)); } if (maxIndex == 2) { return(new Quaternion(a, b, d, c)); } return(new Quaternion(a, b, c, d)); }
/// <summary> /// Pops the enum value from the bytes stack /// </summary> /// <param name="bytesStack">Buffer where enum is pushed</param> /// <typeparam name="T">Enum type</typeparam> /// <returns>Enum value decompressed from the bytes stack</returns> public static T PopEnum <T>(this BytesStack bytesStack) where T : IComparable, IConvertible, IFormattable { var intValue = bytesStack.PopInt(RequiredBytes <T>()); return((T)Enum.ToObject(typeof(T), intValue)); }