From 904baa6da6107c3aabfae45d977491b97c22a6ef Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Apr 2014 22:37:58 +0100 Subject: [PATCH] Fix issue where terrain height values > 327 caused chaotic spiked terrain. Per http://wiki.secondlife.com/wiki/Tips_for_Creating_Heightfields_and_Details_on_Terrain_RAW_Files#Notes_for_Creating_Height_Field_Maps_for_Second_Life terrain heights up to 508 are possible on the LL grid (and were available on previous releases of OpenSimulator). The obvious way to allow both this and equivalent -z values, is to rewiden the internal terrain height storage from short to int. The memory tradeoff is most noticeable on the maximum 8192x8192 var region (equiv to 1024 normal regions), where it adds 128mb to resident use (128k on a normal region) This is still better than the double used in previous releases. This does not affect physics or data storage since they already use float and double respectively. This may not be the final solution if we actually want to sacrifice -z, >327 or something else. Relates to http://opensimulator.org/mantis/view.php?id=7076 --- OpenSim/Framework/TerrainData.cs | 34 +++++++++---------- .../Region/Framework/Scenes/TerrainChannel.cs | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index 25f9ca699f..6b1be4e9fa 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 shorts - public abstract short[] GetCompressedMap(); + // return a special compressed representation of the heightmap in ints + public abstract int[] 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 - // "short compressedHeight = (short)(height * compressionFactor);" + // "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'. @@ -109,8 +109,8 @@ 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 short integers. The integer values are converted to - // and from floats by TerrainCompressionFactor. Shorts are used to limit storage used. + // 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); @@ -121,7 +121,7 @@ namespace OpenSim.Framework { get { return FromCompressedHeight(m_heightmap[x, y]); } set { - short newVal = ToCompressedHeight(value); + int 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) { - short flatHeight = ToCompressedHeight(pHeight); + int 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 short[] GetCompressedMap() + public override int[] GetCompressedMap() { - short[] newMap = new short[SizeX * SizeY]; + int[] newMap = new int[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 = (short[,])this.m_heightmap.Clone(); + ret.m_heightmap = (int[,])this.m_heightmap.Clone(); return ret; } @@ -267,19 +267,19 @@ namespace OpenSim.Framework // ============================================================= - private short[,] m_heightmap; + 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 short ToCompressedHeight(double pHeight) + public int ToCompressedHeight(double pHeight) { - return (short)(pHeight * CompressionFactor); + return (int)(pHeight * CompressionFactor); } - public float FromCompressedHeight(short pHeight) + public float FromCompressedHeight(int pHeight) { return ((float)pHeight) / CompressionFactor; } @@ -293,7 +293,7 @@ namespace OpenSim.Framework SizeZ = (int)Constants.RegionHeight; m_compressionFactor = 100.0f; - m_heightmap = new short[SizeX, SizeY]; + m_heightmap = new int[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 short[SizeX, SizeY]; + 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(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) + public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) { m_compressionFactor = pCompressionFactor; int ind = 0; diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs index cc040a66d7..3d563a6523 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs @@ -363,8 +363,8 @@ namespace OpenSim.Region.Framework.Scenes public int SizeY; public int SizeZ; public float CompressionFactor; - public short[] Map; - public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap) + public int[] Map; + public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap) { Version = 1; SizeX = pX;