Esempio n. 1
0
        /// <summary>
        /// Compress vector3 to integers and push it to the buffer
        /// </summary>
        /// <param name="bytesStack">Buffer where vector3 will be pushed</param>
        /// <param name="color">Vector3 to be compressed and 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>
        public static void PushCompressedVector3(this BytesStack bytesStack, Vector3 color, float minElementValue,
                                                 float maxElementValue, int bytesPerElement)
        {
            //Reverse order when writing to stack
            //Always use little-endian so compression and decompression are machines independent
            var z = CompressFloatToInt(color.z, minElementValue, maxElementValue, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                z = SwapEndianness(z);
            }
            bytesStack.PushInt(z, bytesPerElement);

            var y = CompressFloatToInt(color.y, minElementValue, maxElementValue, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                y = SwapEndianness(y);
            }
            bytesStack.PushInt(y, bytesPerElement);

            var x = CompressFloatToInt(color.x, minElementValue, maxElementValue, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                x = SwapEndianness(x);
            }
            bytesStack.PushInt(x, bytesPerElement);
        }
Esempio n. 2
0
        /// <summary>
        /// Compress position to integers and push it to the buffer, required bytes count: <see cref="PositionRequiredBytes"/>
        /// </summary>
        /// <param name="bytesStack">Buffer where position will be pushed</param>
        /// <param name="position">Position to be compressed and pushed</param>
        public static void PushCompressedPosition(this BytesStack bytesStack, Vector3 position)
        {
            //Reverse order when writing to stack
            //Always use little-endian so compression and decompression are machines independent
            var z = CompressPositionZ(position.z);

            if (!BitConverter.IsLittleEndian)
            {
                z = SwapEndianness(z);
            }
            bytesStack.PushInt(z, PositionZRequiredBytes);

            var y = CompressPositionY(position.y);

            if (!BitConverter.IsLittleEndian)
            {
                y = SwapEndianness(y);
            }
            bytesStack.PushInt(y, PositionYRequiredBytes);

            var x = CompressPositionX(position.x);

            if (!BitConverter.IsLittleEndian)
            {
                x = SwapEndianness(x);
            }
            bytesStack.PushInt(x, PositionXRequiredBytes);
        }
Esempio n. 3
0
        /// <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))));
        }
Esempio n. 4
0
        /// <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)));
        }
Esempio n. 5
0
        /// <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)));
        }
Esempio n. 6
0
        /// <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));
        }
Esempio n. 7
0
        /// <summary>
        /// Compress color to integers and push it to the buffer
        /// </summary>
        /// <param name="bytesStack">Buffer where color will be pushed</param>
        /// <param name="color">Color to be compressed and pushed</param>
        /// <param name="bytesPerElement">Bytes count that will be used per each element</param>
        public static void PushCompressedColor(this BytesStack bytesStack, Color color, int bytesPerElement)
        {
            //Reverse order when writing to stack
            //Always use little-endian so compression and decompression are machines independent
            var a = CompressFloatToInt(color.a, 0.0f, 1.0f, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                a = SwapEndianness(a);
            }
            bytesStack.PushInt(a, bytesPerElement);

            var b = CompressFloatToInt(color.b, 0.0f, 1.0f, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                b = SwapEndianness(b);
            }
            bytesStack.PushInt(b, bytesPerElement);

            var g = CompressFloatToInt(color.g, 0.0f, 1.0f, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                g = SwapEndianness(g);
            }
            bytesStack.PushInt(g, bytesPerElement);

            var r = CompressFloatToInt(color.r, 0.0f, 1.0f, bytesPerElement);

            if (!BitConverter.IsLittleEndian)
            {
                r = SwapEndianness(r);
            }
            bytesStack.PushInt(r, bytesPerElement);
        }
Esempio n. 8
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="addressKey">Address key defining where message should be passed</param>
 /// <param name="content">The content of message</param>
 /// <param name="messageType">Type defining how message should be delivered</param>
 public Message(string addressKey, BytesStack content, MessageType messageType)
 {
     AddressKey = addressKey;
     Content    = content;
     Type       = messageType;
 }
