Beispiel #1
0
        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 / (float)quantize;
            float   mult     = ooq * (float)header.Range;
            float   addval   = mult * (float)(1 << (prequant - 1)) + header.DCOffset;

            if (group.PatchSize == 16)
            {
                for (int n = 0; n < 16 * 16; n++)
                {
                    block[n] = patches[CopyMatrix16[n]] * DequantizeTable16[n];
                }

                float[] ftemp = new float[16 * 16];

                for (int o = 0; o < 16; o++)
                {
                    IDCTColumn16(block, ftemp, o);
                }
                for (int o = 0; o < 16; o++)
                {
                    IDCTLine16(ftemp, block, o);
                }
            }
            else
            {
                for (int n = 0; n < 32 * 32; 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 void CreatePatch(BitPack output, float[] patchData, int x, int y)
        {
            if (patchData.Length != 16 * 16)
            {
                throw new ArgumentException("Patch data must be a 16x16 array");
            }

            TerrainPatch.Header header = PrescanPatch(patchData);
            header.QuantWBits = 136;
            header.PatchIDs   = (y & 0x1F);
            header.PatchIDs  += (x << 5);

            // NOTE: No idea what prequant and postquant should be or what they do
            int[] patch = CompressPatch(patchData, header, 10);
            int   wbits = EncodePatchHeader(output, header, patch);

            EncodePatch(output, patch, 0, wbits);
        }
 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
 {
     for (int n = 0; n < size * size; n++)
     {
         // ?
         var temp = bitpack.UnpackBits(1);
         if (temp != 0)
         {
             // Value or EOB
             temp = bitpack.UnpackBits(1);
             if (temp != 0)
             {
                 // Value
                 temp = bitpack.UnpackBits(1);
                 if (temp != 0)
                 {
                     // Negative
                     temp       = bitpack.UnpackBits((int)header.WordBits);
                     patches[n] = temp * -1;
                 }
                 else
                 {
                     // Positive
                     temp       = bitpack.UnpackBits((int)header.WordBits);
                     patches[n] = temp;
                 }
             }
             else
             {
                 // Set the rest to zero
                 // TODO: This might not be necessary
                 for (int o = n; o < size * size; o++)
                 {
                     patches[o] = 0;
                 }
                 break;
             }
         }
         else
         {
             patches[n] = 0;
         }
     }
 }
        /// <summary>
        /// Add a patch of terrain to a BitPacker
        /// </summary>
        /// <param name="output">BitPacker to write the patch to</param>
        /// <param name="heightmap">Heightmap of the simulator, must be a 256 *
        /// 256 float array</param>
        /// <param name="x">X offset of the patch to create, valid values are
        /// from 0 to 15</param>
        /// <param name="y">Y offset of the patch to create, valid values are
        /// from 0 to 15</param>
        public static void CreatePatchFromHeightmap(BitPack output, float[] heightmap, int x, int y)
        {
            if (heightmap.Length != 256 * 256)
            {
                throw new ArgumentException("Heightmap data must be 256x256");
            }

            if (x < 0 || x > 15 || y < 0 || y > 15)
            {
                throw new ArgumentException("X and Y patch offsets must be from 0 to 15");
            }

            TerrainPatch.Header header = PrescanPatch(heightmap, x, y);
            header.QuantWBits = 136;
            header.PatchIDs   = (y & 0x1F);
            header.PatchIDs  += (x << 5);

            // NOTE: No idea what prequant and postquant should be or what they do
            int[] patch = CompressPatch(heightmap, x, y, header, 10);
            int   wbits = EncodePatchHeader(output, header, patch);

            EncodePatch(output, patch, 0, wbits);
        }
        private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant)
        {
            float[] block    = new float[16 * 16];
            int     wordsize = prequant;
            float   oozrange = 1.0f / (float)header.Range;
            float   range    = (float)(1 << prequant);
            float   premult  = oozrange * range;
            float   sub      = (float)(1 << (prequant - 1)) + header.DCOffset * premult;

            header.QuantWBits  = wordsize - 2;
            header.QuantWBits |= (prequant - 2) << 4;

            int k = 0;

            for (int j = 0; j < 16; j++)
            {
                for (int i = 0; i < 16; i++)
                {
                    block[k++] = patchData[j, i] * premult - sub;
                }
            }

            float[] ftemp = new float[16 * 16];
            int[]   itemp = new int[16 * 16];

            for (int o = 0; o < 16; o++)
            {
                DCTLine16(block, ftemp, o);
            }
            for (int o = 0; o < 16; o++)
            {
                DCTColumn16(ftemp, itemp, o);
            }

            return(itemp);
        }
Beispiel #6
0
        public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
        {
            TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};

            // Quantized word bits
            if (header.QuantWBits == END_OF_PATCHES)
                return header;

            // DC offset
            header.DCOffset = bitpack.UnpackFloat();

            // Range
            header.Range = bitpack.UnpackBits(16);

            // Patch IDs (10 bits)
            header.PatchIDs = bitpack.UnpackBits(10);

            // Word bits
            header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);

            return header;
        }
