From bedafb8fae9898ef0c5fc6470236ee7244e616a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 27 Mar 2015 19:32:50 -0700 Subject: varregion: refactor use of 'double heightmap[,]' into references to new class TerrainData and push the implementation from Scene into the database readers and writers. --- OpenSim/Framework/TerrainData.cs | 464 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 OpenSim/Framework/TerrainData.cs (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs new file mode 100644 index 0000000..6b1be4e --- /dev/null +++ b/OpenSim/Framework/TerrainData.cs @@ -0,0 +1,464 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using OpenMetaverse; + +using log4net; + +namespace OpenSim.Framework +{ + public abstract class TerrainData + { + // Terrain always is a square + public int SizeX { get; protected set; } + public int SizeY { get; protected set; } + public int SizeZ { get; protected set; } + + // A height used when the user doesn't specify anything + public const float DefaultTerrainHeight = 21f; + + public abstract float this[int x, int y] { get; set; } + // Someday terrain will have caves + public abstract float this[int x, int y, int z] { get; set; } + + public abstract bool IsTaintedAt(int xx, int yy); + public abstract bool IsTaintedAt(int xx, int yy, bool clearOnTest); + public abstract void TaintAllTerrain(); + public abstract void ClearTaint(); + + public abstract void ClearLand(); + public abstract void ClearLand(float height); + + // Return a representation of this terrain for storing as a blob in the database. + // Returns 'true' to say blob was stored in the 'out' locations. + public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob); + + // Given a revision code and a blob from the database, create and return the right type of TerrainData. + // The sizes passed are the expected size of the region. The database info will be used to + // initialize the heightmap of that sized region with as much data is in the blob. + // Return created TerrainData or 'null' if unsuccessful. + public static TerrainData CreateFromDatabaseBlobFactory(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) + { + // For the moment, there is only one implementation class + return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob); + } + + // return a special compressed representation of the heightmap in ints + public abstract int[] GetCompressedMap(); + public abstract float CompressionFactor { get; } + + public abstract float[] GetFloatsSerialized(); + public abstract double[,] GetDoubles(); + public abstract TerrainData Clone(); + } + + // The terrain is stored in the database as a blob with a 'revision' field. + // Some implementations of terrain storage would fill the revision field with + // the time the terrain was stored. When real revisions were added and this + // feature removed, that left some old entries with the time in the revision + // field. + // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is + // left over and it is presumed to be 'Legacy256'. + // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation. + // If a revision does not match any of these, it is assumed to be Legacy256. + public enum DBTerrainRevision + { + // Terrain is 'double[256,256]' + Legacy256 = 11, + // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions + // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. + Variable2D = 22, + // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions + // and third int is the 'compression factor'. The heights are compressed as + // "int compressedHeight = (int)(height * compressionFactor);" + // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. + Compressed2D = 27, + // A revision that is not listed above or any revision greater than this value is 'Legacy256'. + RevisionHigh = 1234 + } + + // Version of terrain that is a heightmap. + // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge + // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. + // The heighmap is kept as an array of integers. The integer values are converted to + // and from floats by TerrainCompressionFactor. + public class HeightmapTerrainData : TerrainData + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static string LogHeader = "[HEIGHTMAP TERRAIN DATA]"; + + // TerrainData.this[x, y] + public override float this[int x, int y] + { + get { return FromCompressedHeight(m_heightmap[x, y]); } + set { + int newVal = ToCompressedHeight(value); + if (m_heightmap[x, y] != newVal) + { + m_heightmap[x, y] = newVal; + m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; + } + } + } + + // TerrainData.this[x, y, z] + public override float this[int x, int y, int z] + { + get { return this[x, y]; } + set { this[x, y] = value; } + } + + // TerrainData.ClearTaint + public override void ClearTaint() + { + SetAllTaint(false); + } + + // TerrainData.TaintAllTerrain + public override void TaintAllTerrain() + { + SetAllTaint(true); + } + + private void SetAllTaint(bool setting) + { + for (int ii = 0; ii < m_taint.GetLength(0); ii++) + for (int jj = 0; jj < m_taint.GetLength(1); jj++) + m_taint[ii, jj] = setting; + } + + // TerrainData.ClearLand + public override void ClearLand() + { + ClearLand(DefaultTerrainHeight); + } + // TerrainData.ClearLand(float) + public override void ClearLand(float pHeight) + { + int flatHeight = ToCompressedHeight(pHeight); + for (int xx = 0; xx < SizeX; xx++) + for (int yy = 0; yy < SizeY; yy++) + m_heightmap[xx, yy] = flatHeight; + } + + // Return 'true' of the patch that contains these region coordinates has been modified. + // Note that checking the taint clears it. + // There is existing code that relies on this feature. + public override bool IsTaintedAt(int xx, int yy, bool clearOnTest) + { + int tx = xx / Constants.TerrainPatchSize; + int ty = yy / Constants.TerrainPatchSize; + bool ret = m_taint[tx, ty]; + if (ret && clearOnTest) + m_taint[tx, ty] = false; + return ret; + } + + // Old form that clears the taint flag when we check it. + public override bool IsTaintedAt(int xx, int yy) + { + return IsTaintedAt(xx, yy, true /* clearOnTest */); + } + + // TerrainData.GetDatabaseBlob + // The user wants something to store in the database. + public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob) + { + bool ret = false; + if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize) + { + DBRevisionCode = (int)DBTerrainRevision.Legacy256; + blob = ToLegacyTerrainSerialization(); + ret = true; + } + else + { + DBRevisionCode = (int)DBTerrainRevision.Compressed2D; + blob = ToCompressedTerrainSerialization(); + ret = true; + } + return ret; + } + + // TerrainData.CompressionFactor + private float m_compressionFactor = 100.0f; + public override float CompressionFactor { get { return m_compressionFactor; } } + + // TerrainData.GetCompressedMap + public override int[] GetCompressedMap() + { + int[] newMap = new int[SizeX * SizeY]; + + int ind = 0; + for (int xx = 0; xx < SizeX; xx++) + for (int yy = 0; yy < SizeY; yy++) + newMap[ind++] = m_heightmap[xx, yy]; + + return newMap; + + } + // TerrainData.Clone + public override TerrainData Clone() + { + HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); + ret.m_heightmap = (int[,])this.m_heightmap.Clone(); + return ret; + } + + // TerrainData.GetFloatsSerialized + // This one dimensional version is ordered so height = map[y*sizeX+x]; + // DEPRECATED: don't use this function as it does not retain the dimensions of the terrain + // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256. + public override float[] GetFloatsSerialized() + { + int points = SizeX * SizeY; + float[] heights = new float[points]; + + int idx = 0; + for (int jj = 0; jj < SizeY; jj++) + for (int ii = 0; ii < SizeX; ii++) + { + heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); + } + + return heights; + } + + // TerrainData.GetDoubles + public override double[,] GetDoubles() + { + double[,] ret = new double[SizeX, SizeY]; + for (int xx = 0; xx < SizeX; xx++) + for (int yy = 0; yy < SizeY; yy++) + ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); + + return ret; + } + + + // ============================================================= + + private int[,] m_heightmap; + // Remember subregions of the heightmap that has changed. + private bool[,] m_taint; + + // To save space (especially for large regions), keep the height as a short integer + // that is coded as the float height times the compression factor (usually '100' + // to make for two decimal points). + public int ToCompressedHeight(double pHeight) + { + return (int)(pHeight * CompressionFactor); + } + + public float FromCompressedHeight(int pHeight) + { + return ((float)pHeight) / CompressionFactor; + } + + // To keep with the legacy theme, create an instance of this class based on the + // way terrain used to be passed around. + public HeightmapTerrainData(double[,] pTerrain) + { + SizeX = pTerrain.GetLength(0); + SizeY = pTerrain.GetLength(1); + SizeZ = (int)Constants.RegionHeight; + m_compressionFactor = 100.0f; + + m_heightmap = new int[SizeX, SizeY]; + for (int ii = 0; ii < SizeX; ii++) + { + for (int jj = 0; jj < SizeY; jj++) + { + m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); + + } + } + // m_log.DebugFormat("{0} new by doubles. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); + + m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; + ClearTaint(); + } + + // Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that + public HeightmapTerrainData(int pX, int pY, int pZ) + { + SizeX = pX; + SizeY = pY; + SizeZ = pZ; + m_compressionFactor = 100.0f; + m_heightmap = new int[SizeX, SizeY]; + m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; + // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); + ClearTaint(); + ClearLand(0f); + } + + public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) + { + m_compressionFactor = pCompressionFactor; + int ind = 0; + for (int xx = 0; xx < SizeX; xx++) + for (int yy = 0; yy < SizeY; yy++) + m_heightmap[xx, yy] = cmap[ind++]; + // m_log.DebugFormat("{0} new by compressed map. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); + } + + // Create a heighmap from a database blob + public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) + { + switch ((DBTerrainRevision)pFormatCode) + { + case DBTerrainRevision.Compressed2D: + FromCompressedTerrainSerialization(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + default: + FromLegacyTerrainSerialization(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from legacy serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + } + } + + // Just create an array of doubles. Presumes the caller implicitly knows the size. + public Array ToLegacyTerrainSerialization() + { + Array ret = null; + + using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double))) + { + using (BinaryWriter bw = new BinaryWriter(str)) + { + for (int xx = 0; xx < Constants.RegionSize; xx++) + { + for (int yy = 0; yy < Constants.RegionSize; yy++) + { + double height = this[xx, yy]; + if (height == 0.0) + height = double.Epsilon; + bw.Write(height); + } + } + } + ret = str.ToArray(); + } + return ret; + } + + // Just create an array of doubles. Presumes the caller implicitly knows the size. + public void FromLegacyTerrainSerialization(byte[] pBlob) + { + // In case database info doesn't match real terrain size, initialize the whole terrain. + ClearLand(); + + using (MemoryStream mstr = new MemoryStream(pBlob)) + { + using (BinaryReader br = new BinaryReader(mstr)) + { + for (int xx = 0; xx < (int)Constants.RegionSize; xx++) + { + for (int yy = 0; yy < (int)Constants.RegionSize; yy++) + { + float val = (float)br.ReadDouble(); + if (xx < SizeX && yy < SizeY) + m_heightmap[xx, yy] = ToCompressedHeight(val); + } + } + } + ClearTaint(); + } + } + + // See the reader below. + public Array ToCompressedTerrainSerialization() + { + Array ret = null; + using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16)))) + { + using (BinaryWriter bw = new BinaryWriter(str)) + { + bw.Write((Int32)DBTerrainRevision.Compressed2D); + bw.Write((Int32)SizeX); + bw.Write((Int32)SizeY); + bw.Write((Int32)CompressionFactor); + for (int yy = 0; yy < SizeY; yy++) + for (int xx = 0; xx < SizeX; xx++) + { + bw.Write((Int16)m_heightmap[xx, yy]); + } + } + ret = str.ToArray(); + } + return ret; + } + + // Initialize heightmap from blob consisting of: + // int32, int32, int32, int32, int16[] + // where the first int32 is format code, next two int32s are the X and y of heightmap data and + // the forth int is the compression factor for the following int16s + // This is just sets heightmap info. The actual size of the region was set on this instance's + // creation and any heights not initialized by theis blob are set to the default height. + public void FromCompressedTerrainSerialization(byte[] pBlob) + { + Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; + + using (MemoryStream mstr = new MemoryStream(pBlob)) + { + using (BinaryReader br = new BinaryReader(mstr)) + { + hmFormatCode = br.ReadInt32(); + hmSizeX = br.ReadInt32(); + hmSizeY = br.ReadInt32(); + hmCompressionFactor = br.ReadInt32(); + + m_compressionFactor = hmCompressionFactor; + + // In case database info doesn't match real terrain size, initialize the whole terrain. + ClearLand(); + + for (int yy = 0; yy < hmSizeY; yy++) + { + for (int xx = 0; xx < hmSizeX; xx++) + { + Int16 val = br.ReadInt16(); + if (xx < SizeX && yy < SizeY) + m_heightmap[xx, yy] = val; + } + } + } + ClearTaint(); + + m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", + LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); + } + } + } +} -- cgit v1.1 From 1c752296bfc25ca709117ad1c557aff2b6097ffb Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 24 Aug 2015 18:40:28 +0100 Subject: change internal representation of terrain from int to ushort. This will suporte height from 0 to 655.53m that includes SL limits ( still need to add code to trap eventual negative values from dbs or user input) --- OpenSim/Framework/TerrainData.cs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index 6b1be4e..d0eddc6 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -72,8 +72,8 @@ namespace OpenSim.Framework return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob); } - // return a special compressed representation of the heightmap in ints - public abstract int[] GetCompressedMap(); + // return a special compressed representation of the heightmap in ushort + public abstract ushort[] GetCompressedMap(); public abstract float CompressionFactor { get; } public abstract float[] GetFloatsSerialized(); @@ -99,7 +99,7 @@ namespace OpenSim.Framework Variable2D = 22, // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions // and third int is the 'compression factor'. The heights are compressed as - // "int compressedHeight = (int)(height * compressionFactor);" + // "ushort compressedHeight = (ushort)(height * compressionFactor);" // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. Compressed2D = 27, // A revision that is not listed above or any revision greater than this value is 'Legacy256'. @@ -109,7 +109,7 @@ namespace OpenSim.Framework // Version of terrain that is a heightmap. // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. - // The heighmap is kept as an array of integers. The integer values are converted to + // The heighmap is kept as an array of ushorts. The ushort values are converted to // and from floats by TerrainCompressionFactor. public class HeightmapTerrainData : TerrainData { @@ -121,7 +121,7 @@ namespace OpenSim.Framework { get { return FromCompressedHeight(m_heightmap[x, y]); } set { - int newVal = ToCompressedHeight(value); + ushort newVal = ToCompressedHeight(value); if (m_heightmap[x, y] != newVal) { m_heightmap[x, y] = newVal; @@ -164,7 +164,7 @@ namespace OpenSim.Framework // TerrainData.ClearLand(float) public override void ClearLand(float pHeight) { - int flatHeight = ToCompressedHeight(pHeight); + ushort flatHeight = ToCompressedHeight(pHeight); for (int xx = 0; xx < SizeX; xx++) for (int yy = 0; yy < SizeY; yy++) m_heightmap[xx, yy] = flatHeight; @@ -214,9 +214,9 @@ namespace OpenSim.Framework public override float CompressionFactor { get { return m_compressionFactor; } } // TerrainData.GetCompressedMap - public override int[] GetCompressedMap() + public override ushort[] GetCompressedMap() { - int[] newMap = new int[SizeX * SizeY]; + ushort[] newMap = new ushort[SizeX * SizeY]; int ind = 0; for (int xx = 0; xx < SizeX; xx++) @@ -230,7 +230,7 @@ namespace OpenSim.Framework public override TerrainData Clone() { HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); - ret.m_heightmap = (int[,])this.m_heightmap.Clone(); + ret.m_heightmap = (ushort[,])this.m_heightmap.Clone(); return ret; } @@ -267,19 +267,19 @@ namespace OpenSim.Framework // ============================================================= - private int[,] m_heightmap; + private ushort[,] m_heightmap; // Remember subregions of the heightmap that has changed. private bool[,] m_taint; // To save space (especially for large regions), keep the height as a short integer // that is coded as the float height times the compression factor (usually '100' // to make for two decimal points). - public int ToCompressedHeight(double pHeight) + public ushort ToCompressedHeight(double pHeight) { - return (int)(pHeight * CompressionFactor); + return (ushort)(pHeight * CompressionFactor); } - public float FromCompressedHeight(int pHeight) + public float FromCompressedHeight(ushort pHeight) { return ((float)pHeight) / CompressionFactor; } @@ -293,7 +293,7 @@ namespace OpenSim.Framework SizeZ = (int)Constants.RegionHeight; m_compressionFactor = 100.0f; - m_heightmap = new int[SizeX, SizeY]; + m_heightmap = new ushort[SizeX, SizeY]; for (int ii = 0; ii < SizeX; ii++) { for (int jj = 0; jj < SizeY; jj++) @@ -315,14 +315,14 @@ namespace OpenSim.Framework SizeY = pY; SizeZ = pZ; m_compressionFactor = 100.0f; - m_heightmap = new int[SizeX, SizeY]; + m_heightmap = new ushort[SizeX, SizeY]; m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); ClearTaint(); ClearLand(0f); } - public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) + public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) { m_compressionFactor = pCompressionFactor; int ind = 0; @@ -401,7 +401,7 @@ namespace OpenSim.Framework public Array ToCompressedTerrainSerialization() { Array ret = null; - using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16)))) + using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) { using (BinaryWriter bw = new BinaryWriter(str)) { @@ -412,7 +412,7 @@ namespace OpenSim.Framework for (int yy = 0; yy < SizeY; yy++) for (int xx = 0; xx < SizeX; xx++) { - bw.Write((Int16)m_heightmap[xx, yy]); + bw.Write((ushort)m_heightmap[xx, yy]); } } ret = str.ToArray(); @@ -448,7 +448,7 @@ namespace OpenSim.Framework { for (int xx = 0; xx < hmSizeX; xx++) { - Int16 val = br.ReadInt16(); + ushort val = br.ReadUInt16(); if (xx < SizeX && yy < SizeY) m_heightmap[xx, yy] = val; } -- cgit v1.1 From 64d05bab0fe9e12038309275a677e68518fb9b15 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 25 Aug 2015 13:36:45 +0100 Subject: terrain stored as ushorts with gzip compression --- OpenSim/Framework/TerrainData.cs | 251 ++++++++++++++++++++++++++++++++++----- 1 file changed, 221 insertions(+), 30 deletions(-) (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index d0eddc6..cc5b8f5 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Reflection; using OpenMetaverse; @@ -102,6 +103,11 @@ namespace OpenSim.Framework // "ushort compressedHeight = (ushort)(height * compressionFactor);" // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. Compressed2D = 27, + // as Compressed2D but using ushort[] in place of int16[] + Compressed2Du = 28, + // as Compressed2D but using ushort[] in place of int16[] with Gzip compression + Compressed2DuGzip = 29, + // A revision that is not listed above or any revision greater than this value is 'Legacy256'. RevisionHigh = 1234 } @@ -120,7 +126,8 @@ namespace OpenSim.Framework public override float this[int x, int y] { get { return FromCompressedHeight(m_heightmap[x, y]); } - set { + set + { ushort newVal = ToCompressedHeight(value); if (m_heightmap[x, y] != newVal) { @@ -177,7 +184,7 @@ namespace OpenSim.Framework { int tx = xx / Constants.TerrainPatchSize; int ty = yy / Constants.TerrainPatchSize; - bool ret = m_taint[tx, ty]; + bool ret = m_taint[tx, ty]; if (ret && clearOnTest) m_taint[tx, ty] = false; return ret; @@ -202,8 +209,8 @@ namespace OpenSim.Framework } else { - DBRevisionCode = (int)DBTerrainRevision.Compressed2D; - blob = ToCompressedTerrainSerialization(); + DBRevisionCode = (int)DBTerrainRevision.Compressed2DuGzip; + blob = ToCompressedTerrainSerializationGzip(); ret = true; } return ret; @@ -276,6 +283,11 @@ namespace OpenSim.Framework // to make for two decimal points). public ushort ToCompressedHeight(double pHeight) { + // clamp into valid range + if (pHeight < 0) + pHeight = 0; + else if (pHeight > 655.35f) + pHeight = 655.35f; return (ushort)(pHeight * CompressionFactor); } @@ -322,7 +334,8 @@ namespace OpenSim.Framework ClearLand(0f); } - public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) + public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) + : this(pX, pY, pZ) { m_compressionFactor = pCompressionFactor; int ind = 0; @@ -333,12 +346,21 @@ namespace OpenSim.Framework } // Create a heighmap from a database blob - public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) + public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) + : this(pSizeX, pSizeY, pSizeZ) { switch ((DBTerrainRevision)pFormatCode) { - case DBTerrainRevision.Compressed2D: + case DBTerrainRevision.Compressed2DuGzip: + FromCompressedTerrainSerializationGZip(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + case DBTerrainRevision.Compressed2Du: FromCompressedTerrainSerialization(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + case DBTerrainRevision.Compressed2D: + FromCompressedTerrainSerialization2D(pBlob); m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); break; default: @@ -379,44 +401,132 @@ namespace OpenSim.Framework // In case database info doesn't match real terrain size, initialize the whole terrain. ClearLand(); - using (MemoryStream mstr = new MemoryStream(pBlob)) + try { - using (BinaryReader br = new BinaryReader(mstr)) + using (MemoryStream mstr = new MemoryStream(pBlob)) { - for (int xx = 0; xx < (int)Constants.RegionSize; xx++) + using (BinaryReader br = new BinaryReader(mstr)) { - for (int yy = 0; yy < (int)Constants.RegionSize; yy++) + for (int xx = 0; xx < (int)Constants.RegionSize; xx++) { - float val = (float)br.ReadDouble(); - if (xx < SizeX && yy < SizeY) - m_heightmap[xx, yy] = ToCompressedHeight(val); + for (int yy = 0; yy < (int)Constants.RegionSize; yy++) + { + float val = (float)br.ReadDouble(); + + if (xx < SizeX && yy < SizeY) + m_heightmap[xx, yy] = ToCompressedHeight(val); + } } } } - ClearTaint(); } + catch + { + ClearLand(); + } + ClearTaint(); + } + + public Array ToCompressedTerrainSerialization2D() + { + Array ret = null; + try + { + using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) + { + using (BinaryWriter bw = new BinaryWriter(str)) + { + bw.Write((Int32)DBTerrainRevision.Compressed2D); + bw.Write((Int32)SizeX); + bw.Write((Int32)SizeY); + bw.Write((Int32)CompressionFactor); + for (int yy = 0; yy < SizeY; yy++) + for (int xx = 0; xx < SizeX; xx++) + { + bw.Write((Int16)m_heightmap[xx, yy]); + } + } + ret = str.ToArray(); + } + } + catch + { + + } + return ret; } - + // See the reader below. public Array ToCompressedTerrainSerialization() { Array ret = null; - using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) + try { - using (BinaryWriter bw = new BinaryWriter(str)) + using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) { - bw.Write((Int32)DBTerrainRevision.Compressed2D); - bw.Write((Int32)SizeX); - bw.Write((Int32)SizeY); - bw.Write((Int32)CompressionFactor); - for (int yy = 0; yy < SizeY; yy++) - for (int xx = 0; xx < SizeX; xx++) + using (BinaryWriter bw = new BinaryWriter(str)) + { + bw.Write((Int32)DBTerrainRevision.Compressed2Du); + bw.Write((Int32)SizeX); + bw.Write((Int32)SizeY); + bw.Write((Int32)CompressionFactor); + for (int yy = 0; yy < SizeY; yy++) + for (int xx = 0; xx < SizeX; xx++) + { + bw.Write((ushort)m_heightmap[xx, yy]); + } + } + ret = str.ToArray(); + } + } + catch + { + + } + return ret; + } + + // as above with Gzip compression + public Array ToCompressedTerrainSerializationGzip() + { + Array ret = null; + try + { + using (MemoryStream inp = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) + { + using (BinaryWriter bw = new BinaryWriter(inp)) + { + bw.Write((Int32)DBTerrainRevision.Compressed2DuGzip); + bw.Write((Int32)SizeX); + bw.Write((Int32)SizeY); + bw.Write((Int32)CompressionFactor); + for (int yy = 0; yy < SizeY; yy++) + for (int xx = 0; xx < SizeX; xx++) + { + bw.Write((ushort)m_heightmap[xx, yy]); + } + + bw.Flush(); + inp.Seek(0,SeekOrigin.Begin); + + using (MemoryStream outputStream = new MemoryStream()) { - bw.Write((ushort)m_heightmap[xx, yy]); + using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress)) + { + inp.CopyStream(compressionStream, int.MaxValue); + compressionStream.Close(); + ret = outputStream.ToArray(); + } } + } } - ret = str.ToArray(); } + catch + { + + } + m_log.InfoFormat("{0} terrain GZiped to {1} bytes (compressed2Dus)", + LogHeader, ret.Length); return ret; } @@ -426,7 +536,7 @@ namespace OpenSim.Framework // the forth int is the compression factor for the following int16s // This is just sets heightmap info. The actual size of the region was set on this instance's // creation and any heights not initialized by theis blob are set to the default height. - public void FromCompressedTerrainSerialization(byte[] pBlob) + public void FromCompressedTerrainSerialization2D(byte[] pBlob) { Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; @@ -448,17 +558,98 @@ namespace OpenSim.Framework { for (int xx = 0; xx < hmSizeX; xx++) { - ushort val = br.ReadUInt16(); + short val = br.ReadInt16(); + if (val < 0) + val = 0; if (xx < SizeX && yy < SizeY) - m_heightmap[xx, yy] = val; + m_heightmap[xx, yy] = (ushort)val; } } } ClearTaint(); - m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", + m_log.InfoFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); } } + + // Initialize heightmap from blob consisting of: + // int32, int32, int32, int32, ushort[] + // where the first int32 is format code, next two int32s are the X and y of heightmap data and + // the forth int is the compression factor for the following int16s + // This is just sets heightmap info. The actual size of the region was set on this instance's + // creation and any heights not initialized by theis blob are set to the default height. + public void FromCompressedTerrainSerialization(byte[] pBlob) + { + Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; + try + { + using (MemoryStream mstr = new MemoryStream(pBlob)) + { + using (BinaryReader br = new BinaryReader(mstr)) + { + hmFormatCode = br.ReadInt32(); + hmSizeX = br.ReadInt32(); + hmSizeY = br.ReadInt32(); + hmCompressionFactor = br.ReadInt32(); + + m_compressionFactor = hmCompressionFactor; + + // In case database info doesn't match real terrain size, initialize the whole terrain. + ClearLand(); + + for (int yy = 0; yy < hmSizeY; yy++) + { + for (int xx = 0; xx < hmSizeX; xx++) + { + ushort val = br.ReadUInt16(); + if (xx < SizeX && yy < SizeY) + m_heightmap[xx, yy] = val; + } + } + } + } + } + catch (Exception e) + { + ClearTaint(); + m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged", + LogHeader,e.Message); + return; + } + ClearTaint(); + + m_log.InfoFormat("{0} Read compressed2D terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", + LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); + + } + + // as above but Gzip compressed + public void FromCompressedTerrainSerializationGZip(byte[] pBlob) + { + m_log.InfoFormat("{0} GZip {1} bytes for terrain", + LogHeader,pBlob.Length); + byte[] gzipout = null; + try + { + using (MemoryStream inputStream = new MemoryStream(pBlob)) + { + using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) + { + using (MemoryStream outputStream = new MemoryStream()) + { + decompressionStream.Flush(); + decompressionStream.CopyTo(outputStream); + gzipout = outputStream.ToArray(); + } + } + } + } + catch + { + } + + FromCompressedTerrainSerialization(gzipout); + } } } -- cgit v1.1 From 244f0c6352a920b8bba5e13fadda49cb5b368e06 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 25 Aug 2015 16:51:48 +0100 Subject: change terrain internal representation to float. ushort work with legal sl terrain, but may break existent terrain and that may cost a lot more than the cost of memory --- OpenSim/Framework/TerrainData.cs | 241 ++++++++++++++++++++++++++------------- 1 file changed, 162 insertions(+), 79 deletions(-) (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index cc5b8f5..976c1f0 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -49,6 +49,7 @@ namespace OpenSim.Framework public abstract float this[int x, int y] { get; set; } // Someday terrain will have caves + // at most holes :p public abstract float this[int x, int y, int z] { get; set; } public abstract bool IsTaintedAt(int xx, int yy); @@ -74,7 +75,7 @@ namespace OpenSim.Framework } // return a special compressed representation of the heightmap in ushort - public abstract ushort[] GetCompressedMap(); + public abstract float[] GetCompressedMap(); public abstract float CompressionFactor { get; } public abstract float[] GetFloatsSerialized(); @@ -95,16 +96,21 @@ namespace OpenSim.Framework { // Terrain is 'double[256,256]' Legacy256 = 11, + // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. Variable2D = 22, + Variable2DGzip = 23, + // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions // and third int is the 'compression factor'. The heights are compressed as // "ushort compressedHeight = (ushort)(height * compressionFactor);" // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. Compressed2D = 27, + // as Compressed2D but using ushort[] in place of int16[] Compressed2Du = 28, + // as Compressed2D but using ushort[] in place of int16[] with Gzip compression Compressed2DuGzip = 29, @@ -125,13 +131,12 @@ namespace OpenSim.Framework // TerrainData.this[x, y] public override float this[int x, int y] { - get { return FromCompressedHeight(m_heightmap[x, y]); } + get { return m_heightmap[x, y]; } set { - ushort newVal = ToCompressedHeight(value); - if (m_heightmap[x, y] != newVal) + if (m_heightmap[x, y] != value) { - m_heightmap[x, y] = newVal; + m_heightmap[x, y] = value; m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; } } @@ -171,10 +176,9 @@ namespace OpenSim.Framework // TerrainData.ClearLand(float) public override void ClearLand(float pHeight) { - ushort flatHeight = ToCompressedHeight(pHeight); for (int xx = 0; xx < SizeX; xx++) for (int yy = 0; yy < SizeY; yy++) - m_heightmap[xx, yy] = flatHeight; + m_heightmap[xx, yy] = pHeight; } // Return 'true' of the patch that contains these region coordinates has been modified. @@ -209,8 +213,8 @@ namespace OpenSim.Framework } else { - DBRevisionCode = (int)DBTerrainRevision.Compressed2DuGzip; - blob = ToCompressedTerrainSerializationGzip(); + DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip; + blob = ToCompressedTerrainSerializationV2DGzip(); ret = true; } return ret; @@ -221,9 +225,9 @@ namespace OpenSim.Framework public override float CompressionFactor { get { return m_compressionFactor; } } // TerrainData.GetCompressedMap - public override ushort[] GetCompressedMap() + public override float[] GetCompressedMap() { - ushort[] newMap = new ushort[SizeX * SizeY]; + float[] newMap = new float[SizeX * SizeY]; int ind = 0; for (int xx = 0; xx < SizeX; xx++) @@ -237,7 +241,7 @@ namespace OpenSim.Framework public override TerrainData Clone() { HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); - ret.m_heightmap = (ushort[,])this.m_heightmap.Clone(); + ret.m_heightmap = (float[,])this.m_heightmap.Clone(); return ret; } @@ -254,7 +258,7 @@ namespace OpenSim.Framework for (int jj = 0; jj < SizeY; jj++) for (int ii = 0; ii < SizeX; ii++) { - heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); + heights[idx++] = m_heightmap[ii, jj]; } return heights; @@ -266,7 +270,7 @@ namespace OpenSim.Framework double[,] ret = new double[SizeX, SizeY]; for (int xx = 0; xx < SizeX; xx++) for (int yy = 0; yy < SizeY; yy++) - ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); + ret[xx, yy] = (double)m_heightmap[xx, yy]; return ret; } @@ -274,21 +278,37 @@ namespace OpenSim.Framework // ============================================================= - private ushort[,] m_heightmap; + private float[,] m_heightmap; // Remember subregions of the heightmap that has changed. private bool[,] m_taint; - // To save space (especially for large regions), keep the height as a short integer // that is coded as the float height times the compression factor (usually '100' // to make for two decimal points). - public ushort ToCompressedHeight(double pHeight) + public short ToCompressedHeightshort(float pHeight) + { + // clamp into valid range + pHeight *= CompressionFactor; + if (pHeight < short.MinValue) + return short.MinValue; + else if (pHeight > short.MaxValue) + return short.MaxValue; + return (short)pHeight; + } + + public ushort ToCompressedHeightushort(float pHeight) { // clamp into valid range - if (pHeight < 0) - pHeight = 0; - else if (pHeight > 655.35f) - pHeight = 655.35f; - return (ushort)(pHeight * CompressionFactor); + pHeight *= CompressionFactor; + if (pHeight < ushort.MinValue) + return ushort.MinValue; + else if (pHeight > ushort.MaxValue) + return ushort.MaxValue; + return (ushort)pHeight; + } + + public float FromCompressedHeight(short pHeight) + { + return ((float)pHeight) / CompressionFactor; } public float FromCompressedHeight(ushort pHeight) @@ -305,12 +325,12 @@ namespace OpenSim.Framework SizeZ = (int)Constants.RegionHeight; m_compressionFactor = 100.0f; - m_heightmap = new ushort[SizeX, SizeY]; + m_heightmap = new float[SizeX, SizeY]; for (int ii = 0; ii < SizeX; ii++) { for (int jj = 0; jj < SizeY; jj++) { - m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); + m_heightmap[ii, jj] = (float)pTerrain[ii, jj]; } } @@ -327,14 +347,14 @@ namespace OpenSim.Framework SizeY = pY; SizeZ = pZ; m_compressionFactor = 100.0f; - m_heightmap = new ushort[SizeX, SizeY]; + m_heightmap = new float[SizeX, SizeY]; m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); ClearTaint(); ClearLand(0f); } - public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) + public HeightmapTerrainData(float[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) { m_compressionFactor = pCompressionFactor; @@ -351,12 +371,22 @@ namespace OpenSim.Framework { switch ((DBTerrainRevision)pFormatCode) { + case DBTerrainRevision.Variable2DGzip: + FromCompressedTerrainSerializationV2DGZip(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + + case DBTerrainRevision.Variable2D: + FromCompressedTerrainSerializationV2D(pBlob); + m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + break; + case DBTerrainRevision.Compressed2DuGzip: - FromCompressedTerrainSerializationGZip(pBlob); + FromCompressedTerrainSerialization2DuGZip(pBlob); m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); break; case DBTerrainRevision.Compressed2Du: - FromCompressedTerrainSerialization(pBlob); + FromCompressedTerrainSerialization2D(pBlob); m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); break; case DBTerrainRevision.Compressed2D: @@ -414,7 +444,7 @@ namespace OpenSim.Framework float val = (float)br.ReadDouble(); if (xx < SizeX && yy < SizeY) - m_heightmap[xx, yy] = ToCompressedHeight(val); + m_heightmap[xx, yy] = val; } } } @@ -427,53 +457,33 @@ namespace OpenSim.Framework ClearTaint(); } - public Array ToCompressedTerrainSerialization2D() - { - Array ret = null; - try - { - using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) - { - using (BinaryWriter bw = new BinaryWriter(str)) - { - bw.Write((Int32)DBTerrainRevision.Compressed2D); - bw.Write((Int32)SizeX); - bw.Write((Int32)SizeY); - bw.Write((Int32)CompressionFactor); - for (int yy = 0; yy < SizeY; yy++) - for (int xx = 0; xx < SizeX; xx++) - { - bw.Write((Int16)m_heightmap[xx, yy]); - } - } - ret = str.ToArray(); - } - } - catch - { - } - return ret; - } + // stores as variable2D + // int32 format + // int32 sizeX + // int32 sizeY + // float[,] array - // See the reader below. - public Array ToCompressedTerrainSerialization() + // may have endian issues like older + + public Array ToCompressedTerrainSerializationV2D() { Array ret = null; try { - using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) + using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) { using (BinaryWriter bw = new BinaryWriter(str)) { - bw.Write((Int32)DBTerrainRevision.Compressed2Du); + bw.Write((Int32)DBTerrainRevision.Variable2D); bw.Write((Int32)SizeX); bw.Write((Int32)SizeY); - bw.Write((Int32)CompressionFactor); for (int yy = 0; yy < SizeY; yy++) for (int xx = 0; xx < SizeX; xx++) { - bw.Write((ushort)m_heightmap[xx, yy]); + // reduce to 1cm resolution + float val = (float)Math.Round(m_heightmap[xx, yy],2,MidpointRounding.ToEven); + bw.Write(val); } } ret = str.ToArray(); @@ -487,27 +497,26 @@ namespace OpenSim.Framework } // as above with Gzip compression - public Array ToCompressedTerrainSerializationGzip() + public Array ToCompressedTerrainSerializationV2DGzip() { Array ret = null; try { - using (MemoryStream inp = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) + using (MemoryStream inp = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) { using (BinaryWriter bw = new BinaryWriter(inp)) { - bw.Write((Int32)DBTerrainRevision.Compressed2DuGzip); + bw.Write((Int32)DBTerrainRevision.Variable2DGzip); bw.Write((Int32)SizeX); bw.Write((Int32)SizeY); - bw.Write((Int32)CompressionFactor); for (int yy = 0; yy < SizeY; yy++) for (int xx = 0; xx < SizeX; xx++) { - bw.Write((ushort)m_heightmap[xx, yy]); + bw.Write((float)m_heightmap[xx, yy]); } bw.Flush(); - inp.Seek(0,SeekOrigin.Begin); + inp.Seek(0, SeekOrigin.Begin); using (MemoryStream outputStream = new MemoryStream()) { @@ -525,7 +534,7 @@ namespace OpenSim.Framework { } - m_log.InfoFormat("{0} terrain GZiped to {1} bytes (compressed2Dus)", + m_log.InfoFormat("{0} terrain GZiped to {1} bytes (V2DGzip)", LogHeader, ret.Length); return ret; } @@ -558,11 +567,9 @@ namespace OpenSim.Framework { for (int xx = 0; xx < hmSizeX; xx++) { - short val = br.ReadInt16(); - if (val < 0) - val = 0; + float val = FromCompressedHeight(br.ReadInt16()); if (xx < SizeX && yy < SizeY) - m_heightmap[xx, yy] = (ushort)val; + m_heightmap[xx, yy] = val; } } } @@ -579,7 +586,7 @@ namespace OpenSim.Framework // the forth int is the compression factor for the following int16s // This is just sets heightmap info. The actual size of the region was set on this instance's // creation and any heights not initialized by theis blob are set to the default height. - public void FromCompressedTerrainSerialization(byte[] pBlob) + public void FromCompressedTerrainSerialization2Du(byte[] pBlob) { Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; try @@ -602,7 +609,7 @@ namespace OpenSim.Framework { for (int xx = 0; xx < hmSizeX; xx++) { - ushort val = br.ReadUInt16(); + float val = FromCompressedHeight(br.ReadUInt16()); if (xx < SizeX && yy < SizeY) m_heightmap[xx, yy] = val; } @@ -614,7 +621,7 @@ namespace OpenSim.Framework { ClearTaint(); m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged", - LogHeader,e.Message); + LogHeader, e.Message); return; } ClearTaint(); @@ -625,10 +632,86 @@ namespace OpenSim.Framework } // as above but Gzip compressed - public void FromCompressedTerrainSerializationGZip(byte[] pBlob) + public void FromCompressedTerrainSerialization2DuGZip(byte[] pBlob) + { + m_log.InfoFormat("{0} GZip {1} bytes for terrain", + LogHeader, pBlob.Length); + byte[] gzipout = null; + try + { + using (MemoryStream inputStream = new MemoryStream(pBlob)) + { + using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) + { + using (MemoryStream outputStream = new MemoryStream()) + { + decompressionStream.Flush(); + decompressionStream.CopyTo(outputStream); + gzipout = outputStream.ToArray(); + } + } + } + } + catch + { + } + + FromCompressedTerrainSerialization2Du(gzipout); + } + + // Initialize heightmap from blob consisting of: + // int32, int32, int32, int32, ushort[] + // where the first int32 is format code, next two int32s are the X and y of heightmap data and + // the forth int is the compression factor for the following int16s + // This is just sets heightmap info. The actual size of the region was set on this instance's + // creation and any heights not initialized by theis blob are set to the default height. + public void FromCompressedTerrainSerializationV2D(byte[] pBlob) + { + Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; + try + { + using (MemoryStream mstr = new MemoryStream(pBlob)) + { + using (BinaryReader br = new BinaryReader(mstr)) + { + hmFormatCode = br.ReadInt32(); + hmSizeX = br.ReadInt32(); + hmSizeY = br.ReadInt32(); + + // In case database info doesn't match real terrain size, initialize the whole terrain. + ClearLand(); + + for (int yy = 0; yy < hmSizeY; yy++) + { + for (int xx = 0; xx < hmSizeX; xx++) + { + float val = br.ReadSingle(); + if (xx < SizeX && yy < SizeY) + m_heightmap[xx, yy] = val; + } + } + } + } + } + catch (Exception e) + { + ClearTaint(); + m_log.ErrorFormat("{0} Read (Variable size format) terrain error: {1} - terrain may be damaged", + LogHeader, e.Message); + return; + } + ClearTaint(); + + m_log.InfoFormat("{0} Read Variable size format terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>", + LogHeader, hmSizeX, hmSizeY, SizeX, SizeY); + + } + // as above but Gzip compressed + public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob) { m_log.InfoFormat("{0} GZip {1} bytes for terrain", - LogHeader,pBlob.Length); + LogHeader, pBlob.Length); + byte[] gzipout = null; try { @@ -649,7 +732,7 @@ namespace OpenSim.Framework { } - FromCompressedTerrainSerialization(gzipout); + FromCompressedTerrainSerializationV2D(gzipout); } } } -- cgit v1.1 From ef3deffeeb0664443f7bef6cc7f2f6844355364b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 25 Aug 2015 17:54:49 +0100 Subject: remove rest of ushort test code --- OpenSim/Framework/TerrainData.cs | 125 ++++++++++----------------------------- 1 file changed, 31 insertions(+), 94 deletions(-) (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index 976c1f0..c66c1ad 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -108,12 +108,6 @@ namespace OpenSim.Framework // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. Compressed2D = 27, - // as Compressed2D but using ushort[] in place of int16[] - Compressed2Du = 28, - - // as Compressed2D but using ushort[] in place of int16[] with Gzip compression - Compressed2DuGzip = 29, - // A revision that is not listed above or any revision greater than this value is 'Legacy256'. RevisionHigh = 1234 } @@ -373,21 +367,12 @@ namespace OpenSim.Framework { case DBTerrainRevision.Variable2DGzip: FromCompressedTerrainSerializationV2DGZip(pBlob); - m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2DGzip serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); break; case DBTerrainRevision.Variable2D: FromCompressedTerrainSerializationV2D(pBlob); - m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); - break; - - case DBTerrainRevision.Compressed2DuGzip: - FromCompressedTerrainSerialization2DuGZip(pBlob); - m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); - break; - case DBTerrainRevision.Compressed2Du: - FromCompressedTerrainSerialization2D(pBlob); - m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); + m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); break; case DBTerrainRevision.Compressed2D: FromCompressedTerrainSerialization2D(pBlob); @@ -425,7 +410,7 @@ namespace OpenSim.Framework return ret; } - // Just create an array of doubles. Presumes the caller implicitly knows the size. + // Presumes the caller implicitly knows the size. public void FromLegacyTerrainSerialization(byte[] pBlob) { // In case database info doesn't match real terrain size, initialize the whole terrain. @@ -464,8 +449,6 @@ namespace OpenSim.Framework // int32 sizeY // float[,] array - // may have endian issues like older - public Array ToCompressedTerrainSerializationV2D() { Array ret = null; @@ -493,6 +476,10 @@ namespace OpenSim.Framework { } + + m_log.DebugFormat("{0} V2D {1} bytes", + LogHeader, ret.Length); + return ret; } @@ -534,7 +521,7 @@ namespace OpenSim.Framework { } - m_log.InfoFormat("{0} terrain GZiped to {1} bytes (V2DGzip)", + m_log.DebugFormat("{0} V2DGzip {1} bytes", LogHeader, ret.Length); return ret; } @@ -575,20 +562,19 @@ namespace OpenSim.Framework } ClearTaint(); - m_log.InfoFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", + m_log.DebugFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); } } // Initialize heightmap from blob consisting of: - // int32, int32, int32, int32, ushort[] - // where the first int32 is format code, next two int32s are the X and y of heightmap data and - // the forth int is the compression factor for the following int16s + // int32, int32, int32, float[] + // where the first int32 is format code, next two int32s are the X and y of heightmap data // This is just sets heightmap info. The actual size of the region was set on this instance's // creation and any heights not initialized by theis blob are set to the default height. - public void FromCompressedTerrainSerialization2Du(byte[] pBlob) + public void FromCompressedTerrainSerializationV2D(byte[] pBlob) { - Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; + Int32 hmFormatCode, hmSizeX, hmSizeY; try { using (MemoryStream mstr = new MemoryStream(pBlob)) @@ -598,9 +584,6 @@ namespace OpenSim.Framework hmFormatCode = br.ReadInt32(); hmSizeX = br.ReadInt32(); hmSizeY = br.ReadInt32(); - hmCompressionFactor = br.ReadInt32(); - - m_compressionFactor = hmCompressionFactor; // In case database info doesn't match real terrain size, initialize the whole terrain. ClearLand(); @@ -609,7 +592,7 @@ namespace OpenSim.Framework { for (int xx = 0; xx < hmSizeX; xx++) { - float val = FromCompressedHeight(br.ReadUInt16()); + float val = br.ReadSingle(); if (xx < SizeX && yy < SizeY) m_heightmap[xx, yy] = val; } @@ -620,59 +603,41 @@ namespace OpenSim.Framework catch (Exception e) { ClearTaint(); - m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged", + m_log.ErrorFormat("{0} 2D error: {1} - terrain may be damaged", LogHeader, e.Message); return; } ClearTaint(); - m_log.InfoFormat("{0} Read compressed2D terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", - LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); + m_log.DebugFormat("{0} V2D Heightmap size=<{1},{2}>. Region size=<{3},{4}>", + LogHeader, hmSizeX, hmSizeY, SizeX, SizeY); } // as above but Gzip compressed - public void FromCompressedTerrainSerialization2DuGZip(byte[] pBlob) + public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob) { - m_log.InfoFormat("{0} GZip {1} bytes for terrain", + m_log.InfoFormat("{0} VD2Gzip {1} bytes input", LogHeader, pBlob.Length); - byte[] gzipout = null; + + Int32 hmFormatCode, hmSizeX, hmSizeY; + try { - using (MemoryStream inputStream = new MemoryStream(pBlob)) + using (MemoryStream outputStream = new MemoryStream()) { - using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) + using (MemoryStream inputStream = new MemoryStream(pBlob)) { - using (MemoryStream outputStream = new MemoryStream()) + using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) { decompressionStream.Flush(); decompressionStream.CopyTo(outputStream); - gzipout = outputStream.ToArray(); } } - } - } - catch - { - } - FromCompressedTerrainSerialization2Du(gzipout); - } + outputStream.Seek(0, SeekOrigin.Begin); - // Initialize heightmap from blob consisting of: - // int32, int32, int32, int32, ushort[] - // where the first int32 is format code, next two int32s are the X and y of heightmap data and - // the forth int is the compression factor for the following int16s - // This is just sets heightmap info. The actual size of the region was set on this instance's - // creation and any heights not initialized by theis blob are set to the default height. - public void FromCompressedTerrainSerializationV2D(byte[] pBlob) - { - Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; - try - { - using (MemoryStream mstr = new MemoryStream(pBlob)) - { - using (BinaryReader br = new BinaryReader(mstr)) + using (BinaryReader br = new BinaryReader(outputStream)) { hmFormatCode = br.ReadInt32(); hmSizeX = br.ReadInt32(); @@ -693,46 +658,18 @@ namespace OpenSim.Framework } } } - catch (Exception e) + catch( Exception e) { ClearTaint(); - m_log.ErrorFormat("{0} Read (Variable size format) terrain error: {1} - terrain may be damaged", + m_log.ErrorFormat("{0} V2DGzip error: {1} - terrain may be damaged", LogHeader, e.Message); return; } - ClearTaint(); - m_log.InfoFormat("{0} Read Variable size format terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>", + ClearTaint(); + m_log.DebugFormat("{0} V2DGzip. Heightmap size=<{1},{2}>. Region size=<{3},{4}>", LogHeader, hmSizeX, hmSizeY, SizeX, SizeY); } - // as above but Gzip compressed - public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob) - { - m_log.InfoFormat("{0} GZip {1} bytes for terrain", - LogHeader, pBlob.Length); - - byte[] gzipout = null; - try - { - using (MemoryStream inputStream = new MemoryStream(pBlob)) - { - using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) - { - using (MemoryStream outputStream = new MemoryStream()) - { - decompressionStream.Flush(); - decompressionStream.CopyTo(outputStream); - gzipout = outputStream.ToArray(); - } - } - } - } - catch - { - } - - FromCompressedTerrainSerializationV2D(gzipout); - } } } -- cgit v1.1 From c7f148ee6410700a11bbf1439e1fd5788dc70f51 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 27 Aug 2015 14:13:23 +0100 Subject: minor clear. Use isTainted in is read clear form --- OpenSim/Framework/TerrainData.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'OpenSim/Framework/TerrainData.cs') diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index c66c1ad..d2e1c6a 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -189,6 +189,8 @@ namespace OpenSim.Framework } // Old form that clears the taint flag when we check it. + // ubit: this dangerus naming should be only check without clear + // keeping for old modules outthere public override bool IsTaintedAt(int xx, int yy) { return IsTaintedAt(xx, yy, true /* clearOnTest */); @@ -208,7 +210,9 @@ namespace OpenSim.Framework else { DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip; +// DBRevisionCode = (int)DBTerrainRevision.Variable2D; blob = ToCompressedTerrainSerializationV2DGzip(); +// blob = ToCompressedTerrainSerializationV2D(); ret = true; } return ret; @@ -444,7 +448,6 @@ namespace OpenSim.Framework // stores as variable2D - // int32 format // int32 sizeX // int32 sizeY // float[,] array @@ -454,11 +457,10 @@ namespace OpenSim.Framework Array ret = null; try { - using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) + using (MemoryStream str = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) { using (BinaryWriter bw = new BinaryWriter(str)) { - bw.Write((Int32)DBTerrainRevision.Variable2D); bw.Write((Int32)SizeX); bw.Write((Int32)SizeY); for (int yy = 0; yy < SizeY; yy++) @@ -489,11 +491,10 @@ namespace OpenSim.Framework Array ret = null; try { - using (MemoryStream inp = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) + using (MemoryStream inp = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) { using (BinaryWriter bw = new BinaryWriter(inp)) { - bw.Write((Int32)DBTerrainRevision.Variable2DGzip); bw.Write((Int32)SizeX); bw.Write((Int32)SizeY); for (int yy = 0; yy < SizeY; yy++) @@ -574,14 +575,13 @@ namespace OpenSim.Framework // creation and any heights not initialized by theis blob are set to the default height. public void FromCompressedTerrainSerializationV2D(byte[] pBlob) { - Int32 hmFormatCode, hmSizeX, hmSizeY; + Int32 hmSizeX, hmSizeY; try { using (MemoryStream mstr = new MemoryStream(pBlob)) { using (BinaryReader br = new BinaryReader(mstr)) { - hmFormatCode = br.ReadInt32(); hmSizeX = br.ReadInt32(); hmSizeY = br.ReadInt32(); @@ -620,7 +620,7 @@ namespace OpenSim.Framework m_log.InfoFormat("{0} VD2Gzip {1} bytes input", LogHeader, pBlob.Length); - Int32 hmFormatCode, hmSizeX, hmSizeY; + Int32 hmSizeX, hmSizeY; try { @@ -639,7 +639,6 @@ namespace OpenSim.Framework using (BinaryReader br = new BinaryReader(outputStream)) { - hmFormatCode = br.ReadInt32(); hmSizeX = br.ReadInt32(); hmSizeY = br.ReadInt32(); -- cgit v1.1