public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int RegionSizeX, int RegionSizeY) { LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } }; TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize }; // Should be enough to fit even the most poorly packed data byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; BitPack bitpack = new BitPack(data, 0); bitpack.PackBits(header.Stride, 16); bitpack.PackBits(header.PatchSize, 8); bitpack.PackBits(type, 8); foreach (TerrainPatch t in patches) { CreatePatch(bitpack, t.Data, t.X, t.Y, RegionSizeX, RegionSizeY); } bitpack.PackBits(END_OF_PATCHES, 8); layer.LayerData.Data = new byte[bitpack.BytePos + 1]; Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); return(layer); }
/// <summary> /// Creates a LayerData packet for compressed land data given a full /// simulator heightmap and an array of indices of patches to compress /// </summary> /// <param name="heightmap"> /// A 256 * 256 array of floating point values /// specifying the height at each meter in the simulator /// </param> /// <param name="x"> /// Array of indexes in the 16x16 grid of patches /// for this simulator. For example if 1 and 17 are specified, patches /// x=1,y=0 and x=1,y=1 are sent /// </param> /// <param name="y"> /// Array of indexes in the 16x16 grid of patches /// for this simulator. For example if 1 and 17 are specified, patches /// x=1,y=0 and x=1,y=1 are sent /// </param> /// <param name="type"></param> /// <param name="RegionSizeX"></param> /// <param name="RegionSizeY"></param> /// <returns></returns> public static LayerDataPacket CreateLandPacket(short[] heightmap, int[] x, int[] y, byte type, int RegionSizeX, int RegionSizeY) { LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } }; TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize }; byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; BitPack bitpack = new BitPack(data, 0); bitpack.PackBits(header.Stride, 16); bitpack.PackBits(header.PatchSize, 8); bitpack.PackBits(type, 8); for (int i = 0; i < x.Length; i++) { CreatePatchFromHeightmap(bitpack, heightmap, x[i], y[i], RegionSizeX, RegionSizeY); } bitpack.PackBits(END_OF_PATCHES, 8); layer.LayerData.Data = new byte[bitpack.BytePos + 1]; Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); return(layer); }
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, int RegionSizeX, int RegionSizeY, int wbits) { // better check if (wbits > 17) { wbits = 16; } else if (wbits < 3) { wbits = 3; } header.QuantWBits &= 0xf0; header.QuantWBits |= (wbits - 2); output.PackBits(header.QuantWBits, 8); output.PackFloat(header.DCOffset); output.PackBits(header.Range, 16); if (RegionSizeX > Constants.RegionSize || RegionSizeY > Constants.RegionSize) { output.PackBits(header.PatchIDs, 32); } else { output.PackBits(header.PatchIDs, 10); } return(wbits); }
public void BitPacking() { byte[] packedBytes = new byte[12]; BitPack bitpacker = new BitPack(packedBytes, 0); bitpacker.PackBits(0x0ABBCCDD, 32); bitpacker.PackBits(25, 5); bitpacker.PackFloat(123.321f); bitpacker.PackBits(1000, 16); bitpacker = new BitPack(packedBytes, 0); int b = bitpacker.UnpackBits(32); Assert.IsTrue(b == 0x0ABBCCDD, "Unpacked " + b + " instead of 2864434397"); b = bitpacker.UnpackBits(5); Assert.IsTrue(b == 25, "Unpacked " + b + " instead of 25"); float f = bitpacker.UnpackFloat(); Assert.IsTrue(f == 123.321f, "Unpacked " + f + " instead of 123.321"); b = bitpacker.UnpackBits(16); Assert.IsTrue(b == 1000, "Unpacked " + b + " instead of 1000"); }
private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) { int maxwbitssize = (1 << wbits) - 1; if (postquant > Constants.TerrainPatchSize * Constants.TerrainPatchSize || postquant < 0) { Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); return; } if (postquant != 0) { patch[Constants.TerrainPatchSize * Constants.TerrainPatchSize - postquant] = 0; } for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++) { int temp = patch[i]; if (temp == 0) { bool eob = true; for (int j = i; j < Constants.TerrainPatchSize * Constants.TerrainPatchSize - postquant; j++) { if (patch[j] != 0) { eob = false; break; } } if (eob) { output.PackBits(ZERO_EOB, 2); return; } output.PackBits(ZERO_CODE, 1); } else { if (temp < 0) { temp *= -1; if (temp > maxwbitssize) { temp = maxwbitssize; } output.PackBits(NEGATIVE_VALUE, 3); output.PackBits(temp, wbits); } else { if (temp > maxwbitssize) { temp = maxwbitssize; } output.PackBits(POSITIVE_VALUE, 3); output.PackBits(temp, wbits); } } } }
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, int RegionSizeX, int RegionSizeY, int wbits) { /* * int temp; * int wbits = (header.QuantWBits & 0x0f) + 2; * uint maxWbits = (uint)wbits + 5; * uint minWbits = ((uint)wbits >> 1); * int wbitsMaxValue; */ // goal is to determ minimum number of bits to use so all data fits /* * wbits = (int)minWbits; * wbitsMaxValue = (1 << wbits); * * for (int i = 0; i < patch.Length; i++) * { * temp = patch[i]; * if (temp != 0) * { * // Get the absolute value * if (temp < 0) temp *= -1; * * no coments.. * * for (int j = (int)maxWbits; j > (int)minWbits; j--) * { * if ((temp & (1 << j)) != 0) * { * if (j > wbits) wbits = j; * break; * } * } * * while (temp > wbitsMaxValue) * { * wbits++; * if (wbits == maxWbits) * goto Done; * wbitsMaxValue = 1 << wbits; * } * } * } * * Done: * * // wbits += 1; */ // better check if (wbits > 17) { wbits = 16; } else if (wbits < 3) { wbits = 3; } header.QuantWBits &= 0xf0; header.QuantWBits |= (wbits - 2); output.PackBits(header.QuantWBits, 8); output.PackFloat(header.DCOffset); output.PackBits(header.Range, 16); if (RegionSizeX > Constants.RegionSize || RegionSizeY > Constants.RegionSize) { output.PackBits(header.PatchIDs, 32); } else { output.PackBits(header.PatchIDs, 10); } return(wbits); }