varregion: move the compressed heighmap compression factor from

Constants into TerrainData.
Save compression factor with the terrain blob in the database.
varregion
Robert Adams 2013-10-16 07:52:30 -07:00
parent 86bf79aa2b
commit 97bc5263de
5 changed files with 42 additions and 37 deletions

View File

@ -36,8 +36,6 @@ namespace OpenSim.Framework
public const uint RegionSize = 256;
public const uint RegionHeight = 4096;
// Terrain heightmap is kept as shorts that are the float value times this compression factor
public const float TerrainCompression = 100.0f;
// Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
public const int MinRegionSize = 16;
public const int TerrainPatchSize = 16;

View File

@ -28,9 +28,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using OpenMetaverse;
using log4net;
namespace OpenSim.Framework
{
public abstract class TerrainData
@ -54,12 +57,13 @@ namespace OpenSim.Framework
// return a special compressed representation of the heightmap in shorts
public abstract short[] GetCompressedMap();
public abstract void SetCompressedMap(short[] cmap);
public abstract float CompressionFactor { get; }
public abstract void SetCompressedMap(short[] cmap, float pCompressionFactor);
public abstract TerrainData Clone();
}
// The terrain is stored as a blob in the database with a 'revision' field.
// 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
@ -83,9 +87,12 @@ namespace OpenSim.Framework
// 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.
// and from floats by TerrainCompressionFactor. Shorts are used to limit storage used.
public class HeightmapTerrainData : TerrainData
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[TERRAIN DATA]";
// TerrainData.this[x, y]
public override float this[int x, int y]
{
@ -96,7 +103,7 @@ namespace OpenSim.Framework
{
m_heightmap[x, y] = newVal;
m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
m_log.DebugFormat("{0} set[{1},{2}] to {3} ({4})", LogHeader, x, y, value, newVal);
}
}
}
@ -131,6 +138,11 @@ namespace OpenSim.Framework
return false;
}
// TerrainData.CompressionFactor
private float m_compressionFactor = 100.0f;
public override float CompressionFactor { get { return m_compressionFactor; } }
// TerrainData.GetCompressedMap
public override short[] GetCompressedMap()
{
short[] newMap = new short[SizeX * SizeY];
@ -143,8 +155,11 @@ namespace OpenSim.Framework
return newMap;
}
public override void SetCompressedMap(short[] cmap)
// TerrainData.SetCompressedMap
public override void SetCompressedMap(short[] cmap, float pCompressionFactor)
{
m_compressionFactor = pCompressionFactor;
int ind = 0;
for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++)
@ -168,23 +183,24 @@ namespace OpenSim.Framework
// 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 static short ToCompressedHeight(double pHeight)
public short ToCompressedHeight(double pHeight)
{
return (short)(pHeight * Constants.TerrainCompression);
return (short)(pHeight * CompressionFactor);
}
public static float FromCompressedHeight(short pHeight)
public float FromCompressedHeight(short pHeight)
{
return ((float)pHeight) / Constants.TerrainCompression;
return ((float)pHeight) / CompressionFactor;
}
// To keep with the legacy theme, this can be created with the way terrain
// used to passed around as.
// 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 short[SizeX, SizeY];
for (int ii = 0; ii < SizeX; ii++)
@ -206,14 +222,15 @@ namespace OpenSim.Framework
SizeX = pX;
SizeY = pY;
SizeZ = pZ;
m_compressionFactor = 100.0f;
m_heightmap = new short[SizeX, SizeY];
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
ClearTaint();
}
public HeightmapTerrainData(short[] cmap, int pX, int pY, int pZ) : this(pX, pY, pZ)
public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
{
SetCompressedMap(cmap);
SetCompressedMap(cmap, pCompressionFactor);
}

View File

@ -74,6 +74,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
#endregion
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[TERRAIN MODULE]";
private readonly Commander m_commander = new Commander("terrain");
@ -712,7 +713,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void CheckForTerrainUpdates(bool respectEstateSettings)
{
bool shouldTaint = false;
float[] terrData = m_channel.GetFloatsSerialised();
float[] terrHeights = m_channel.GetFloatsSerialised();
int x;
for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
{
@ -727,10 +728,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (respectEstateSettings && LimitChannelChanges(x, y))
{
// Terrain heights were modified. Refetch the terrain info.
terrData = m_channel.GetFloatsSerialised();
terrHeights = m_channel.GetFloatsSerialised();
}
SendToClients(terrData, x, y);
// m_log.DebugFormat("{0} Patch modified. Sending (x,y) = ({1},{2})", LogHeader, x, y);
SendToClients(terrHeights, x, y);
shouldTaint = true;
}
}

View File

@ -183,21 +183,6 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
/*
// 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 static short ToCompressedHeight(double pHeight)
{
return (short)(pHeight * Constants.TerrainCompression);
}
public static float FromCompressedHeight(short pHeight)
{
return ((float)pHeight) / Constants.TerrainCompression;
}
*/
public TerrainChannel Copy()
{
TerrainChannel copy = new TerrainChannel();
@ -280,13 +265,15 @@ namespace OpenSim.Region.Framework.Scenes
public int SizeX;
public int SizeY;
public int SizeZ;
public float CompressionFactor;
public short[] Map;
public TerrainChannelXMLPackage(int pX, int pY, int pZ, short[] pMap)
public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
{
Version = 1;
SizeX = pX;
SizeY = pY;
SizeZ = pZ;
CompressionFactor = pCompressionFactor;
Map = pMap;
}
}
@ -294,7 +281,8 @@ namespace OpenSim.Region.Framework.Scenes
// New terrain serialization format that includes the width and length.
private void ToXml2(XmlWriter xmlWriter)
{
TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.GetCompressedMap());
TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
m_terrainData.GetCompressedMap());
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
serializer.Serialize(xmlWriter, package);
}
@ -304,7 +292,7 @@ namespace OpenSim.Region.Framework.Scenes
{
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
m_terrainData = new HeightmapTerrainData(package.Map, package.SizeX, package.SizeY, package.SizeZ);
m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
}
// Fill the heightmap with the center bump terrain

View File

@ -112,7 +112,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// This is an intermediate step in converting terrain into a variable sized heightmap. Some of the
// routines (like IClientAPI) only pass the float array of heights around. This entry
// converts that legacy representation into the more compact represenation used in
// TerrainChannel. Someday fix the plumbing between here and the scene.
// TerrainData. Someday fix the plumbing between here and the scene.
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
{
int[] xPieces = new int[1];