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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }