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
0.8.0.3
Justin Clark-Casey (justincc) 2014-04-25 22:37:58 +01:00
parent a108fcac95
commit 904baa6da6
2 changed files with 19 additions and 19 deletions

View File

@ -72,8 +72,8 @@ namespace OpenSim.Framework
return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob); return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
} }
// return a special compressed representation of the heightmap in shorts // return a special compressed representation of the heightmap in ints
public abstract short[] GetCompressedMap(); public abstract int[] GetCompressedMap();
public abstract float CompressionFactor { get; } public abstract float CompressionFactor { get; }
public abstract float[] GetFloatsSerialized(); public abstract float[] GetFloatsSerialized();
@ -99,7 +99,7 @@ namespace OpenSim.Framework
Variable2D = 22, Variable2D = 22,
// Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions // 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 // 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. // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
Compressed2D = 27, Compressed2D = 27,
// A revision that is not listed above or any revision greater than this value is 'Legacy256'. // 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. // Version of terrain that is a heightmap.
// This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
// of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. // 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 // The heighmap is kept as an array of integers. The integer values are converted to
// and from floats by TerrainCompressionFactor. Shorts are used to limit storage used. // and from floats by TerrainCompressionFactor.
public class HeightmapTerrainData : TerrainData public class HeightmapTerrainData : TerrainData
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 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]); } get { return FromCompressedHeight(m_heightmap[x, y]); }
set { set {
short newVal = ToCompressedHeight(value); int newVal = ToCompressedHeight(value);
if (m_heightmap[x, y] != newVal) if (m_heightmap[x, y] != newVal)
{ {
m_heightmap[x, y] = newVal; m_heightmap[x, y] = newVal;
@ -164,7 +164,7 @@ namespace OpenSim.Framework
// TerrainData.ClearLand(float) // TerrainData.ClearLand(float)
public override void ClearLand(float pHeight) public override void ClearLand(float pHeight)
{ {
short flatHeight = ToCompressedHeight(pHeight); int flatHeight = ToCompressedHeight(pHeight);
for (int xx = 0; xx < SizeX; xx++) for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++) for (int yy = 0; yy < SizeY; yy++)
m_heightmap[xx, yy] = flatHeight; m_heightmap[xx, yy] = flatHeight;
@ -214,9 +214,9 @@ namespace OpenSim.Framework
public override float CompressionFactor { get { return m_compressionFactor; } } public override float CompressionFactor { get { return m_compressionFactor; } }
// TerrainData.GetCompressedMap // 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; int ind = 0;
for (int xx = 0; xx < SizeX; xx++) for (int xx = 0; xx < SizeX; xx++)
@ -230,7 +230,7 @@ namespace OpenSim.Framework
public override TerrainData Clone() public override TerrainData Clone()
{ {
HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); 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; 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. // Remember subregions of the heightmap that has changed.
private bool[,] m_taint; private bool[,] m_taint;
// To save space (especially for large regions), keep the height as a short integer // 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' // that is coded as the float height times the compression factor (usually '100'
// to make for two decimal points). // 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; return ((float)pHeight) / CompressionFactor;
} }
@ -293,7 +293,7 @@ namespace OpenSim.Framework
SizeZ = (int)Constants.RegionHeight; SizeZ = (int)Constants.RegionHeight;
m_compressionFactor = 100.0f; 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 ii = 0; ii < SizeX; ii++)
{ {
for (int jj = 0; jj < SizeY; jj++) for (int jj = 0; jj < SizeY; jj++)
@ -315,14 +315,14 @@ namespace OpenSim.Framework
SizeY = pY; SizeY = pY;
SizeZ = pZ; SizeZ = pZ;
m_compressionFactor = 100.0f; 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_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); // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
ClearTaint(); ClearTaint();
ClearLand(0f); 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; m_compressionFactor = pCompressionFactor;
int ind = 0; int ind = 0;

View File

@ -363,8 +363,8 @@ namespace OpenSim.Region.Framework.Scenes
public int SizeY; public int SizeY;
public int SizeZ; public int SizeZ;
public float CompressionFactor; public float CompressionFactor;
public short[] Map; public int[] Map;
public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap) public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap)
{ {
Version = 1; Version = 1;
SizeX = pX; SizeX = pX;