Esempio n. 9
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="content">The content of message</param>
 public Message(BytesStack content)
 {
     Content = content;
 }
Esempio n. 10
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="original">Original stack from where data will be copied</param>
 public BytesStack(BytesStack original) : this(original.GetDataCopy(), false)
 {
 }
Esempio n. 11
0
        /// <summary>
        /// Compress rotation to integers and push it to the buffer, required bytes count: <see cref="RotationPrecision"/>
        /// </summary>
        /// <param name="bytesStack">Buffer where rotation will be pushed</param>
        /// <param name="rotation">Rotation to be compressed and pushed</param>
        public static void PushCompressedRotation(this BytesStack bytesStack, Quaternion rotation)
        {
            //Algorithm based on the "smallest three" method described at:
            //http://gafferongames.com/networked-physics/snapshot-compression/
            var maxIndex = (byte)0;
            var maxValue = float.MinValue;
            var sign     = 1f;

            // Find the maximum element in the quaternion
            for (var i = 0; i < 4; i++)
            {
                var element = rotation[i];
                var abs     = Mathf.Abs(rotation[i]);
                if (!(abs > maxValue))
                {
                    continue;
                }
                // Maximum element is always compressed as positive, all other elements are negated if needed
                sign     = (element < 0) ? -1 : 1;
                maxIndex = (byte)i;
                maxValue = abs;
            }

            // If the maximum element is approximately equal to 1.0f all other elements are approximately equal to 0.0f and does not have to be encoded
            if (Mathf.Approximately(maxValue, 1.0f))
            {
                //Use 4-7 indexes to determine which element is maximum and it is approximately equal to 1.0f
                bytesStack.PushInt(maxIndex + 4, 1);
                return;
            }

            //Reverse order when writing to stack
            // Compress and encode only smallest three Quaternion components as little endian integers
            if (maxIndex != 3)
            {
                var w = CompressFloatToInt(rotation.w * sign, -1.0f, 1.0f, DefaultBytesForCompressedFloat);
                if (!BitConverter.IsLittleEndian)
                {
                    w = SwapEndianness(w);
                }
                bytesStack.PushInt(w, DefaultBytesForCompressedFloat);
            }

            if (maxIndex != 2)
            {
                var z = CompressFloatToInt(rotation.z * sign, -1.0f, 1.0f, DefaultBytesForCompressedFloat);
                if (!BitConverter.IsLittleEndian)
                {
                    z = SwapEndianness(z);
                }
                bytesStack.PushInt(z, DefaultBytesForCompressedFloat);
            }

            if (maxIndex != 1)
            {
                var y = CompressFloatToInt(rotation.y * sign, -1.0f, 1.0f, DefaultBytesForCompressedFloat);
                if (!BitConverter.IsLittleEndian)
                {
                    y = SwapEndianness(y);
                }
                bytesStack.PushInt(y, DefaultBytesForCompressedFloat);
            }

            if (maxIndex != 0)
            {
                var x = CompressFloatToInt(rotation.x * sign, -1.0f, 1.0f, DefaultBytesForCompressedFloat);
                if (!BitConverter.IsLittleEndian)
                {
                    x = SwapEndianness(x);
                }
                bytesStack.PushInt(x, DefaultBytesForCompressedFloat);
            }

            bytesStack.PushInt(BitConverter.IsLittleEndian ? maxIndex : SwapEndianness(maxIndex), 1);
        }
Esempio n. 12
0
        /// <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));
        }
Esempio n. 13
0
 /// <summary>
 /// Pushes the enum integer value with minimum required bytes
 /// </summary>
 /// <param name="bytesStack">Buffer where enum is pushed</param>
 /// <param name="intValue">Enum value casted to integer</param>
 /// <typeparam name="T">Enum type</typeparam>
 public static void PushEnum <T>(this BytesStack bytesStack, int intValue)
     where T : IComparable, IConvertible, IFormattable
 {
     bytesStack.PushInt(intValue, RequiredBytes <T>());
 }