public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size) { for (int n = 0; n < size * size; n++) { // ? int 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; } } }
private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int wordsize = (prequant - 2) & 0x0f; float oozrange = 1.0f / header.Range; float range = (1 << prequant); float premult = oozrange * range; float sub = (1 << (prequant - 1)) + header.DCOffset * premult; header.QuantWBits = wordsize; header.QuantWBits |= wordsize << 4; int k = 0; for (int j = 0; j < Constants.TerrainPatchSize; j++) { for (int i = 0; i < Constants.TerrainPatchSize; i++) { block[k++] = patchData[j * Constants.TerrainPatchSize + i] * premult - sub; } } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] itemp = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int maxWbits = prequant + 5; wbits = (prequant >> 1); for (int o = 0; o < Constants.TerrainPatchSize; o++) { DCTLine16(block, ftemp, o); } for (int o = 0; o < Constants.TerrainPatchSize; o++) { wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); } return(itemp); }
/// <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, short[] heightmap, int x, int y, int RegionSizeX, int RegionSizeY) { TerrainPatch.Header header = PrescanPatch(heightmap, x, y, RegionSizeX, RegionSizeY); header.QuantWBits = 136; if (RegionSizeX > Constants.RegionSize || RegionSizeY > Constants.RegionSize) { header.PatchIDs = (y & 0xFFFF); header.PatchIDs += (x << 16); } else { header.PatchIDs = (y & 0x1F); header.PatchIDs += (x << 5); } // NOTE: No idea what prequant and postquant should be or what they do int wbits; int[] patch = CompressPatch(heightmap, x, y, header, 10, RegionSizeX, RegionSizeY, out wbits); wbits = EncodePatchHeader(output, header, patch, RegionSizeX, RegionSizeY, wbits); EncodePatch(output, patch, 0, wbits); }
// Unused: left for historical reference. public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY) { TerrainPatch.Header header = PrescanPatch(patchData); header.QuantWBits = 136; if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) { header.PatchIDs = (y & 0xFFFF); header.PatchIDs += (x << 16); } else { header.PatchIDs = (y & 0x1F); header.PatchIDs += (x << 5); } // NOTE: No idea what prequant and postquant should be or what they do int wbits; int[] patch = CompressPatch(patchData, header, 10, out wbits); wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); EncodePatch(output, patch, 0, wbits); }
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 int[] CompressPatch(short[] heightmap, int patchX, int patchY, TerrainPatch.Header header, int prequant, int RegionSizeX, int RegionSizeY, out int wbits) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int wordsize = prequant; float oozrange = 1.0f / header.Range; float range = (1 << prequant); float premult = oozrange * range; float sub = (1 << (prequant - 1)) + header.DCOffset * premult; header.QuantWBits = wordsize - 2; header.QuantWBits |= (prequant - 2) << 4; int k = 0; premult /= Constants.TerrainCompression; // put here short to float factor 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++) { block[k++] = (heightmap[j * RegionSizeX + i]) * premult - sub; } } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] itemp = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int maxWbits = prequant + 5; wbits = (prequant >> 1); for (int o = 0; o < Constants.TerrainPatchSize; o++) { DCTLine16(block, ftemp, o); } for (int o = 0; o < Constants.TerrainPatchSize; o++) { wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); } return(itemp); }
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); }
private static int[] CompressPatch(HeightMapTerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, int prequant, out int wbits) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int wordsize = prequant; float oozrange = 1.0f / header.Range; float range = (1 << prequant); float premult = oozrange * range; float sub = (1 << (prequant - 1)) + header.DCOffset * premult; header.QuantWBits = wordsize - 2; header.QuantWBits |= (prequant - 2) << 4; int k = 0; int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ? (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY; yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize; int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ? (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX; xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize; for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++) { for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++) { block[k++] = terrData[xx, yy] * premult - sub; } } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] itemp = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int maxWbits = prequant + 5; wbits = (prequant >> 1); for (int o = 0; o < Constants.TerrainPatchSize; o++) { DCTLine16(block, ftemp, o); } for (int o = 0; o < Constants.TerrainPatchSize; o++) { wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); } return(itemp); }