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++; try { OnLandPatchReceived(new LandPatchReceivedEventArgs(simulator, x, y, group.PatchSize, heightmap)); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } if (Client.Settings.STORE_LAND_PATCHES) { TerrainPatch patch = new TerrainPatch(); patch.Data = heightmap; patch.X = x; patch.Y = y; simulator.Terrain[y * 16 + x] = patch; } } }
public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, TerrainPatch.LayerType type) { LayerDataPacket layer = new LayerDataPacket(); layer.LayerID.Type = (byte)type; TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader(); header.Stride = STRIDE; header.PatchSize = 16; header.Type = type; // Should be enough to fit even the most poorly packed data byte[] data = new byte[patches.Length * 16 * 16 * 2]; BitPack bitpack = new BitPack(data, 0); bitpack.PackBits(header.Stride, 16); bitpack.PackBits(header.PatchSize, 8); bitpack.PackBits((int)header.Type, 8); for (int i = 0; i < patches.Length; i++) CreatePatch(bitpack, patches[i].Data, patches[i].X, patches[i].Y); 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; }
// Used to send cloud and wind patches public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX, int pRegionSizeY) { 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, pRegionSizeX, pRegionSizeY); 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 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++; try { OnLandPatchReceived(new LandPatchReceivedEventArgs(simulator, x, y, group.PatchSize, heightmap)); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } if (Client.Settings.STORE_LAND_PATCHES) { TerrainPatch patch = new TerrainPatch { Data = heightmap, X = x, Y = y }; simulator.Terrain[y * 16 + x] = patch; } } }
/// <summary> /// Retrieve the terrain height at a given coordinate /// </summary> /// <param name="x">Sim X coordinate, valid range is from 0 to 255</param> /// <param name="y">Sim Y coordinate, valid range is from 0 to 255</param> /// <param name="height">The terrain height at the given point if the /// lookup was successful, otherwise 0.0f</param> /// <returns>True if the lookup was successful, otherwise false</returns> public bool TerrainHeightAtPoint(int x, int y, out float height) { if (Terrain != null && x >= 0 && x < 256 && y >= 0 && y < 256) { int patchX = x / 16; int patchY = y / 16; x = x % 16; y = y % 16; TerrainPatch patch = Terrain[patchY * 16 + patchX]; if (patch != null) { height = patch.Data[y * 16 + x]; return(true); } } height = 0.0f; return(false); }
static float[,] GetHeightMap(TerrainPatch[] Terrain) { float average = 23; float[,] height = new float[256, 256]; for (int x = 0; x < 256; x++) { for (int y = 0; y < 256; y++) { int patchX = x / 16; int patchY = y / 16; TerrainPatch patch = Terrain[patchY * 16 + patchX]; if (patch != null) { height[x, y] = average = patch.Data[(y % 16) * 16 + (x % 16)]; } else { height[x, y] = average; } } } return height; }
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch) { int temp; int wbits = (header.QuantWBits & 0x0f) + 2; uint maxWbits = (uint)wbits + 5; uint minWbits = ((uint)wbits >> 1); wbits = (int)minWbits; for (int i = 0; i < patch.Length; i++) { temp = patch[i]; if (temp != 0) { // Get the absolute value if (temp < 0) temp *= -1; for (int j = (int)maxWbits; j > (int)minWbits; j--) { if ((temp & (1 << j)) != 0) { if (j > wbits) wbits = j; break; } } } } wbits += 1; header.QuantWBits &= 0xf0; if (wbits > 17 || wbits < 2) { Logger.Log("Bits needed per word in EncodePatchHeader() are outside the allowed range", Helpers.LogLevel.Error); } header.QuantWBits |= (wbits - 2); output.PackBits(header.QuantWBits, 8); output.PackFloat(header.DCOffset); output.PackBits(header.Range, 16); output.PackBits(header.PatchIDs, 10); return wbits; }
private static int[] CompressPatch(float[] heightmap, int patchX, int patchY, 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 = patchY * 16; j < (patchY + 1) * 16; j++) { for (int i = patchX * 16; i < (patchX + 1) * 16; i++) block[k++] = heightmap[j * 256 + 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; }
private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, int prequant, out int wbits) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; float oozrange = 1.0f / header.Range; float invprequat = (1 << prequant); float premult = oozrange * invprequat; float sub = 0.5f * header.Range + header.DCOffset; int wordsize = (prequant - 2) & 0x0f; header.QuantWBits = wordsize; header.QuantWBits |= wordsize << 4; int k = 0; int startX = patchX * Constants.TerrainPatchSize; int startY = patchY * Constants.TerrainPatchSize; for (int y = startY; y < startY + Constants.TerrainPatchSize; y++) { for (int x = startX; x < startX + Constants.TerrainPatchSize; x++) { block[k++] = (terrData[x, y] - sub) * premult; } } wbits = (prequant >> 1); dct16x16(block, iout, ref wbits); return iout; }
private void DecompressCloud(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group) { // FIXME: }
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; }
private static int[] CompressPatch(TerrainData 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; }
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.PatchIDs >> 5; y = header.PatchIDs & 0x1F; 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]); SimPatches[simulator.Handle][y * 16 + x] = new TerrainPatch(); SimPatches[simulator.Handle][y * 16 + x].Heightmap = heightmap; } } } }
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, uint pRegionSizeY, 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 (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) output.PackBits(header.PatchIDs, 32); else output.PackBits(header.PatchIDs, 10); return wbits; }
public void SendLayerData(int[] x, int[] y, float[] map, TerrainPatch.LayerType type) { }
private void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group) { ; }
private void UpdateHeightMap(RegionContextBase reg) { int stride = TerrainPatchStride; int stride2 = stride * TerrainPatchWidth; lock (this) { float[,] newHM = new float[TerrainPatchWidth, TerrainPatchLength]; float minHeight = 999999f; float maxHeight = 0f; if ((reg == null) || !(reg is LLRegionContext)) { // things are not set up so create a default, flat heightmap LogManager.Log.Log(LogLevel.DWORLDDETAIL, "LLTerrainInfo: Building default zero terrain"); CreateZeroHeight(ref newHM); minHeight = maxHeight = 0f; } else { try { LLRegionContext llreg = (LLRegionContext)reg; OMV.Simulator sim = llreg.Simulator; int nullPatchCount = 0; for (int px = 0; px < stride; px++) { for (int py = 0; py < stride; py++) { OMV.TerrainPatch pat = sim.Terrain[px + py * stride]; if (pat == null) { // if no patch, it's all zeros if (0.0f < minHeight) { minHeight = 0.0f; } if (0.0f > maxHeight) { maxHeight = 0.0f; } for (int xx = 0; xx < stride; xx++) { for (int yy = 0; yy < stride; yy++) { // newHM[(py * stride + yy), (px * stride + xx)] = 0.0f; newHM[(px * stride + xx), (py * stride + yy)] = 0.0f; } } nullPatchCount++; } else { for (int xx = 0; xx < stride; xx++) { for (int yy = 0; yy < stride; yy++) { float height = pat.Data[xx + yy * stride]; // newHM[(py * stride + yy), (px * stride + xx)] = height; newHM[(px * stride + xx), (py * stride + yy)] = height; if (height < minHeight) { minHeight = height; } if (height > maxHeight) { maxHeight = height; } } } } } } // LogManager.Log.Log(LogLevel.DWORLDDETAIL, // "LLTerrainInfo: UpdateHeightMap: {0} null patches = {1}", sim.Name, nullPatchCount); } catch { // this usually happens when first starting a region LogManager.Log.Log(LogLevel.DWORLDDETAIL, "LLTerrainInfo: Exception building terrain. Defaulting to zero."); CreateZeroHeight(ref newHM); minHeight = maxHeight = 0f; } } m_heightMap = newHM; m_heightMapWidth = TerrainPatchWidth; // X m_heightMapLength = TerrainPatchLength; m_minimumHeight = minHeight; m_maximumHeight = maxHeight; LogManager.Log.Log(LogLevel.DWORLDDETAIL, "LLTerrainInfo: New terrain:" + " min=" + m_minimumHeight.ToString() + " max=" + m_maximumHeight.ToString() ); } }
private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; float oozrange = 1.0f / header.Range; float range = (1 << prequant); float premult = oozrange * range; float sub = 0.5f * header.Range + header.DCOffset; int wordsize = (prequant - 2) & 0x0f; 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] - sub) * premult; } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; wbits = (prequant >> 1); dct16x16(block, iout, ref wbits); return iout; }
void LoadTerrain(string mapFile) { byte[] rgbValues = new byte[256 * 256 * 3]; if (File.Exists(mapFile)) { lock (heightmap) { Bitmap bmp = LoadTGAClass.LoadTGA(mapFile); if (bmp.Width == 256 && bmp.Height == 256) { Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); Marshal.Copy(bmpData.Scan0, rgbValues, 0, rgbValues.Length); bmp.UnlockBits(bmpData); } else { Logger.Log("Map file " + mapFile + " has the wrong dimensions or wrong pixel format (must be 256x256 RGB). Defaulting to 25m", Helpers.LogLevel.Warning); for (int i = 0; i < rgbValues.Length; i++) rgbValues[i] = 25; } } } else { Logger.Log("Map file " + mapFile + " not found, defaulting to 25m", Helpers.LogLevel.Info); for (int i = 0; i < rgbValues.Length; i++) rgbValues[i] = 25; } uint patchX = 0, patchY = 0, x = 0, y = 0; for (int i = 0; i < rgbValues.Length; i += 3) { if (heightmap[patchY, patchX] == null) heightmap[patchY, patchX] = new TerrainPatch(16, 16); heightmap[patchY, patchX].Height[y, x] = (float)rgbValues[i]; ++x; if (x > 15) { if (y == 15) { if (OnTerrainUpdate != null) OnTerrainUpdate(this, patchX, patchY, heightmap[patchY, patchX].Height); } x = 0; ++patchX; } if (patchX > 15) { patchX = 0; ++y; } if (y > 15) { y = 0; ++patchY; } } }
private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 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 < 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]; for (int o = 0; o < Constants.TerrainPatchSize; o++) DCTLine16(block, ftemp, o); for (int o = 0; o < Constants.TerrainPatchSize; o++) DCTColumn16(ftemp, itemp, o); return itemp; }
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, int RegionSizeX, int RegionSizeY) { int temp; int wbits = (header.QuantWBits & 0x0f) + 2; uint maxWbits = (uint)wbits + 5; uint minWbits = ((uint)wbits >> 1); wbits = (int)minWbits; for (int i = 0; i < patch.Length; i++) { temp = patch[i]; if (temp != 0) { // Get the absolute value if (temp < 0) temp *= -1; for (int j = (int)maxWbits; j > (int)minWbits; j--) { if ((temp & (1 << j)) != 0) { if (j > wbits) wbits = j; break; } } } } wbits += 1; 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) if (RegionSizeX > Constants.RegionSize || RegionSizeY > Constants.RegionSize) output.PackBits(header.PatchIDs, 32); else output.PackBits(header.PatchIDs, 10); return wbits; }
private static int[] CompressPatch(float[] 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; 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 void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group) { int[] patches = new int[32 * 32]; // Ignore the simulator stride value group.Stride = group.PatchSize; // Each wind packet contains the wind speeds and direction for the entire simulator // stored as two float arrays. The first array is the X value of the wind speed at // each 16x16m block, second is the Y value. // wind_speed = distance(x,y to 0,0) // wind_direction = vec2(x,y) // X values TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack); TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize); float[] xvalues = TerrainCompressor.DecompressPatch(patches, header, group); // Y values header = TerrainCompressor.DecodePatchHeader(bitpack); TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize); float[] yvalues = TerrainCompressor.DecompressPatch(patches, header, group); if (simulator.Client.Settings.STORE_LAND_PATCHES) { for (int i = 0; i < 256; i++) simulator.WindSpeeds[i] = new Vector2(xvalues[i], yvalues[i]); } }
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[] heightmap, int patchX, int patchY, TerrainPatch.Header header, int prequant, int RegionSizeX, int RegionSizeY) { float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 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; // int sqrt = (int)Math.Sqrt(heightmap.Length); //OpenSim.Framework.Console.MainConsole.Instance.Output(sqrt + "," + patchX + "," + patchY + ","+ // patchX * Constants.TerrainPatchSize + "," + // ((patchX >= (RegionSizeX / Constants.TerrainPatchSize) ? (RegionSizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX) + 1) * Constants.TerrainPatchSize + "," + // patchY * Constants.TerrainPatchSize + "," + // ((patchY >= (RegionSizeY / Constants.TerrainPatchSize) ? (RegionSizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY) + 1) * Constants.TerrainPatchSize); 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 * sqrt + i] * premult - sub; block[k++] = heightmap[j * RegionSizeX + i] * premult - sub; } float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; int[] itemp = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; for (int o = 0; o < Constants.TerrainPatchSize; o++) DCTLine16(block, ftemp, o); for (int o = 0; o < Constants.TerrainPatchSize; o++) DCTColumn16(ftemp, itemp, o); return itemp; }
private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) { float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; float oozrange = 1.0f/header.Range; float range = (1 << prequant); float premult = oozrange*range; float sub = (1 << (prequant - 1)) + header.DCOffset*premult; int wordsize = (prequant - 2) & 0x0f; 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, 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 void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group) { int[] patches = new int[32 * 32]; // Ignore the simulator stride value group.Stride = group.PatchSize; // Each wind packet contains the wind speeds and direction for the entire simulator // stored as two float arrays. The first array is the X value of the wind speed at // each 16x16m block, second is the Y value. // wind_speed = distance(x,y to 0,0) // wind_direction = vec2(x,y) // X values TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack); TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize); float[] xvalues = TerrainCompressor.DecompressPatch(patches, header, group); // Y values header = TerrainCompressor.DecodePatchHeader(bitpack); TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize); float[] yvalues = TerrainCompressor.DecompressPatch(patches, header, group); ulong handle = simulator.Handle; Vector2[] windSpeeds; lock (WindSpeeds.Dictionary) { if (!WindSpeeds.TryGetValue(handle,out windSpeeds)) { windSpeeds = WindSpeeds[handle] = new Vector2[256]; } } for (int i = 0; i < 256; i++) windSpeeds[i] = new Vector2(xvalues[i], yvalues[i]); }
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; }
private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits) { if (wbits > 17) wbits = 17; else if (wbits < 2) wbits = 2; header.QuantWBits &= 0xf0; header.QuantWBits |= (wbits - 2); output.PackBits(header.QuantWBits, 8); output.PackFloat(header.DCOffset); output.PackBits(header.Range, 16); if (largeRegion) output.PackBits(header.PatchIDs, 32); else output.PackBits(header.PatchIDs, 10); }