/// <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); }
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); }
public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group) { float[] block = new float[group.PatchSize * group.PatchSize]; float[] output = new float[group.PatchSize * group.PatchSize]; int prequant = (header.QuantWBits >> 4) + 2; int quantize = 1 << prequant; float ooq = 1.0f / quantize; float mult = ooq * header.Range; float addval = mult * (1 << (prequant - 1)) + header.DCOffset; if (group.PatchSize == Constants.TerrainPatchSize) { for (int n = 0; n < Constants.TerrainPatchSize * Constants.TerrainPatchSize; n++) { block[n] = patches[CopyMatrix16[n]] * DequantizeTable16[n]; } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; for (int o = 0; o < Constants.TerrainPatchSize; o++) { IDCTColumn16(block, ftemp, o); } for (int o = 0; o < Constants.TerrainPatchSize; o++) { IDCTLine16(ftemp, block, o); } } else { for (int n = 0; n < Constants.TerrainPatchSize * 2 * Constants.TerrainPatchSize * 2; n++) { block[n] = patches[CopyMatrix32[n]] * DequantizeTable32[n]; } Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error); } for (int j = 0; j < block.Length; j++) { output[j] = block[j] * mult + addval; } return(output); }
public static LayerDataPacket CreateLandPacket(List <PatchInfo> ps, byte type) { LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } }; TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize }; byte[] outdata = new byte[1500]; byte[] indata = BitConverter.GetBytes((ushort)header.Stride); if (!BitConverter.IsLittleEndian) { Array.Reverse(indata); } outdata[0] = indata[0]; outdata[1] = indata[1]; outdata[2] = (byte)header.PatchSize; outdata[3] = type; int outBitPos = 32; PatchInfo eop = new PatchInfo(); eop.PackedData = new byte[] { END_OF_PATCHES }; eop.BitLength = 8; ps.Add(eop); foreach (PatchInfo pi in ps) { int count = 0; int curBytePos = 0; int bitCount = pi.BitLength; /* this bit pack method has a slight variance allowing it to directly accept BitPacked data */ while (bitCount > 0) { count = bitCount; if (count > 8) { count = 8; } byte srcBits = pi.PackedData[curBytePos]; while (count-- > 0) { byte curBitMask = (byte)(0x80 >> (outBitPos % 8)); if ((srcBits & 0x80) != 0) { outdata[outBitPos / 8] |= curBitMask; } else { outdata[outBitPos / 8] &= (byte)~curBitMask; } ++outBitPos; srcBits <<= 1; } ++curBytePos; if (bitCount > 8) { bitCount -= 8; } else { bitCount = 0; } } } layer.LayerData.Data = new byte[(outBitPos + 7) / 8]; Buffer.BlockCopy(outdata, 0, layer.LayerData.Data, 0, (outBitPos + 7) / 8); return(layer); }