mirror of
https://github.com/TechplexEngineer/plexview.git
synced 2026-07-28 06:22:14 +00:00
Initial commit
I wish I could figure out how to have PlexVie be out of the LibOMV tree but its just not working die to a DLL not found exception about libopenjpeg. (Yes the dll is in the bin folder) This will do for now
This commit is contained in:
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014, openmetaverse.org
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* - Neither the name of the openmetaverse.org nor the names
|
||||
* of its contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper around a byte array that allows bit to be packed and unpacked
|
||||
/// one at a time or by a variable amount. Useful for very tightly packed
|
||||
/// data like LayerData packets
|
||||
/// </summary>
|
||||
public class BitPack
|
||||
{
|
||||
/// <summary></summary>
|
||||
public byte[] Data;
|
||||
|
||||
/// <summary></summary>
|
||||
public int BytePos
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bytePos != 0 && bitPos == 0)
|
||||
return bytePos - 1;
|
||||
else
|
||||
return bytePos;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public int BitPos { get { return bitPos; } }
|
||||
|
||||
|
||||
private const int MAX_BITS = 8;
|
||||
private static readonly byte[] ON = new byte[] { 1 };
|
||||
private static readonly byte[] OFF = new byte[] { 0 };
|
||||
|
||||
private int bytePos;
|
||||
private int bitPos;
|
||||
private bool weAreBigEndian = !BitConverter.IsLittleEndian;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor, initialize the bit packer / bit unpacker
|
||||
/// with a byte array and starting position
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to pack bits in to or unpack from</param>
|
||||
/// <param name="pos">Starting position in the byte array</param>
|
||||
public BitPack(byte[] data, int pos)
|
||||
{
|
||||
Data = data;
|
||||
bytePos = pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack a floating point value in to the data
|
||||
/// </summary>
|
||||
/// <param name="data">Floating point value to pack</param>
|
||||
public void PackFloat(float data)
|
||||
{
|
||||
byte[] input = BitConverter.GetBytes(data);
|
||||
if (weAreBigEndian) Array.Reverse(input);
|
||||
PackBitArray(input, 32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack part or all of an integer in to the data
|
||||
/// </summary>
|
||||
/// <param name="data">Integer containing the data to pack</param>
|
||||
/// <param name="totalCount">Number of bits of the integer to pack</param>
|
||||
public void PackBits(int data, int totalCount)
|
||||
{
|
||||
byte[] input = BitConverter.GetBytes(data);
|
||||
if (weAreBigEndian) Array.Reverse(input);
|
||||
PackBitArray(input, totalCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack part or all of an unsigned integer in to the data
|
||||
/// </summary>
|
||||
/// <param name="data">Unsigned integer containing the data to pack</param>
|
||||
/// <param name="totalCount">Number of bits of the integer to pack</param>
|
||||
public void PackBits(uint data, int totalCount)
|
||||
{
|
||||
byte[] input = BitConverter.GetBytes(data);
|
||||
if (weAreBigEndian) Array.Reverse(input);
|
||||
PackBitArray(input, totalCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack a single bit in to the data
|
||||
/// </summary>
|
||||
/// <param name="bit">Bit to pack</param>
|
||||
public void PackBit(bool bit)
|
||||
{
|
||||
if (bit)
|
||||
PackBitArray(ON, 1);
|
||||
else
|
||||
PackBitArray(OFF, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="isSigned"></param>
|
||||
/// <param name="intBits"></param>
|
||||
/// <param name="fracBits"></param>
|
||||
public void PackFixed(float data, bool isSigned, int intBits, int fracBits)
|
||||
{
|
||||
int unsignedBits = intBits + fracBits;
|
||||
int totalBits = unsignedBits;
|
||||
int min, max;
|
||||
|
||||
if (isSigned)
|
||||
{
|
||||
totalBits++;
|
||||
min = 1 << intBits;
|
||||
min *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = 0;
|
||||
}
|
||||
|
||||
max = 1 << intBits;
|
||||
|
||||
float fixedVal = Utils.Clamp(data, (float)min, (float)max);
|
||||
if (isSigned) fixedVal += max;
|
||||
fixedVal *= 1 << fracBits;
|
||||
|
||||
if (totalBits <= 8)
|
||||
PackBits((uint)fixedVal, 8);
|
||||
else if (totalBits <= 16)
|
||||
PackBits((uint)fixedVal, 16);
|
||||
else if (totalBits <= 31)
|
||||
PackBits((uint)fixedVal, 32);
|
||||
else
|
||||
throw new Exception("Can't use fixed point packing for " + totalBits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public void PackUUID(UUID data)
|
||||
{
|
||||
byte[] bytes = data.GetBytes();
|
||||
|
||||
// Not sure if our PackBitArray function can handle 128-bit byte
|
||||
//arrays, so using this for now
|
||||
for (int i = 0; i < 16; i++)
|
||||
PackBits(bytes[i], 8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public void PackColor(Color4 data)
|
||||
{
|
||||
byte[] bytes = data.GetBytes();
|
||||
PackBitArray(bytes, 32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacking a floating point value from the data
|
||||
/// </summary>
|
||||
/// <returns>Unpacked floating point value</returns>
|
||||
public float UnpackFloat()
|
||||
{
|
||||
byte[] output = UnpackBitsArray(32);
|
||||
|
||||
if (weAreBigEndian) Array.Reverse(output);
|
||||
return BitConverter.ToSingle(output, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a variable number of bits from the data in to integer format
|
||||
/// </summary>
|
||||
/// <param name="totalCount">Number of bits to unpack</param>
|
||||
/// <returns>An integer containing the unpacked bits</returns>
|
||||
/// <remarks>This function is only useful up to 32 bits</remarks>
|
||||
public int UnpackBits(int totalCount)
|
||||
{
|
||||
byte[] output = UnpackBitsArray(totalCount);
|
||||
|
||||
if (weAreBigEndian) Array.Reverse(output);
|
||||
return BitConverter.ToInt32(output, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a variable number of bits from the data in to unsigned
|
||||
/// integer format
|
||||
/// </summary>
|
||||
/// <param name="totalCount">Number of bits to unpack</param>
|
||||
/// <returns>An unsigned integer containing the unpacked bits</returns>
|
||||
/// <remarks>This function is only useful up to 32 bits</remarks>
|
||||
public uint UnpackUBits(int totalCount)
|
||||
{
|
||||
byte[] output = UnpackBitsArray(totalCount);
|
||||
|
||||
if (weAreBigEndian) Array.Reverse(output);
|
||||
return BitConverter.ToUInt32(output, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a 16-bit signed integer
|
||||
/// </summary>
|
||||
/// <returns>16-bit signed integer</returns>
|
||||
public short UnpackShort()
|
||||
{
|
||||
return (short)UnpackBits(16);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a 16-bit unsigned integer
|
||||
/// </summary>
|
||||
/// <returns>16-bit unsigned integer</returns>
|
||||
public ushort UnpackUShort()
|
||||
{
|
||||
return (ushort)UnpackUBits(16);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a 32-bit signed integer
|
||||
/// </summary>
|
||||
/// <returns>32-bit signed integer</returns>
|
||||
public int UnpackInt()
|
||||
{
|
||||
return UnpackBits(32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack a 32-bit unsigned integer
|
||||
/// </summary>
|
||||
/// <returns>32-bit unsigned integer</returns>
|
||||
public uint UnpackUInt()
|
||||
{
|
||||
return UnpackUBits(32);
|
||||
}
|
||||
|
||||
public byte UnpackByte()
|
||||
{
|
||||
byte[] output = UnpackBitsArray(8);
|
||||
return output[0];
|
||||
}
|
||||
|
||||
public float UnpackFixed(bool signed, int intBits, int fracBits)
|
||||
{
|
||||
int minVal;
|
||||
int maxVal;
|
||||
int unsignedBits = intBits + fracBits;
|
||||
int totalBits = unsignedBits;
|
||||
float fixedVal;
|
||||
|
||||
if (signed)
|
||||
{
|
||||
totalBits++;
|
||||
|
||||
minVal = 1 << intBits;
|
||||
minVal *= -1;
|
||||
}
|
||||
maxVal = 1 << intBits;
|
||||
|
||||
if (totalBits <= 8)
|
||||
fixedVal = (float)UnpackByte();
|
||||
else if (totalBits <= 16)
|
||||
fixedVal = (float)UnpackUBits(16);
|
||||
else if (totalBits <= 31)
|
||||
fixedVal = (float)UnpackUBits(32);
|
||||
else
|
||||
return 0.0f;
|
||||
|
||||
fixedVal /= (float)(1 << fracBits);
|
||||
|
||||
if (signed) fixedVal -= (float)maxVal;
|
||||
|
||||
return fixedVal;
|
||||
}
|
||||
|
||||
public string UnpackString(int size)
|
||||
{
|
||||
if (bitPos != 0 || bytePos + size > Data.Length) throw new IndexOutOfRangeException();
|
||||
|
||||
string str = System.Text.UTF8Encoding.UTF8.GetString(Data, bytePos, size);
|
||||
bytePos += size;
|
||||
return str;
|
||||
}
|
||||
|
||||
public UUID UnpackUUID()
|
||||
{
|
||||
if (bitPos != 0) throw new IndexOutOfRangeException();
|
||||
|
||||
UUID val = new UUID(Data, bytePos);
|
||||
bytePos += 16;
|
||||
return val;
|
||||
}
|
||||
|
||||
private void PackBitArray(byte[] data, int totalCount)
|
||||
{
|
||||
int count = 0;
|
||||
int curBytePos = 0;
|
||||
int curBitPos = 0;
|
||||
|
||||
while (totalCount > 0)
|
||||
{
|
||||
if (totalCount > MAX_BITS)
|
||||
{
|
||||
count = MAX_BITS;
|
||||
totalCount -= MAX_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = totalCount;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
byte curBit = (byte)(0x80 >> bitPos);
|
||||
|
||||
if ((data[curBytePos] & (0x01 << (count - 1))) != 0)
|
||||
Data[bytePos] |= curBit;
|
||||
else
|
||||
Data[bytePos] &= (byte)~curBit;
|
||||
|
||||
--count;
|
||||
++bitPos;
|
||||
++curBitPos;
|
||||
|
||||
if (bitPos >= MAX_BITS)
|
||||
{
|
||||
bitPos = 0;
|
||||
++bytePos;
|
||||
}
|
||||
if (curBitPos >= MAX_BITS)
|
||||
{
|
||||
curBitPos = 0;
|
||||
++curBytePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] UnpackBitsArray(int totalCount)
|
||||
{
|
||||
int count = 0;
|
||||
byte[] output = new byte[4];
|
||||
int curBytePos = 0;
|
||||
int curBitPos = 0;
|
||||
|
||||
while (totalCount > 0)
|
||||
{
|
||||
if (totalCount > MAX_BITS)
|
||||
{
|
||||
count = MAX_BITS;
|
||||
totalCount -= MAX_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = totalCount;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
// Shift the previous bits
|
||||
output[curBytePos] <<= 1;
|
||||
|
||||
// Grab one bit
|
||||
if ((Data[bytePos] & (0x80 >> bitPos++)) != 0)
|
||||
++output[curBytePos];
|
||||
|
||||
--count;
|
||||
++curBitPos;
|
||||
|
||||
if (bitPos >= MAX_BITS)
|
||||
{
|
||||
bitPos = 0;
|
||||
++bytePos;
|
||||
}
|
||||
if (curBitPos >= MAX_BITS)
|
||||
{
|
||||
curBitPos = 0;
|
||||
++curBytePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user