Beispiel #7
0
        // Scan the height info we're returning and return a patch packet header for this patch.
        private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

            for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
            {
                for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
                {
                    float val = terrData[i, j];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = zmin;
            header.Range = (int)((zmax - zmin) + 1.0f);

            return header;
        }
Beispiel #8
0
        private static TerrainPatch.Header PrescanPatch(float[] patch)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

            for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
            {
                float val = patch[i];
                if (val > zmax) zmax = val;
                if (val < zmin) zmin = val;
            }

            header.DCOffset = zmin;
            header.Range = (int) ((zmax - zmin) + 1.0f);

            return header;
        }
        private static TerrainPatch.Header PrescanPatch(float[] heightmap, int patchX, int patchY, int RegionSizeX,
                                                        int RegionSizeY)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -32767;
            float zmin = 32767;

            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    float val = heightmap[j * RegionSizeX + i];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = (zmin);
            header.Range = (int)(((zmax - zmin)) + 1.0f);

            return header;
        }
Beispiel #10
0
        private static TerrainPatch.Header PrescanPatch(float[] heightmap, int patchX, int patchY)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    float val = heightmap[j * 256 + i];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = zmin;
            header.Range = (int)((zmax - zmin) + 1.0f);

            return header;
        }
Beispiel #11
0
        private static TerrainPatch.Header PrescanPatch(float[,] patch)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

            for (int j = 0; j < 16; j++)
            {
                for (int i = 0; i < 16; i++)
                {
                    float val = patch[j, i];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = zmin;
            header.Range = (int)((zmax - zmin) + 1.0f);

            return header;
        }
        private static TerrainPatch.Header PrescanPatch(short[] heightmap, int patchX, int patchY, int RegionSizeX,
            int RegionSizeY)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            short zmax = -32767;
            short zmin = 32767;
            const float iscale = 1.0f/Constants.TerrainCompression;

            for (int j = patchY*16; j < (patchY + 1)*16; j++)
            {
                for (int i = patchX*16; i < (patchX + 1)*16; i++)
                {
                    short val = heightmap[j*RegionSizeX + i];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = (zmin)*iscale;
            header.Range = (int) (((zmax - zmin))*iscale + 1.0f);

            return header;
        }
        // Scan the height info we're returning and return a patch packet header for this patch.
        private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = float.MinValue;
            float zmin = float.MaxValue;

            int startx = patchX * Constants.TerrainPatchSize;
            int starty = patchY * Constants.TerrainPatchSize;

            for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
            {
                for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
                {
                    float val = terrData[i, j];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = zmin;
            frange = ((zmax - zmin) + 1.0f);
            header.Range = (int)frange;

            return header;
        }
Beispiel #14
0
        private void DecompressLand(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
        {
            int x;
            int y;

            int[] patches = new int[32 * 32];
            int   count   = 0;

            while (true)
            {
                TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack);

                if (header.QuantWBits == TerrainCompressor.END_OF_PATCHES)
                {
                    break;
                }

                x = header.X;
                y = header.Y;

                if (x >= TerrainCompressor.PATCHES_PER_EDGE || y >= TerrainCompressor.PATCHES_PER_EDGE)
                {
                    Logger.Log(String.Format(
                                   "Invalid LayerData land packet, x={0}, y={1}, dc_offset={2}, range={3}, quant_wbits={4}, patchids={5}, count={6}",
                                   x, y, header.DCOffset, header.Range, header.QuantWBits, header.PatchIDs, count),
                               Helpers.LogLevel.Warning, Client);
                    return;
                }

                // Decode this patch
                TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);

                // Decompress this patch
                float[] heightmap = TerrainCompressor.DecompressPatch(patches, header, group);

                count++;

                if (OnLandPatch != null)
                {
                    try { OnLandPatch(simulator, x, y, group.PatchSize, heightmap); }
                    catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
                }

                if (Client.Settings.STORE_LAND_PATCHES)
                {
                    lock (SimPatches)
                    {
                        if (!SimPatches.ContainsKey(simulator.Handle))
                        {
                            SimPatches.Add(simulator.Handle, new TerrainPatch[16 * 16]);
                        }

                        TerrainPatch patch = new TerrainPatch();
                        patch.Data = heightmap;
                        patch.X    = x;
                        patch.Y    = y;

                        SimPatches[simulator.Handle][y * 16 + x] = patch;
                    }
                }
            }
        }
        private static TerrainPatch.Header PrescanPatch(float[] heightmap, int patchX, int patchY, int RegionSizeX, int RegionSizeY)
        {
            TerrainPatch.Header header = new TerrainPatch.Header();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

//            int sqrt = (int)Math.Sqrt(heightmap.Length);
            for (int j = patchY * Constants.TerrainPatchSize; j < ((patchY >= (RegionSizeY / Constants.TerrainPatchSize) ? (RegionSizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY) + 1) * Constants.TerrainPatchSize; j++)
            {
                for (int i = patchX * Constants.TerrainPatchSize; i < ((patchX >= (RegionSizeX / Constants.TerrainPatchSize) ? (RegionSizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX) + 1) * Constants.TerrainPatchSize; i++)
                {
                    float val = heightmap[j * RegionSizeX + i];
                    if (val > zmax) zmax = val;
                    if (val < zmin) zmin = val;
                }
            }

            header.DCOffset = zmin;
            header.Range = (int)((zmax - zmin) + 1.0f);

            return header;
        }