From ff5885ab234bc9a7efda49eea0e2200711c4933c Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Fri, 1 Nov 2013 11:35:31 -0700
Subject: varregion: push TerrainData implementation up and down the database
storage stack. Implement both LoadTerrain and StoreTerrain for all DBs. Move
all database blob serialization/deserialization into TerrainData.
---
OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 62 +++----
OpenSim/Data/MySQL/MySQLSimulationData.cs | 32 ++--
OpenSim/Data/Null/NullSimulationData.cs | 21 ++-
OpenSim/Data/PGSQL/PGSQLSimulationData.cs | 48 ++---
OpenSim/Data/SQLite/SQLiteSimulationData.cs | 29 ++--
OpenSim/Framework/TerrainData.cs | 193 ++++++++++++++++++---
.../Framework/Interfaces/ISimulationDataService.cs | 9 +
.../Framework/Interfaces/ISimulationDataStore.cs | 9 +
OpenSim/Region/Framework/Scenes/Scene.cs | 4 +-
OpenSim/Region/Framework/Scenes/TerrainChannel.cs | 27 ++-
.../Connectors/Simulation/SimulationDataService.cs | 10 ++
OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs | 29 +++-
12 files changed, 343 insertions(+), 130 deletions(-)
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index dbfd16c..9f5991b 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -531,43 +531,43 @@ ELSE
///
public double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ return terrData.GetDoubles();
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc";
using (SqlConnection conn = new SqlConnection(m_connectionString))
- using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- // MySqlParameter param = new MySqlParameter();
- cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
- conn.Open();
- using (SqlDataReader reader = cmd.ExecuteReader())
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- int rev;
- if (reader.Read())
+ // MySqlParameter param = new MySqlParameter();
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
+ conn.Open();
+ using (SqlDataReader reader = cmd.ExecuteReader())
{
- MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
- BinaryReader br = new BinaryReader(str);
- for (int x = 0; x < (int)Constants.RegionSize; x++)
+ int rev;
+ if (reader.Read())
{
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
+ rev = (int)reader["Revision"];
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
- rev = (int)reader["Revision"];
- }
- else
- {
- _Log.Info("[REGION DB]: No terrain found for region");
- return null;
+ else
+ {
+ _Log.Info("[REGION DB]: No terrain found for region");
+ return null;
+ }
+ _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
- _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
}
- return terrain;
+ return terrData;
}
// Legacy entry point for when terrain was always a 256x256 hieghtmap
@@ -600,13 +600,15 @@ ELSE
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
using (SqlConnection conn = new SqlConnection(m_connectionString))
- using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
- cmd.Parameters.Add(_Database.CreateParameter("@Revision", terrainDBRevision));
- cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", terrainDBblob));
- conn.Open();
- cmd.ExecuteNonQuery();
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
+ cmd.Parameters.Add(_Database.CreateParameter("@Revision", terrainDBRevision));
+ cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", terrainDBblob));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
}
_Log.InfoFormat("{0} Stored terrain revision r={1}", LogHeader, terrainDBRevision);
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 4bd8617..42f2ebb 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -613,9 +613,16 @@ namespace OpenSim.Data.MySQL
}
}
+ // Legacy region loading
public double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = null;
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ return terrData.GetDoubles();
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
lock (m_dbLock)
{
@@ -635,32 +642,15 @@ namespace OpenSim.Data.MySQL
while (reader.Read())
{
int rev = Convert.ToInt32(reader["Revision"]);
-
- terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
-
- using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"]))
- {
- using (BinaryReader br = new BinaryReader(mstr))
- {
- for (int x = 0; x < (int)Constants.RegionSize; x++)
- {
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
- }
- }
-
- m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev);
- }
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
}
}
}
}
- return terrain;
+ return terrData;
}
public void RemoveLandObject(UUID globalID)
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index d11ad72..acde1a1 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -132,18 +132,35 @@ namespace OpenSim.Data.Null
return new List();
}
- Dictionary m_terrains = new Dictionary();
- public void StoreTerrain(double[,] ter, UUID regionID)
+ Dictionary m_terrains = new Dictionary();
+ public void StoreTerrain(TerrainData ter, UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
m_terrains.Remove(regionID);
m_terrains.Add(regionID, ter);
}
+ // Legacy. Just don't do this.
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ TerrainData terrData = new HeightmapTerrainData(ter);
+ StoreTerrain(terrData, regionID);
+ }
+
+ // Legacy. Just don't do this.
public double[,] LoadTerrain(UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
{
+ return m_terrains[regionID].GetDoubles();
+ }
+ return null;
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ if (m_terrains.ContainsKey(regionID))
+ {
return m_terrains[regionID];
}
return null;
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 433ffe9..34eb038 100644
--- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -524,44 +524,44 @@ namespace OpenSim.Data.PGSQL
///
public double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ return terrData.GetDoubles();
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain
where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; ";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
- using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
- // PGSqlParameter param = new PGSqlParameter();
- cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
- conn.Open();
- using (NpgsqlDataReader reader = cmd.ExecuteReader())
+ using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
- int rev;
- if (reader.Read())
+ // PGSqlParameter param = new PGSqlParameter();
+ cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
+ conn.Open();
+ using (NpgsqlDataReader reader = cmd.ExecuteReader())
{
- MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
- BinaryReader br = new BinaryReader(str);
- for (int x = 0; x < (int)Constants.RegionSize; x++)
+ int rev;
+ if (reader.Read())
{
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
+ rev = Convert.ToInt32(reader["Revision"]);
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
- rev = (int)reader["Revision"];
- }
- else
- {
- _Log.Info("[REGION DB]: No terrain found for region");
- return null;
+ else
+ {
+ _Log.Info("[REGION DB]: No terrain found for region");
+ return null;
+ }
+ _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
- _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
}
- return terrain;
+ return terrData;
}
// Legacy entry point for when terrain was always a 256x256 heightmap
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index cce59c1..dac4450 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -870,11 +870,16 @@ namespace OpenSim.Data.SQLite
/// Heightfield data
public double[,] LoadTerrain(UUID regionID)
{
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ return terrData.GetDoubles();
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
+
lock (ds)
{
- double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terret.Initialize();
-
String sql = "select RegionUUID, Revision, Heightfield from terrain" +
" where RegionUUID=:RegionUUID order by Revision desc";
@@ -887,21 +892,9 @@ namespace OpenSim.Data.SQLite
int rev = 0;
if (row.Read())
{
- // TODO: put this into a function
- using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"]))
- {
- using (BinaryReader br = new BinaryReader(str))
- {
- for (int x = 0; x < (int)Constants.RegionSize; x++)
- {
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terret[x, y] = br.ReadDouble();
- }
- }
- }
- }
rev = Convert.ToInt32(row["Revision"]);
+ byte[] blob = (byte[])row["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
else
{
@@ -912,8 +905,8 @@ namespace OpenSim.Data.SQLite
m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString());
}
}
- return terret;
}
+ return terrData;
}
public void RemoveLandObject(UUID globalID)
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index d7f1655..58b203f 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -43,6 +43,9 @@ namespace OpenSim.Framework
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; }
@@ -51,15 +54,28 @@ namespace OpenSim.Framework
public abstract bool IsTaintedAt(int xx, int yy);
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 shorts
public abstract short[] GetCompressedMap();
public abstract float CompressionFactor { get; }
- public abstract void SetCompressedMap(short[] cmap, float pCompressionFactor);
+ public abstract double[,] GetDoubles();
public abstract TerrainData Clone();
}
@@ -76,9 +92,14 @@ namespace OpenSim.Framework
{
// Terrain is 'double[256,256]'
Legacy256 = 11,
- // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions
+ // 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
+ // "short compressedHeight = (short)(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
}
@@ -124,6 +145,20 @@ namespace OpenSim.Framework
m_taint[ii, jj] = false;
}
+ // TerrainData.ClearLand
+ public override void ClearLand()
+ {
+ ClearLand(DefaultTerrainHeight);
+ }
+ // TerrainData.ClearLand(float)
+ public override void ClearLand(float pHeight)
+ {
+ short flatHeight = ToCompressedHeight(pHeight);
+ for (int xx = 0; xx < SizeX; xx++)
+ for (int yy = 0; yy < SizeY; yy++)
+ m_heightmap[xx, yy] = flatHeight;
+ }
+
public override bool IsTaintedAt(int xx, int yy)
{
return m_taint[xx / Constants.TerrainPatchSize, yy / Constants.TerrainPatchSize];
@@ -134,7 +169,7 @@ namespace OpenSim.Framework
public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
{
DBRevisionCode = (int)DBTerrainRevision.Legacy256;
- blob = LegacyTerrainSerialization();
+ blob = ToLegacyTerrainSerialization();
return false;
}
@@ -155,17 +190,6 @@ namespace OpenSim.Framework
return newMap;
}
- // 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++)
- m_heightmap[xx, yy] = cmap[ind++];
- }
-
// TerrainData.Clone
public override TerrainData Clone()
{
@@ -174,6 +198,18 @@ namespace OpenSim.Framework
return ret;
}
+ // 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 short[,] m_heightmap;
@@ -230,31 +266,140 @@ namespace OpenSim.Framework
public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
{
- SetCompressedMap(cmap, pCompressionFactor);
+ 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++];
}
+ // 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);
+ break;
+ default:
+ FromLegacyTerrainSerialization(pBlob);
+ break;
+ }
+ }
// Just create an array of doubles. Presumes the caller implicitly knows the size.
- public Array LegacyTerrainSerialization()
+ public Array ToLegacyTerrainSerialization()
{
Array ret = null;
- using (MemoryStream str = new MemoryStream(SizeX * SizeY * sizeof(double)))
+
+ using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double)))
{
using (BinaryWriter bw = new BinaryWriter(str))
{
- // TODO: COMPATIBILITY - Add byte-order conversions
- for (int ii = 0; ii < SizeX; ii++)
- for (int jj = 0; jj < SizeY; jj++)
+ for (int xx = 0; xx < Constants.RegionSize; xx++)
{
- double height = this[ii, jj];
- if (height == 0.0)
- height = double.Epsilon;
- bw.Write(height);
+ 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();
+
+ m_log.InfoFormat("{0} Loaded legacy heightmap. SizeX={1}, SizeY={2}", LogHeader, SizeX, SizeY);
+ }
+ }
+
+ // 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] = ToCompressedHeight(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);
+ }
+ }
}
}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 085b5ca..8948f04 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
///
/// HeightField data
/// region UUID
+ void StoreTerrain(TerrainData terrain, UUID regionID);
+
+ // Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
///
/// Load the latest terrain revision from region storage
///
/// the region UUID
+ /// the X dimension of the region being filled
+ /// the Y dimension of the region being filled
+ /// the Z dimension of the region being filled
/// Heightfield data
+ TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
+
+ // Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 5ba5b31..917b5d1 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
///
/// HeightField data
/// region UUID
+ void StoreTerrain(TerrainData terrain, UUID regionID);
+
+ // Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
///
/// Load the latest terrain revision from region storage
///
/// the region UUID
+ /// the X dimension of the terrain being filled
+ /// the Y dimension of the terrain being filled
+ /// the Z dimension of the terrain being filled
/// Heightfield data
+ TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
+
+ // Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e2880e3..a19f31f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1894,7 +1894,7 @@ namespace OpenSim.Region.Framework.Scenes
{
try
{
- double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID);
+ TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
if (map == null)
{
// This should be in the Terrain module, but it isn't because
@@ -1911,7 +1911,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- Heightmap = new TerrainChannel(map, RegionInfo.RegionSizeZ);
+ Heightmap = new TerrainChannel(map);
}
}
catch (IOException e)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index d641c87..03499e8 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -80,9 +80,26 @@ namespace OpenSim.Region.Framework.Scenes
PinHeadIsland();
}
- public TerrainChannel(double[,] pM, uint pAltitude)
+ // Create channel passed a heightmap and expected dimensions of the region.
+ // The heightmap might not fit the passed size so accomodations must be made.
+ public TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
{
- m_terrainData = new HeightmapTerrainData(pM);
+ int hmSizeX = pM.GetLength(0);
+ int hmSizeY = pM.GetLength(1);
+
+ m_terrainData = new HeightmapTerrainData(pSizeX, pSizeY, pAltitude);
+
+ for (int xx = 0; xx < pSizeX; xx++)
+ for (int yy = 0; yy < pSizeY; yy++)
+ if (xx > hmSizeX || yy > hmSizeY)
+ m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
+ else
+ m_terrainData[xx, yy] = (float)pM[xx, yy];
+ }
+
+ public TerrainChannel(TerrainData pTerrData)
+ {
+ m_terrainData = pTerrData;
}
#region ITerrainChannel Members
@@ -247,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes
byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
int index = 0;
- m_terrainData = new HeightmapTerrainData(Width, Height, Altitude);
+ m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
for (int y = 0; y < Height; y++)
{
@@ -317,9 +334,7 @@ namespace OpenSim.Region.Framework.Scenes
private void FlatLand()
{
- for (int xx = 0; xx < Width; xx++)
- for (int yy = 0; yy < Height; yy++)
- m_terrainData[xx, yy] = 21;
+ m_terrainData.ClearLand();
}
}
}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
index 504fcaf..2cbf967 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
@@ -100,6 +100,11 @@ namespace OpenSim.Services.Connectors
return m_database.LoadObjects(regionUUID);
}
+ public void StoreTerrain(TerrainData terrain, UUID regionID)
+ {
+ m_database.StoreTerrain(terrain, regionID);
+ }
+
public void StoreTerrain(double[,] terrain, UUID regionID)
{
m_database.StoreTerrain(terrain, regionID);
@@ -110,6 +115,11 @@ namespace OpenSim.Services.Connectors
return m_database.LoadTerrain(regionID);
}
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ return m_database.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ);
+ }
+
public void StoreLandObject(ILandObject Parcel)
{
m_database.StoreLandObject(Parcel);
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index ed29c39..5df8e04 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -69,11 +69,21 @@ namespace OpenSim.Data.Null
m_store.StoreTerrain(terrain, regionID);
}
+ public void StoreTerrain(TerrainData terrain, UUID regionID)
+ {
+ m_store.StoreTerrain(terrain, regionID);
+ }
+
public double[,] LoadTerrain(UUID regionID)
{
return m_store.LoadTerrain(regionID);
}
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ return m_store.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ);
+ }
+
public void StoreLandObject(ILandObject Parcel)
{
m_store.StoreLandObject(Parcel);
@@ -154,7 +164,7 @@ namespace OpenSim.Data.Null
protected Dictionary m_sceneObjectParts = new Dictionary();
protected Dictionary> m_primItems
= new Dictionary>();
- protected Dictionary m_terrains = new Dictionary();
+ protected Dictionary m_terrains = new Dictionary();
protected Dictionary m_landData = new Dictionary();
public void Initialise(string dbfile)
@@ -299,12 +309,17 @@ namespace OpenSim.Data.Null
return new List(objects.Values);
}
- public void StoreTerrain(double[,] ter, UUID regionID)
+ public void StoreTerrain(TerrainData ter, UUID regionID)
{
m_terrains[regionID] = ter;
}
- public double[,] LoadTerrain(UUID regionID)
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ m_terrains[regionID] = new HeightmapTerrainData(ter);
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
if (m_terrains.ContainsKey(regionID))
return m_terrains[regionID];
@@ -312,6 +327,14 @@ namespace OpenSim.Data.Null
return null;
}
+ public double[,] LoadTerrain(UUID regionID)
+ {
+ if (m_terrains.ContainsKey(regionID))
+ return m_terrains[regionID].GetDoubles();
+ else
+ return null;
+ }
+
public void RemoveLandObject(UUID globalID)
{
if (m_landData.ContainsKey(globalID))
--
cgit v1.1