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 RegionSize = 256;
public const uint RegionHeight = 4096; 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 // 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 MinRegionSize = 16;
public const int TerrainPatchSize = 16; public const int TerrainPatchSize = 16;

View File

@ -28,9 +28,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection;
using OpenMetaverse; using OpenMetaverse;
using log4net;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
public abstract class TerrainData public abstract class TerrainData
@ -54,12 +57,13 @@ namespace OpenSim.Framework
// return a special compressed representation of the heightmap in shorts // return a special compressed representation of the heightmap in shorts
public abstract short[] GetCompressedMap(); 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(); 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 // Some implementations of terrain storage would fill the revision field with
// the time the terrain was stored. When real revisions were added and this // 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 // 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 // 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 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 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] // TerrainData.this[x, y]
public override float this[int x, int y] public override float this[int x, int y]
{ {
@ -96,7 +103,7 @@ namespace OpenSim.Framework
{ {
m_heightmap[x, y] = newVal; m_heightmap[x, y] = newVal;
m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; 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; return false;
} }
// TerrainData.CompressionFactor
private float m_compressionFactor = 100.0f;
public override float CompressionFactor { get { return m_compressionFactor; } }
// TerrainData.GetCompressedMap
public override short[] GetCompressedMap() public override short[] GetCompressedMap()
{ {
short[] newMap = new short[SizeX * SizeY]; short[] newMap = new short[SizeX * SizeY];
@ -143,8 +155,11 @@ namespace OpenSim.Framework
return newMap; return newMap;
} }
public override void SetCompressedMap(short[] cmap) // TerrainData.SetCompressedMap
public override void SetCompressedMap(short[] cmap, float pCompressionFactor)
{ {
m_compressionFactor = pCompressionFactor;
int ind = 0; int ind = 0;
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++)
@ -168,23 +183,24 @@ namespace OpenSim.Framework
// 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 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 // To keep with the legacy theme, create an instance of this class based on the
// used to passed around as. // way terrain used to be passed around.
public HeightmapTerrainData(double[,] pTerrain) public HeightmapTerrainData(double[,] pTerrain)
{ {
SizeX = pTerrain.GetLength(0); SizeX = pTerrain.GetLength(0);
SizeY = pTerrain.GetLength(1); SizeY = pTerrain.GetLength(1);
SizeZ = (int)Constants.RegionHeight; SizeZ = (int)Constants.RegionHeight;
m_compressionFactor = 100.0f;
m_heightmap = new short[SizeX, SizeY]; m_heightmap = new short[SizeX, SizeY];
for (int ii = 0; ii < SizeX; ii++) for (int ii = 0; ii < SizeX; ii++)
@ -206,14 +222,15 @@ namespace OpenSim.Framework
SizeX = pX; SizeX = pX;
SizeY = pY; SizeY = pY;
SizeZ = pZ; SizeZ = pZ;
m_compressionFactor = 100.0f;
m_heightmap = new short[SizeX, SizeY]; m_heightmap = new short[SizeX, SizeY];
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
ClearTaint(); 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 #endregion
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 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"); private readonly Commander m_commander = new Commander("terrain");
@ -712,7 +713,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void CheckForTerrainUpdates(bool respectEstateSettings) private void CheckForTerrainUpdates(bool respectEstateSettings)
{ {
bool shouldTaint = false; bool shouldTaint = false;
float[] terrData = m_channel.GetFloatsSerialised(); float[] terrHeights = m_channel.GetFloatsSerialised();
int x; int x;
for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) 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)) if (respectEstateSettings && LimitChannelChanges(x, y))
{ {
// Terrain heights were modified. Refetch the terrain info. // 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; shouldTaint = true;
} }
} }

View File

@ -183,21 +183,6 @@ namespace OpenSim.Region.Framework.Scenes
#endregion #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() public TerrainChannel Copy()
{ {
TerrainChannel copy = new TerrainChannel(); TerrainChannel copy = new TerrainChannel();
@ -280,13 +265,15 @@ namespace OpenSim.Region.Framework.Scenes
public int SizeX; public int SizeX;
public int SizeY; public int SizeY;
public int SizeZ; public int SizeZ;
public float CompressionFactor;
public short[] Map; 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; Version = 1;
SizeX = pX; SizeX = pX;
SizeY = pY; SizeY = pY;
SizeZ = pZ; SizeZ = pZ;
CompressionFactor = pCompressionFactor;
Map = pMap; Map = pMap;
} }
} }
@ -294,7 +281,8 @@ namespace OpenSim.Region.Framework.Scenes
// New terrain serialization format that includes the width and length. // New terrain serialization format that includes the width and length.
private void ToXml2(XmlWriter xmlWriter) 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)); XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
serializer.Serialize(xmlWriter, package); serializer.Serialize(xmlWriter, package);
} }
@ -304,7 +292,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage)); XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader); 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 // 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 // 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 // routines (like IClientAPI) only pass the float array of heights around. This entry
// converts that legacy representation into the more compact represenation used in // 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) public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
{ {
int[] xPieces = new int[1]; int[] xPieces = new int[1];