Merge branch 'mbworkvar2' into ubitvar
commit
0b105da626
|
@ -1157,7 +1157,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
// Set home position
|
||||
|
||||
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
|
||||
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
|
||||
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
|
||||
if (null == home)
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", firstName, lastName);
|
||||
|
@ -1387,7 +1387,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
if ((null != regionXLocation) && (null != regionYLocation))
|
||||
{
|
||||
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
|
||||
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
|
||||
(int)Util.RegionToWorldLoc((uint)regionXLocation), (int)Util.RegionToWorldLoc((uint)regionYLocation));
|
||||
if (null == home) {
|
||||
m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstName, lastName);
|
||||
} else {
|
||||
|
@ -3118,7 +3118,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
// Set home position
|
||||
|
||||
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
|
||||
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
|
||||
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
|
||||
if (null == home) {
|
||||
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]);
|
||||
} else {
|
||||
|
|
|
@ -52,14 +52,14 @@ namespace OpenSim.Data
|
|||
public int sizeY;
|
||||
|
||||
/// <summary>
|
||||
/// Return the x-coordinate of this region.
|
||||
/// Return the x-coordinate of this region in region units.
|
||||
/// </summary>
|
||||
public int coordX { get { return posX / (int)Constants.RegionSize; } }
|
||||
public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } }
|
||||
|
||||
/// <summary>
|
||||
/// Return the y-coordinate of this region.
|
||||
/// Return the y-coordinate of this region in region units.
|
||||
/// </summary>
|
||||
public int coordY { get { return posY / (int)Constants.RegionSize; } }
|
||||
public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } }
|
||||
|
||||
public Dictionary<string, object> Data;
|
||||
}
|
||||
|
|
|
@ -530,43 +530,52 @@ ELSE
|
|||
/// <returns></returns>
|
||||
public double[,] LoadTerrain(UUID regionID)
|
||||
{
|
||||
double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
|
||||
terrain.Initialize();
|
||||
double[,] ret = null;
|
||||
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
|
||||
if (terrData != null)
|
||||
ret = terrData.GetDoubles();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns 'null' if region not found
|
||||
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++)
|
||||
if (reader.Read())
|
||||
{
|
||||
for (int y = 0; y < (int)Constants.RegionSize; y++)
|
||||
{
|
||||
terrain[x, y] = br.ReadDouble();
|
||||
}
|
||||
int 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;
|
||||
}
|
||||
_Log.Info("[REGION DB]: Loaded terrain");
|
||||
}
|
||||
else
|
||||
{
|
||||
_Log.Info("[REGION DB]: No terrain found for region");
|
||||
return null;
|
||||
}
|
||||
_Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
|
||||
}
|
||||
}
|
||||
|
||||
return terrain;
|
||||
return terrData;
|
||||
}
|
||||
|
||||
// Legacy entry point for when terrain was always a 256x256 hieghtmap
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
{
|
||||
StoreTerrain(new HeightmapTerrainData(ter), regionID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -574,10 +583,8 @@ ELSE
|
|||
/// </summary>
|
||||
/// <param name="terrain">terrain map data.</param>
|
||||
/// <param name="regionID">regionID.</param>
|
||||
public void StoreTerrain(double[,] terrain, UUID regionID)
|
||||
public void StoreTerrain(TerrainData terrData, UUID regionID)
|
||||
{
|
||||
int revision = Util.UnixTimeSinceEpoch();
|
||||
|
||||
//Delete old terrain map
|
||||
string sql = "delete from terrain where RegionUUID=@RegionUUID";
|
||||
using (SqlConnection conn = new SqlConnection(m_connectionString))
|
||||
|
@ -590,17 +597,23 @@ ELSE
|
|||
|
||||
sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)";
|
||||
|
||||
int terrainDBRevision;
|
||||
Array terrainDBblob;
|
||||
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", revision));
|
||||
cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain)));
|
||||
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.Info("[REGION DB]: Stored terrain revision r " + revision);
|
||||
_Log.Info("[REGION DB]: Stored terrain");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1344,6 +1357,7 @@ VALUES
|
|||
|
||||
#region Private Methods
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Serializes the terrain data for storage in DB.
|
||||
/// </summary>
|
||||
|
@ -1367,6 +1381,7 @@ VALUES
|
|||
|
||||
return str.ToArray();
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Stores new regionsettings.
|
||||
|
|
|
@ -48,8 +48,18 @@ namespace OpenSim.Data.MySQL
|
|||
public class MySQLSimulationData : ISimulationDataStore
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[REGION DB MYSQL]";
|
||||
|
||||
private string m_connectionString;
|
||||
|
||||
/// <summary>
|
||||
/// This lock was being used to serialize database operations when the connection was shared, but this has
|
||||
/// been unnecessary for a long time after we switched to using MySQL's underlying connection pooling instead.
|
||||
/// FIXME: However, the locks remain in many places since they are effectively providing a level of
|
||||
/// transactionality. This should be replaced by more efficient database transactions which would not require
|
||||
/// unrelated operations to block each other or unrelated operations on the same tables from blocking each
|
||||
/// other.
|
||||
/// </summary>
|
||||
private object m_dbLock = new object();
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
|
@ -91,7 +101,7 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message);
|
||||
m_log.ErrorFormat("{0} MySQL error in ExecuteReader: {1}", LogHeader, e);
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -574,12 +584,16 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void StoreTerrain(double[,] ter, UUID regionID)
|
||||
// Legacy entry point for when terrain was always a 256x256 hieghtmap
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
{
|
||||
StoreTerrain(new HeightmapTerrainData(ter), regionID);
|
||||
}
|
||||
|
||||
public void StoreTerrain(TerrainData terrData, UUID regionID)
|
||||
{
|
||||
Util.FireAndForget(delegate(object x)
|
||||
{
|
||||
double[,] oldTerrain = LoadTerrain(regionID);
|
||||
|
||||
m_log.Info("[REGION DB]: Storing terrain");
|
||||
|
||||
lock (m_dbLock)
|
||||
|
@ -601,8 +615,12 @@ namespace OpenSim.Data.MySQL
|
|||
"Revision, Heightfield) values (?RegionUUID, " +
|
||||
"1, ?Heightfield)";
|
||||
|
||||
cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString());
|
||||
cmd2.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter, oldTerrain));
|
||||
int terrainDBRevision;
|
||||
Array terrainDBblob;
|
||||
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
|
||||
|
||||
cmd2.Parameters.AddWithValue("Revision", terrainDBRevision);
|
||||
cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
ExecuteNonQuery(cmd2);
|
||||
|
@ -618,9 +636,20 @@ namespace OpenSim.Data.MySQL
|
|||
});
|
||||
}
|
||||
|
||||
// Legacy region loading
|
||||
public virtual double[,] LoadTerrain(UUID regionID)
|
||||
{
|
||||
double[,] terrain = null;
|
||||
double[,] ret = null;
|
||||
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
|
||||
if (terrData != null)
|
||||
ret = terrData.GetDoubles();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns 'null' if region not found
|
||||
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
|
||||
{
|
||||
TerrainData terrData = null;
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
|
@ -640,32 +669,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 virtual void RemoveLandObject(UUID globalID)
|
||||
|
|
|
@ -132,15 +132,33 @@ namespace OpenSim.Data.Null
|
|||
return new List<SceneObjectGroup>();
|
||||
}
|
||||
|
||||
Dictionary<UUID, double[,]> m_terrains = new Dictionary<UUID, double[,]>();
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
Dictionary<UUID, TerrainData> m_terrains = new Dictionary<UUID, TerrainData>();
|
||||
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.
|
||||
// Returns 'null' if region not found
|
||||
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))
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace OpenSim.Data.PGSQL
|
|||
public class PGSQLSimulationData : ISimulationDataStore
|
||||
{
|
||||
private const string _migrationStore = "RegionStore";
|
||||
private const string LogHeader = "[REGION DB PGSQL]";
|
||||
|
||||
// private static FileSystemDataStore Instance = new FileSystemDataStore();
|
||||
private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
@ -523,8 +524,17 @@ namespace OpenSim.Data.PGSQL
|
|||
/// <returns></returns>
|
||||
public double[,] LoadTerrain(UUID regionID)
|
||||
{
|
||||
double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
|
||||
terrain.Initialize();
|
||||
double[,] ret = null;
|
||||
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
|
||||
if (terrData != null)
|
||||
ret = terrData.GetDoubles();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns 'null' if region not found
|
||||
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; ";
|
||||
|
@ -540,16 +550,9 @@ namespace OpenSim.Data.PGSQL
|
|||
int rev;
|
||||
if (reader.Read())
|
||||
{
|
||||
MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
|
||||
BinaryReader br = new BinaryReader(str);
|
||||
for (int x = 0; x < (int)Constants.RegionSize; x++)
|
||||
{
|
||||
for (int y = 0; y < (int)Constants.RegionSize; y++)
|
||||
{
|
||||
terrain[x, y] = br.ReadDouble();
|
||||
}
|
||||
}
|
||||
rev = (int)reader["Revision"];
|
||||
rev = Convert.ToInt32(reader["Revision"]);
|
||||
byte[] blob = (byte[])reader["Heightfield"];
|
||||
terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -560,7 +563,13 @@ namespace OpenSim.Data.PGSQL
|
|||
}
|
||||
}
|
||||
|
||||
return terrain;
|
||||
return terrData;
|
||||
}
|
||||
|
||||
// Legacy entry point for when terrain was always a 256x256 heightmap
|
||||
public void StoreTerrain(double[,] terrain, UUID regionID)
|
||||
{
|
||||
StoreTerrain(new HeightmapTerrainData(terrain), regionID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -568,35 +577,38 @@ namespace OpenSim.Data.PGSQL
|
|||
/// </summary>
|
||||
/// <param name="terrain">terrain map data.</param>
|
||||
/// <param name="regionID">regionID.</param>
|
||||
public void StoreTerrain(double[,] terrain, UUID regionID)
|
||||
public void StoreTerrain(TerrainData terrData, UUID regionID)
|
||||
{
|
||||
int revision = Util.UnixTimeSinceEpoch();
|
||||
|
||||
//Delete old terrain map
|
||||
string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_Log.Info("[REGION DB]: Deleted terrain revision r " + revision);
|
||||
int terrainDBRevision;
|
||||
Array terrainDBblob;
|
||||
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
|
||||
|
||||
sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
|
||||
cmd.Parameters.Add(_Database.CreateParameter("Revision", revision));
|
||||
cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain)));
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(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.Info("[REGION DB]: Stored terrain revision r " + revision);
|
||||
_Log.Info("[REGION DB]: Stored terrain revision r " + terrainDBRevision);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1349,6 +1361,7 @@ namespace OpenSim.Data.PGSQL
|
|||
|
||||
#region Private Methods
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Serializes the terrain data for storage in DB.
|
||||
/// </summary>
|
||||
|
@ -1372,6 +1385,7 @@ namespace OpenSim.Data.PGSQL
|
|||
|
||||
return str.ToArray();
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Stores new regionsettings.
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace OpenSim.Data.SQLite
|
|||
public class SQLiteSimulationData : ISimulationDataStore
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[REGION DB SQLLITE]";
|
||||
|
||||
private const string primSelect = "select * from prims";
|
||||
private const string shapeSelect = "select * from primshapes";
|
||||
|
@ -819,12 +820,18 @@ namespace OpenSim.Data.SQLite
|
|||
prim.Inventory.RestoreInventoryItems(inventory);
|
||||
}
|
||||
|
||||
// Legacy entry point for when terrain was always a 256x256 hieghtmap
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
{
|
||||
StoreTerrain(new HeightmapTerrainData(ter), regionID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store a terrain revision in region storage
|
||||
/// </summary>
|
||||
/// <param name="ter">terrain heightfield</param>
|
||||
/// <param name="regionID">region UUID</param>
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
public void StoreTerrain(TerrainData terrData, UUID regionID)
|
||||
{
|
||||
lock (ds)
|
||||
{
|
||||
|
@ -853,11 +860,17 @@ namespace OpenSim.Data.SQLite
|
|||
String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
|
||||
" values(:RegionUUID, :Revision, :Heightfield)";
|
||||
|
||||
int terrainDBRevision;
|
||||
Array terrainDBblob;
|
||||
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
|
||||
|
||||
m_log.DebugFormat("{0} Storing terrain revision r {1}", LogHeader, terrainDBRevision);
|
||||
|
||||
using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
|
||||
{
|
||||
cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
|
||||
cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
|
||||
cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter)));
|
||||
cmd.Parameters.Add(new SqliteParameter(":Revision", terrainDBRevision));
|
||||
cmd.Parameters.Add(new SqliteParameter(":Heightfield", terrainDBblob));
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
@ -870,11 +883,20 @@ namespace OpenSim.Data.SQLite
|
|||
/// <returns>Heightfield data</returns>
|
||||
public double[,] LoadTerrain(UUID regionID)
|
||||
{
|
||||
double[,] ret = null;
|
||||
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
|
||||
if (terrData != null)
|
||||
ret = terrData.GetDoubles();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns 'null' if region not found
|
||||
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 +909,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 +922,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)
|
||||
|
@ -2016,6 +2026,7 @@ namespace OpenSim.Data.SQLite
|
|||
return entry;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
@ -2033,6 +2044,7 @@ namespace OpenSim.Data.SQLite
|
|||
|
||||
return str.ToArray();
|
||||
}
|
||||
*/
|
||||
|
||||
// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val)
|
||||
// {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
|
@ -40,9 +41,26 @@ namespace OpenSim.Framework
|
|||
public byte WaterHeight;
|
||||
public ushort X;
|
||||
public ushort Y;
|
||||
public ushort SizeX;
|
||||
public ushort SizeY;
|
||||
|
||||
public MapBlockData()
|
||||
{
|
||||
}
|
||||
|
||||
public OSDMap ToOSD()
|
||||
{
|
||||
OSDMap map = new OSDMap();
|
||||
map["X"] = X;
|
||||
map["Y"] = Y;
|
||||
map["SizeX"] = SizeX;
|
||||
map["SizeY"] = SizeY;
|
||||
map["Name"] = Name;
|
||||
map["Access"] = Access;
|
||||
map["RegionFlags"] = RegionFlags;
|
||||
map["WaterHeight"] = WaterHeight;
|
||||
map["MapImageID"] = MapImageId;
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,11 +149,32 @@ namespace OpenSim.Framework
|
|||
public uint WorldLocX = 0;
|
||||
public uint WorldLocY = 0;
|
||||
public uint WorldLocZ = 0;
|
||||
|
||||
/// <summary>
|
||||
/// X dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this is a varregion then the default size set here will be replaced when we load the region config.
|
||||
/// </remarks>
|
||||
public uint RegionSizeX = Constants.RegionSize;
|
||||
|
||||
/// <summary>
|
||||
/// X dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this is a varregion then the default size set here will be replaced when we load the region config.
|
||||
/// </remarks>
|
||||
public uint RegionSizeY = Constants.RegionSize;
|
||||
|
||||
/// <summary>
|
||||
/// Z dimension of the region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// XXX: Unknown if this accounts for regions with negative Z.
|
||||
/// </remarks>
|
||||
public uint RegionSizeZ = Constants.RegionHeight;
|
||||
|
||||
private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
|
||||
private Dictionary<String, String> m_extraSettings = new Dictionary<string, string>();
|
||||
|
||||
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
|
||||
|
||||
|
@ -506,16 +527,16 @@ namespace OpenSim.Framework
|
|||
{
|
||||
string val;
|
||||
string keylower = key.ToLower();
|
||||
if (m_otherSettings.TryGetValue(keylower, out val))
|
||||
if (m_extraSettings.TryGetValue(keylower, out val))
|
||||
return val;
|
||||
m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetOtherSetting(string key, string value)
|
||||
public void SetExtraSetting(string key, string value)
|
||||
{
|
||||
string keylower = key.ToLower();
|
||||
m_otherSettings[keylower] = value;
|
||||
m_extraSettings[keylower] = value;
|
||||
}
|
||||
|
||||
private void ReadNiniConfig(IConfigSource source, string name)
|
||||
|
@ -733,7 +754,7 @@ namespace OpenSim.Framework
|
|||
|
||||
foreach (String s in allKeys)
|
||||
{
|
||||
SetOtherSetting(s, config.GetString(s));
|
||||
SetExtraSetting(s, config.GetString(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,6 +825,7 @@ namespace OpenSim.Framework
|
|||
|
||||
if (DataStore != String.Empty)
|
||||
config.Set("Datastore", DataStore);
|
||||
|
||||
if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
|
||||
{
|
||||
config.Set("SizeX", RegionSizeX);
|
||||
|
|
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public abstract class TerrainData
|
||||
{
|
||||
// Terrain always is a square
|
||||
public int SizeX { get; protected set; }
|
||||
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; }
|
||||
|
||||
public abstract bool IsTaintedAt(int xx, int yy);
|
||||
public abstract bool IsTaintedAt(int xx, int yy, bool clearOnTest);
|
||||
public abstract void TaintAllTerrain();
|
||||
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 ints
|
||||
public abstract int[] GetCompressedMap();
|
||||
public abstract float CompressionFactor { get; }
|
||||
|
||||
public abstract float[] GetFloatsSerialized();
|
||||
public abstract double[,] GetDoubles();
|
||||
public abstract TerrainData Clone();
|
||||
}
|
||||
|
||||
// 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
|
||||
// field.
|
||||
// Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
|
||||
// left over and it is presumed to be 'Legacy256'.
|
||||
// Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
|
||||
// If a revision does not match any of these, it is assumed to be Legacy256.
|
||||
public enum DBTerrainRevision
|
||||
{
|
||||
// Terrain is 'double[256,256]'
|
||||
Legacy256 = 11,
|
||||
// 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
|
||||
// "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'.
|
||||
RevisionHigh = 1234
|
||||
}
|
||||
|
||||
// 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 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);
|
||||
private static string LogHeader = "[HEIGHTMAP TERRAIN DATA]";
|
||||
|
||||
// TerrainData.this[x, y]
|
||||
public override float this[int x, int y]
|
||||
{
|
||||
get { return FromCompressedHeight(m_heightmap[x, y]); }
|
||||
set {
|
||||
int newVal = ToCompressedHeight(value);
|
||||
if (m_heightmap[x, y] != newVal)
|
||||
{
|
||||
m_heightmap[x, y] = newVal;
|
||||
m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TerrainData.this[x, y, z]
|
||||
public override float this[int x, int y, int z]
|
||||
{
|
||||
get { return this[x, y]; }
|
||||
set { this[x, y] = value; }
|
||||
}
|
||||
|
||||
// TerrainData.ClearTaint
|
||||
public override void ClearTaint()
|
||||
{
|
||||
SetAllTaint(false);
|
||||
}
|
||||
|
||||
// TerrainData.TaintAllTerrain
|
||||
public override void TaintAllTerrain()
|
||||
{
|
||||
SetAllTaint(true);
|
||||
}
|
||||
|
||||
private void SetAllTaint(bool setting)
|
||||
{
|
||||
for (int ii = 0; ii < m_taint.GetLength(0); ii++)
|
||||
for (int jj = 0; jj < m_taint.GetLength(1); jj++)
|
||||
m_taint[ii, jj] = setting;
|
||||
}
|
||||
|
||||
// TerrainData.ClearLand
|
||||
public override void ClearLand()
|
||||
{
|
||||
ClearLand(DefaultTerrainHeight);
|
||||
}
|
||||
// TerrainData.ClearLand(float)
|
||||
public override void ClearLand(float pHeight)
|
||||
{
|
||||
int flatHeight = ToCompressedHeight(pHeight);
|
||||
for (int xx = 0; xx < SizeX; xx++)
|
||||
for (int yy = 0; yy < SizeY; yy++)
|
||||
m_heightmap[xx, yy] = flatHeight;
|
||||
}
|
||||
|
||||
// Return 'true' of the patch that contains these region coordinates has been modified.
|
||||
// Note that checking the taint clears it.
|
||||
// There is existing code that relies on this feature.
|
||||
public override bool IsTaintedAt(int xx, int yy, bool clearOnTest)
|
||||
{
|
||||
int tx = xx / Constants.TerrainPatchSize;
|
||||
int ty = yy / Constants.TerrainPatchSize;
|
||||
bool ret = m_taint[tx, ty];
|
||||
if (ret && clearOnTest)
|
||||
m_taint[tx, ty] = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Old form that clears the taint flag when we check it.
|
||||
public override bool IsTaintedAt(int xx, int yy)
|
||||
{
|
||||
return IsTaintedAt(xx, yy, true /* clearOnTest */);
|
||||
}
|
||||
|
||||
// TerrainData.GetDatabaseBlob
|
||||
// The user wants something to store in the database.
|
||||
public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
|
||||
{
|
||||
bool ret = false;
|
||||
if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize)
|
||||
{
|
||||
DBRevisionCode = (int)DBTerrainRevision.Legacy256;
|
||||
blob = ToLegacyTerrainSerialization();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBRevisionCode = (int)DBTerrainRevision.Compressed2D;
|
||||
blob = ToCompressedTerrainSerialization();
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TerrainData.CompressionFactor
|
||||
private float m_compressionFactor = 100.0f;
|
||||
public override float CompressionFactor { get { return m_compressionFactor; } }
|
||||
|
||||
// TerrainData.GetCompressedMap
|
||||
public override int[] GetCompressedMap()
|
||||
{
|
||||
int[] newMap = new int[SizeX * SizeY];
|
||||
|
||||
int ind = 0;
|
||||
for (int xx = 0; xx < SizeX; xx++)
|
||||
for (int yy = 0; yy < SizeY; yy++)
|
||||
newMap[ind++] = m_heightmap[xx, yy];
|
||||
|
||||
return newMap;
|
||||
|
||||
}
|
||||
// TerrainData.Clone
|
||||
public override TerrainData Clone()
|
||||
{
|
||||
HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
|
||||
ret.m_heightmap = (int[,])this.m_heightmap.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TerrainData.GetFloatsSerialized
|
||||
// This one dimensional version is ordered so height = map[y*sizeX+x];
|
||||
// DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
|
||||
// and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
|
||||
public override float[] GetFloatsSerialized()
|
||||
{
|
||||
int points = SizeX * SizeY;
|
||||
float[] heights = new float[points];
|
||||
|
||||
int idx = 0;
|
||||
for (int jj = 0; jj < SizeY; jj++)
|
||||
for (int ii = 0; ii < SizeX; ii++)
|
||||
{
|
||||
heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]);
|
||||
}
|
||||
|
||||
return heights;
|
||||
}
|
||||
|
||||
// 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 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 int ToCompressedHeight(double pHeight)
|
||||
{
|
||||
return (int)(pHeight * CompressionFactor);
|
||||
}
|
||||
|
||||
public float FromCompressedHeight(int pHeight)
|
||||
{
|
||||
return ((float)pHeight) / CompressionFactor;
|
||||
}
|
||||
|
||||
// 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 int[SizeX, SizeY];
|
||||
for (int ii = 0; ii < SizeX; ii++)
|
||||
{
|
||||
for (int jj = 0; jj < SizeY; jj++)
|
||||
{
|
||||
m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]);
|
||||
|
||||
}
|
||||
}
|
||||
// m_log.DebugFormat("{0} new by doubles. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
|
||||
|
||||
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
|
||||
ClearTaint();
|
||||
}
|
||||
|
||||
// Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
|
||||
public HeightmapTerrainData(int pX, int pY, int pZ)
|
||||
{
|
||||
SizeX = pX;
|
||||
SizeY = pY;
|
||||
SizeZ = pZ;
|
||||
m_compressionFactor = 100.0f;
|
||||
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(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
|
||||
{
|
||||
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++];
|
||||
// m_log.DebugFormat("{0} new by compressed map. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
|
||||
}
|
||||
|
||||
// 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);
|
||||
m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
|
||||
break;
|
||||
default:
|
||||
FromLegacyTerrainSerialization(pBlob);
|
||||
m_log.DebugFormat("{0} HeightmapTerrainData create from legacy serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Just create an array of doubles. Presumes the caller implicitly knows the size.
|
||||
public Array ToLegacyTerrainSerialization()
|
||||
{
|
||||
Array ret = null;
|
||||
|
||||
using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double)))
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(str))
|
||||
{
|
||||
for (int xx = 0; xx < Constants.RegionSize; xx++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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] = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -161,14 +161,18 @@ namespace OpenSim.Framework
|
|||
{
|
||||
get
|
||||
{
|
||||
return Utils.UIntsToLong(
|
||||
m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
|
||||
return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY));
|
||||
// return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
m_homeRegionX = (uint) (value >> 40);
|
||||
m_homeRegionY = (((uint) (value)) >> 8);
|
||||
uint regionWorldLocX, regionWorldLocY;
|
||||
Util.RegionHandleToWorldLoc(value, out regionWorldLocX, out regionWorldLocY);
|
||||
m_homeRegionX = Util.WorldToRegionLoc(regionWorldLocX);
|
||||
m_homeRegionY = Util.WorldToRegionLoc(regionWorldLocY);
|
||||
// m_homeRegionX = (uint) (value >> 40);
|
||||
// m_homeRegionY = (((uint) (value)) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[EVENT QUEUE GET MODULE]";
|
||||
|
||||
/// <value>
|
||||
/// Debug level.
|
||||
|
@ -479,7 +480,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
|
||||
{
|
||||
m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
|
||||
"[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
|
||||
LogHeader, handle, avatarID, regionSizeX, regionSizeY);
|
||||
|
||||
OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
|
||||
Enqueue(item, avatarID);
|
||||
|
@ -489,7 +490,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
ulong regionHandle, int regionSizeX, int regionSizeY)
|
||||
{
|
||||
m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
|
||||
"[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
|
||||
LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
|
||||
OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
|
||||
Enqueue(item, avatarID);
|
||||
}
|
||||
|
@ -500,7 +501,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
UUID avatarID, int regionSizeX, int regionSizeY)
|
||||
{
|
||||
m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
|
||||
"[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
|
||||
LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
|
||||
|
||||
OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
|
||||
locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
|
||||
|
@ -512,7 +513,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
|
||||
{
|
||||
m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
|
||||
"[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
|
||||
LogHeader, handle, avatarID, regionSizeX, regionSizeY);
|
||||
|
||||
OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
|
||||
capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
|
||||
|
|
|
@ -312,6 +312,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[LLCLIENTVIEW]";
|
||||
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
||||
|
||||
/// <summary>
|
||||
|
@ -691,13 +692,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// </param>
|
||||
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
||||
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
|
||||
{
|
||||
return AddLocalPacketHandler(packetType, handler, doAsync, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a handler for the given packet type.
|
||||
/// </summary>
|
||||
/// <param name="packetType"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <param name="doAsync">
|
||||
/// If true, when the packet is received handle it on a different thread. Whether this is given direct to
|
||||
/// a threadpool thread or placed in a queue depends on the inEngine parameter.
|
||||
/// </param>
|
||||
/// <param name="inEngine">
|
||||
/// If async is false then this parameter is ignored.
|
||||
/// If async is true and inEngine is false, then the packet is sent directly to a
|
||||
/// threadpool thread.
|
||||
/// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine.
|
||||
/// This may result in slower handling but reduces the risk of overloading the simulator when there are many
|
||||
/// simultaneous async requests.
|
||||
/// </param>
|
||||
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
||||
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine)
|
||||
{
|
||||
bool result = false;
|
||||
lock (m_packetHandlers)
|
||||
{
|
||||
if (!m_packetHandlers.ContainsKey(packetType))
|
||||
{
|
||||
m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync });
|
||||
m_packetHandlers.Add(
|
||||
packetType, new PacketProcessor() { method = handler, Async = doAsync });
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
@ -1176,11 +1201,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
/// <summary>
|
||||
/// Send the region heightmap to the client
|
||||
/// This method is only called when not doing intellegent terrain patch sending and
|
||||
/// is only called when the scene presence is initially created and sends all of the
|
||||
/// region's patches to the client.
|
||||
/// </summary>
|
||||
/// <param name="map">heightmap</param>
|
||||
public virtual void SendLayerData(float[] map)
|
||||
{
|
||||
Util.FireAndForget(DoSendLayerData, map);
|
||||
Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
|
||||
|
||||
// Send it sync, and async. It's not that much data
|
||||
// and it improves user experience just so much!
|
||||
|
@ -1193,15 +1221,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="o"></param>
|
||||
private void DoSendLayerData(object o)
|
||||
{
|
||||
float[] map = LLHeightFieldMoronize((float[])o);
|
||||
TerrainData map = (TerrainData)o;
|
||||
|
||||
try
|
||||
{
|
||||
// Send LayerData in typerwriter pattern
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
for (int x = 0; x < 16; x+=4)
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
SendLayerPacket(x, y, map);
|
||||
SendLayerData(x, y, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1211,77 +1240,95 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a set of four patches (x, x+1, ..., x+3) to the client
|
||||
/// </summary>
|
||||
/// <param name="map">heightmap</param>
|
||||
/// <param name="px">X coordinate for patches 0..12</param>
|
||||
/// <param name="py">Y coordinate for patches 0..15</param>
|
||||
private void SendLayerPacket(int x, int y, float[] map)
|
||||
// Legacy form of invocation that passes around a bare data array.
|
||||
// Just ignore what was passed and use the real terrain info that is part of the scene.
|
||||
// As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
|
||||
// there is a special form for specifying multiple terrain patches to send.
|
||||
// The form is to pass 'px' as negative the number of patches to send and to
|
||||
// pass the float array as pairs of patch X and Y coordinates. So, passing 'px'
|
||||
// as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches
|
||||
// and the patches to send are <3,5> and <8,4>.
|
||||
public void SendLayerData(int px, int py, float[] map)
|
||||
{
|
||||
int[] patches = new int[4];
|
||||
patches[0] = x + 0 + y * 16;
|
||||
patches[1] = x + 1 + y * 16;
|
||||
patches[2] = x + 2 + y * 16;
|
||||
patches[3] = x + 3 + y * 16;
|
||||
|
||||
float[] heightmap = (map.Length == 65536) ?
|
||||
map :
|
||||
LLHeightFieldMoronize(map);
|
||||
|
||||
try
|
||||
if (px >= 0)
|
||||
{
|
||||
Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
|
||||
OutPacket(layerpack, ThrottleOutPacketType.Land);
|
||||
SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
|
||||
}
|
||||
catch
|
||||
else
|
||||
{
|
||||
for (int px = x ; px < x + 4 ; px++)
|
||||
SendLayerData(px, y, map);
|
||||
int numPatches = -px;
|
||||
int[] xPatches = new int[numPatches];
|
||||
int[] yPatches = new int[numPatches];
|
||||
for (int pp = 0; pp < numPatches; pp++)
|
||||
{
|
||||
xPatches[pp] = (int)map[pp * 2];
|
||||
yPatches[pp] = (int)map[pp * 2 + 1];
|
||||
}
|
||||
|
||||
// DebugSendingPatches("SendLayerData", xPatches, yPatches);
|
||||
|
||||
SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData());
|
||||
}
|
||||
}
|
||||
|
||||
private void DebugSendingPatches(string pWho, int[] pX, int[] pY)
|
||||
{
|
||||
if (m_log.IsDebugEnabled)
|
||||
{
|
||||
int numPatches = pX.Length;
|
||||
string Xs = "";
|
||||
string Ys = "";
|
||||
for (int pp = 0; pp < numPatches; pp++)
|
||||
{
|
||||
Xs += String.Format("{0}", (int)pX[pp]) + ",";
|
||||
Ys += String.Format("{0}", (int)pY[pp]) + ",";
|
||||
}
|
||||
m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a specified patch to a client
|
||||
/// Sends a terrain packet for the point specified.
|
||||
/// This is a legacy call that has refarbed the terrain into a flat map of floats.
|
||||
/// We just use the terrain from the region we know about.
|
||||
/// </summary>
|
||||
/// <param name="px">Patch coordinate (x) 0..15</param>
|
||||
/// <param name="py">Patch coordinate (y) 0..15</param>
|
||||
/// <param name="map">heightmap</param>
|
||||
public void SendLayerData(int px, int py, float[] map)
|
||||
public void SendLayerData(int px, int py, TerrainData terrData)
|
||||
{
|
||||
int[] xPatches = new[] { px };
|
||||
int[] yPatches = new[] { py };
|
||||
SendLayerData(xPatches, yPatches, terrData);
|
||||
}
|
||||
|
||||
private void SendLayerData(int[] px, int[] py, TerrainData terrData)
|
||||
{
|
||||
try
|
||||
{
|
||||
int[] patches = new int[] { py * 16 + px };
|
||||
float[] heightmap = (map.Length == 65536) ?
|
||||
map :
|
||||
LLHeightFieldMoronize(map);
|
||||
|
||||
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
|
||||
|
||||
// When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
|
||||
// To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
|
||||
// We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
|
||||
// invalidating previous packets for that area.
|
||||
|
||||
// It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
|
||||
// tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
|
||||
|
||||
// One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
|
||||
// have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
|
||||
// patches.
|
||||
|
||||
// m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
|
||||
if (m_justEditedTerrain)
|
||||
/* test code using the terrain compressor in libOpenMetaverse
|
||||
int[] patchInd = new int[1];
|
||||
patchInd[0] = px + (py * Constants.TerrainPatchSize);
|
||||
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd);
|
||||
*/
|
||||
// Many, many patches could have been passed to us. Since the patches will be compressed
|
||||
// into variable sized blocks, we cannot pre-compute how many will fit into one
|
||||
// packet. While some fancy packing algorithm is possible, 4 seems to always fit.
|
||||
int PatchesAssumedToFit = 4;
|
||||
for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit)
|
||||
{
|
||||
layerpack.Header.Reliable = false;
|
||||
OutPacket(layerpack,
|
||||
ThrottleOutPacketType.Unknown );
|
||||
}
|
||||
else
|
||||
{
|
||||
layerpack.Header.Reliable = true;
|
||||
OutPacket(layerpack,
|
||||
ThrottleOutPacketType.Task);
|
||||
int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit);
|
||||
int[] xPatches = new int[remaining];
|
||||
int[] yPatches = new int[remaining];
|
||||
for (int ii = 0; ii < remaining; ii++)
|
||||
{
|
||||
xPatches[ii] = px[pcnt + ii];
|
||||
yPatches[ii] = py[pcnt + ii];
|
||||
}
|
||||
LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches);
|
||||
// DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches);
|
||||
|
||||
SendTheLayerPacket(layerpack);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -1290,36 +1337,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Munges heightfield into the LLUDP backed in restricted heightfield.
|
||||
/// </summary>
|
||||
/// <param name="map">float array in the base; Constants.RegionSize</param>
|
||||
/// <returns>float array in the base 256</returns>
|
||||
internal float[] LLHeightFieldMoronize(float[] map)
|
||||
// When a user edits the terrain, so much data is sent, the data queues up fast and presents a
|
||||
// sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
|
||||
// start skipping the queues until they're done editing the terrain. We also make them
|
||||
// unreliable because it's extremely likely that multiple packets will be sent for a terrain patch
|
||||
// area invalidating previous packets for that area.
|
||||
|
||||
// It's possible for an editing user to flood themselves with edited packets but the majority
|
||||
// of use cases are such that only a tiny percentage of users will be editing the terrain.
|
||||
// Other, non-editing users will see the edits much slower.
|
||||
|
||||
// One last note on this topic, by the time users are going to be editing the terrain, it's
|
||||
// extremely likely that the sim will have rezzed already and therefore this is not likely going
|
||||
// to cause any additional issues with lost packets, objects or terrain patches.
|
||||
|
||||
// m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we
|
||||
// only have one cache miss.
|
||||
private void SendTheLayerPacket(LayerDataPacket layerpack)
|
||||
{
|
||||
if (map.Length == 65536)
|
||||
return map;
|
||||
if (m_justEditedTerrain)
|
||||
{
|
||||
layerpack.Header.Reliable = false;
|
||||
OutPacket(layerpack, ThrottleOutPacketType.Unknown );
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] returnmap = new float[65536];
|
||||
|
||||
if (map.Length < 65535)
|
||||
{
|
||||
// rebase the vector stride to 256
|
||||
for (int i = 0; i < Constants.RegionSize; i++)
|
||||
Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
|
||||
}
|
||||
|
||||
//Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
|
||||
|
||||
return returnmap;
|
||||
layerpack.Header.Reliable = true;
|
||||
OutPacket(layerpack, ThrottleOutPacketType.Land);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1348,21 +1393,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
Vector2[] windSpeeds = (Vector2[])o;
|
||||
TerrainPatch[] patches = new TerrainPatch[2];
|
||||
patches[0] = new TerrainPatch();
|
||||
patches[0].Data = new float[16 * 16];
|
||||
patches[1] = new TerrainPatch();
|
||||
patches[1].Data = new float[16 * 16];
|
||||
patches[0] = new TerrainPatch { Data = new float[16 * 16] };
|
||||
patches[1] = new TerrainPatch { Data = new float[16 * 16] };
|
||||
|
||||
for (int y = 0; y < 16; y++)
|
||||
for (int x = 0; x < 16 * 16; x++)
|
||||
{
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X;
|
||||
patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y;
|
||||
}
|
||||
patches[0].Data[x] = windSpeeds[x].X;
|
||||
patches[1].Data[x] = windSpeeds[x].Y;
|
||||
}
|
||||
|
||||
LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind);
|
||||
byte layerType = (byte)TerrainPatch.LayerType.Wind;
|
||||
if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
|
||||
layerType = (byte)TerrainPatch.LayerType.WindExtended;
|
||||
|
||||
// LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType);
|
||||
LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
|
||||
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
|
||||
layerpack.Header.Zerocoded = true;
|
||||
OutPacket(layerpack, ThrottleOutPacketType.Wind);
|
||||
}
|
||||
|
@ -1386,7 +1432,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud);
|
||||
byte layerType = (byte)TerrainPatch.LayerType.Cloud;
|
||||
if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
|
||||
layerType = (byte)TerrainPatch.LayerType.CloudExtended;
|
||||
|
||||
// LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType);
|
||||
LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
|
||||
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
|
||||
layerpack.Header.Zerocoded = true;
|
||||
OutPacket(layerpack, ThrottleOutPacketType.Cloud);
|
||||
}
|
||||
|
@ -1491,10 +1543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
mapReply.Data[i].Access = mapBlocks2[i].Access;
|
||||
mapReply.Data[i].Agents = mapBlocks2[i].Agents;
|
||||
|
||||
// TODO: hookup varregion sim size here
|
||||
mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
|
||||
mapReply.Size[i].SizeX = 256;
|
||||
mapReply.Size[i].SizeY = 256;
|
||||
mapReply.Size[i].SizeX = mapBlocks2[i].SizeX;
|
||||
mapReply.Size[i].SizeY = mapBlocks2[i].SizeY;
|
||||
}
|
||||
OutPacket(mapReply, ThrottleOutPacketType.Land);
|
||||
}
|
||||
|
@ -1659,15 +1710,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
public void SendKillObject(List<uint> localIDs)
|
||||
{
|
||||
// foreach (uint id in localIDs)
|
||||
// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
|
||||
|
||||
// remove pending entities
|
||||
lock (m_entityProps.SyncRoot)
|
||||
m_entityProps.Remove(localIDs);
|
||||
lock (m_entityUpdates.SyncRoot)
|
||||
m_entityUpdates.Remove(localIDs);
|
||||
|
||||
KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
|
||||
// TODO: don't create new blocks if recycling an old packet
|
||||
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
|
||||
|
@ -9093,6 +9135,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
|
||||
if (handlerTeleportLocationRequest != null)
|
||||
{
|
||||
// Adjust teleport location to base of a larger region if requested to teleport to a sub-region
|
||||
uint locX, locY;
|
||||
Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out locX, out locY);
|
||||
if ((locX >= m_scene.RegionInfo.WorldLocX)
|
||||
&& (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
|
||||
&& (locY >= m_scene.RegionInfo.WorldLocY)
|
||||
&& (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) )
|
||||
{
|
||||
tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||
tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
|
||||
tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY;
|
||||
}
|
||||
|
||||
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
|
||||
tpLocReq.Info.LookAt, 16);
|
||||
}
|
||||
|
|
|
@ -213,8 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
|
|||
IScene scene = c.Scene;
|
||||
UUID destination = c.Destination;
|
||||
Vector3 fromPos = c.Position;
|
||||
Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
|
||||
scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
|
||||
|
||||
bool checkParcelHide = false;
|
||||
UUID sourceParcelID = UUID.Zero;
|
||||
|
@ -424,8 +423,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
|
|||
{
|
||||
Vector3 fromRegionPos = fromPos + regionPos;
|
||||
Vector3 toRegionPos = presence.AbsolutePosition +
|
||||
new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
|
||||
presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
new Vector3(presence.Scene.RegionInfo.WorldLocX, presence.Scene.RegionInfo.WorldLocY, 0);
|
||||
|
||||
int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
|
||||
|
||||
|
|
|
@ -663,8 +663,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
|
|||
|
||||
Vector3 avaPos = p.AbsolutePosition;
|
||||
// Getting the global position for the Avatar
|
||||
Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
|
||||
remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
|
||||
Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.WorldLocX + avaPos.X,
|
||||
remoteClient.Scene.RegionInfo.WorldLocY + avaPos.Y,
|
||||
avaPos.Z);
|
||||
|
||||
string landOwnerName = string.Empty;
|
||||
|
@ -1353,4 +1353,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
|
|||
}
|
||||
#endregion Web Util
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,9 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework
|
|||
foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(kvp.Key, out x, out y);
|
||||
x = x / Constants.RegionSize;
|
||||
y = y / Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
|
||||
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
|
|||
if (part != null)
|
||||
{
|
||||
ObjectRegionName = s.RegionInfo.RegionName;
|
||||
uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize);
|
||||
uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize);
|
||||
uint localX = s.RegionInfo.WorldLocX;
|
||||
uint localY = s.RegionInfo.WorldLocY;
|
||||
ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")";
|
||||
return part;
|
||||
}
|
||||
|
|
|
@ -268,11 +268,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
|
||||
List<GridRegion> regions = kvp.Value.GetNeighbours();
|
||||
foreach (GridRegion r in regions)
|
||||
caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
|
||||
caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(caps.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
return;
|
||||
|
||||
m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
|
||||
m_scene.RegionInfo.RegionName, otherRegion.RegionName, otherRegion.RegionLocX / Constants.RegionSize, otherRegion.RegionLocY / Constants.RegionSize);
|
||||
m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
|
||||
|
||||
m_neighbours[otherRegion.RegionHandle] = otherRegion;
|
||||
}
|
||||
|
@ -82,11 +82,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
return new List<GridRegion>(m_neighbours.Values);
|
||||
}
|
||||
|
||||
// Get a region given its base coordinates (in meters).
|
||||
// NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
|
||||
// be the base coordinate of the region.
|
||||
// The snapping is technically unnecessary but is harmless because regions are always
|
||||
// multiples of the legacy region size (256).
|
||||
public GridRegion GetRegionByPosition(int x, int y)
|
||||
{
|
||||
uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize;
|
||||
uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize;
|
||||
ulong handle = Utils.UIntsToLong(xsnap, ysnap);
|
||||
ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap);
|
||||
|
||||
if (m_neighbours.ContainsKey(handle))
|
||||
return m_neighbours[handle];
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
|||
Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null");
|
||||
Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match");
|
||||
|
||||
result = m_LocalConnector.GetRegionByPosition(UUID.Zero, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
|
||||
result = m_LocalConnector.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
|
||||
Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null");
|
||||
Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match");
|
||||
|
||||
|
@ -197,4 +197,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
|||
Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
|
|||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[MAP IMAGE SERVICE MODULE]";
|
||||
|
||||
private bool m_enabled = false;
|
||||
private IMapImageService m_MapService;
|
||||
|
@ -192,47 +193,94 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
|
|||
m_lastrefresh = Util.EnvironmentTickCount();
|
||||
}
|
||||
|
||||
public void UploadMapTile(IScene scene, Bitmap mapTile)
|
||||
{
|
||||
m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.Name);
|
||||
|
||||
// mapTile.Save( // DEBUG DEBUG
|
||||
// String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY),
|
||||
// ImageFormat.Jpeg);
|
||||
// If the region/maptile is legacy sized, just upload the one tile like it has always been done
|
||||
if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
|
||||
{
|
||||
ConvertAndUploadMaptile(mapTile, scene,
|
||||
scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For larger regions (varregion) we must cut the region image into legacy sized
|
||||
// pieces since that is how the maptile system works.
|
||||
// Note the assumption that varregions are always a multiple of legacy size.
|
||||
for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize)
|
||||
{
|
||||
for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize)
|
||||
{
|
||||
// Images are addressed from the upper left corner so have to do funny
|
||||
// math to pick out the sub-tile since regions are numbered from
|
||||
// the lower left.
|
||||
Rectangle rect = new Rectangle(
|
||||
(int)xx,
|
||||
mapTile.Height - (int)yy - (int)Constants.RegionSize,
|
||||
(int)Constants.RegionSize, (int)Constants.RegionSize);
|
||||
using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
|
||||
{
|
||||
ConvertAndUploadMaptile(subMapTile, scene,
|
||||
scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
|
||||
scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///
|
||||
///</summary>
|
||||
public void UploadMapTile(IScene scene)
|
||||
{
|
||||
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
|
||||
m_log.DebugFormat("{0}: upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
|
||||
|
||||
// Create a JPG map tile and upload it to the AddMapTile API
|
||||
byte[] jpgData = Utils.EmptyBytes;
|
||||
IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
|
||||
if (tileGenerator == null)
|
||||
{
|
||||
m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
|
||||
m_log.WarnFormat("{0} Cannot upload map tile without an ImageGenerator", LogHeader);
|
||||
return;
|
||||
}
|
||||
|
||||
using (Image mapTile = tileGenerator.CreateMapTile())
|
||||
using (Bitmap mapTile = tileGenerator.CreateMapTile())
|
||||
{
|
||||
// XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
|
||||
// is no static map tile.
|
||||
if (mapTile == null)
|
||||
return;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
UploadMapTile(scene, mapTile);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConvertAndUploadMaptile(Image tileImage, IScene scene, uint locX, uint locY)
|
||||
{
|
||||
byte[] jpgData = Utils.EmptyBytes;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
tileImage.Save(stream, ImageFormat.Jpeg);
|
||||
jpgData = stream.ToArray();
|
||||
}
|
||||
if (jpgData != Utils.EmptyBytes)
|
||||
{
|
||||
string reason = string.Empty;
|
||||
if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
|
||||
{
|
||||
mapTile.Save(stream, ImageFormat.Jpeg);
|
||||
jpgData = stream.ToArray();
|
||||
m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
|
||||
scene.RegionInfo.RegionName, locX, locY, reason);
|
||||
}
|
||||
}
|
||||
|
||||
if (jpgData == Utils.EmptyBytes)
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
|
||||
return;
|
||||
}
|
||||
|
||||
string reason = string.Empty;
|
||||
if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, scene.RegionInfo.ScopeID, out reason))
|
||||
{
|
||||
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
|
||||
scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
|
||||
m_log.WarnFormat("{0} Tile image generation failed for region {1}", LogHeader, scene.RegionInfo.RegionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,14 +125,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
|
|||
public OpenSim.Services.Interfaces.GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion)
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
Util.RegionHandleToRegionLoc(regionHandle, out x, out y);
|
||||
|
||||
foreach (Scene s in m_Scenes)
|
||||
{
|
||||
if (s.RegionInfo.RegionHandle == regionHandle)
|
||||
{
|
||||
m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
|
||||
thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
|
||||
thisRegion.RegionName, s.Name, x, y );
|
||||
|
||||
//m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
|
||||
return s.IncomingHelloNeighbour(thisRegion);
|
||||
|
|
|
@ -533,7 +533,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
|||
if (isMegaregion)
|
||||
size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
|
||||
else
|
||||
size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
|
||||
size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
|
||||
|
||||
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
|
||||
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
|
||||
|
|
|
@ -64,6 +64,12 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
public class LandManagementModule : INonSharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
|
||||
|
||||
/// <summary>
|
||||
/// Minimum land unit size in region co-ordinates.
|
||||
/// </summary>
|
||||
public const int landUnit = 4;
|
||||
|
||||
private static readonly string remoteParcelRequestPath = "0009/";
|
||||
|
||||
|
@ -74,15 +80,10 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
protected IPrimCountModule m_primCountModule;
|
||||
protected IDialogModule m_Dialog;
|
||||
|
||||
// Minimum for parcels to work is 64m even if we don't actually use them.
|
||||
#pragma warning disable 0429
|
||||
private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
|
||||
#pragma warning restore 0429
|
||||
|
||||
/// <value>
|
||||
/// Local land ids at specified region co-ordinates (region size / 4)
|
||||
/// </value>
|
||||
private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax];
|
||||
private int[,] m_landIDList;
|
||||
|
||||
/// <value>
|
||||
/// Land objects keyed by local id
|
||||
|
@ -123,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
public void AddRegion(Scene scene)
|
||||
{
|
||||
m_scene = scene;
|
||||
m_landIDList.Initialize();
|
||||
m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
|
||||
landChannel = new LandChannel(scene, this);
|
||||
|
||||
parcelInfoCache = new Cache();
|
||||
|
@ -235,7 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
public void UpdateLandObject(int local_id, LandData data)
|
||||
{
|
||||
LandData newData = data.Copy();
|
||||
newData.LocalID = local_id;
|
||||
newData.LocalID = local_id;
|
||||
|
||||
ILandObject land;
|
||||
lock (m_landList)
|
||||
|
@ -264,7 +265,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
{
|
||||
m_landList.Clear();
|
||||
m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
|
||||
m_landIDList.Initialize();
|
||||
m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,11 +275,11 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
/// <returns>The parcel created.</returns>
|
||||
protected ILandObject CreateDefaultParcel()
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
|
||||
m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
|
||||
|
||||
ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
|
||||
fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
|
||||
fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
|
||||
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
|
||||
fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
|
||||
|
||||
|
@ -569,9 +570,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
new_land.LandData.LocalID = newLandLocalID;
|
||||
|
||||
bool[,] landBitmap = new_land.GetLandBitmap();
|
||||
for (int x = 0; x < landArrayMax; x++)
|
||||
for (int x = 0; x < landBitmap.GetLength(0); x++)
|
||||
{
|
||||
for (int y = 0; y < landArrayMax; y++)
|
||||
for (int y = 0; y < landBitmap.GetLength(1); y++)
|
||||
{
|
||||
if (landBitmap[x, y])
|
||||
{
|
||||
|
@ -601,9 +602,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
ILandObject land;
|
||||
lock (m_landList)
|
||||
{
|
||||
for (int x = 0; x < 64; x++)
|
||||
for (int x = 0; x < m_landIDList.GetLength(0); x++)
|
||||
{
|
||||
for (int y = 0; y < 64; y++)
|
||||
for (int y = 0; y < m_landIDList.GetLength(1); y++)
|
||||
{
|
||||
if (m_landIDList[x, y] == local_id)
|
||||
{
|
||||
|
@ -656,9 +657,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
bool[,] landBitmapSlave = slave.GetLandBitmap();
|
||||
lock (m_landList)
|
||||
{
|
||||
for (int x = 0; x < 64; x++)
|
||||
for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
|
||||
{
|
||||
for (int y = 0; y < 64; y++)
|
||||
for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
|
||||
{
|
||||
if (landBitmapSlave[x, y])
|
||||
{
|
||||
|
@ -695,20 +696,23 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
int x;
|
||||
int y;
|
||||
|
||||
if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
|
||||
if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
|
||||
y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
|
||||
x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
|
||||
y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (x >= 64 || y >= 64 || x < 0 || y < 0)
|
||||
if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
|
||||
|| y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
|
||||
|| x < 0
|
||||
|| y < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -740,20 +744,20 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
int avx = (int)x;
|
||||
if (avx < 0)
|
||||
avx = 0;
|
||||
else if (avx >= (int)Constants.RegionSize)
|
||||
else if (avx >= m_scene.RegionInfo.RegionSizeX)
|
||||
avx = (int)Constants.RegionSize - 1;
|
||||
|
||||
int avy = (int)y;
|
||||
if (avy < 0)
|
||||
avy = 0;
|
||||
else if (avy >= (int)Constants.RegionSize)
|
||||
else if (avy >= m_scene.RegionInfo.RegionSizeY)
|
||||
avy = (int)Constants.RegionSize - 1;
|
||||
|
||||
lock (m_landIDList)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_landList[m_landIDList[avx / 4, avy / 4]];
|
||||
return m_landList[m_landIDList[avx / landUnit, avy / landUnit]];
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
|
@ -764,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
|
||||
public ILandObject GetLandObject(int x, int y)
|
||||
{
|
||||
if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
|
||||
if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
|
||||
{
|
||||
// These exceptions here will cause a lot of complaints from the users specifically because
|
||||
// they happen every time at border crossings
|
||||
|
@ -1057,9 +1061,10 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
int byteArrayCount = 0;
|
||||
int sequenceID = 0;
|
||||
|
||||
for (int y = 0; y < Constants.RegionSize; y += 4)
|
||||
// Layer data is in landUnit (4m) chunks
|
||||
for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += landUnit)
|
||||
{
|
||||
for (int x = 0; x < Constants.RegionSize; x += 4)
|
||||
for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += landUnit)
|
||||
{
|
||||
byte tempByte = 0; //This represents the byte for the current 4x4
|
||||
|
||||
|
@ -1769,7 +1774,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
{
|
||||
// most likely still cached from building the extLandData entry
|
||||
uint x = 0, y = 0;
|
||||
Utils.LongToUInts(data.RegionHandle, out x, out y);
|
||||
Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
|
||||
info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
}
|
||||
// we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
|
||||
|
|
|
@ -45,15 +45,13 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
#region Member Variables
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#pragma warning disable 0429
|
||||
private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
|
||||
#pragma warning restore 0429
|
||||
private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
|
||||
private static readonly string LogHeader = "[LAND OBJECT]";
|
||||
|
||||
private readonly int landUnit = 4;
|
||||
|
||||
private int m_lastSeqId = 0;
|
||||
private int m_expiryCounter = 0;
|
||||
|
||||
protected LandData m_landData = new LandData();
|
||||
protected Scene m_scene;
|
||||
protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
|
||||
protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
|
||||
|
@ -61,6 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
|
||||
protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
|
||||
|
||||
private bool[,] m_landBitmap;
|
||||
public bool[,] LandBitmap
|
||||
{
|
||||
get { return m_landBitmap; }
|
||||
|
@ -76,6 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
return free;
|
||||
}
|
||||
|
||||
protected LandData m_landData;
|
||||
public LandData LandData
|
||||
{
|
||||
get { return m_landData; }
|
||||
|
@ -94,12 +94,12 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
{
|
||||
get
|
||||
{
|
||||
for (int y = 0; y < landArrayMax; y++)
|
||||
for (int y = 0; y < LandBitmap.GetLength(1); y++)
|
||||
{
|
||||
for (int x = 0; x < landArrayMax; x++)
|
||||
for (int x = 0; x < LandBitmap.GetLength(0); x++)
|
||||
{
|
||||
if (LandBitmap[x, y])
|
||||
return new Vector3(x * 4, y * 4, 0);
|
||||
return new Vector3(x * landUnit, y * landUnit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,13 +111,13 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
{
|
||||
get
|
||||
{
|
||||
for (int y = landArrayMax - 1; y >= 0; y--)
|
||||
for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
|
||||
{
|
||||
for (int x = landArrayMax - 1; x >= 0; x--)
|
||||
for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
|
||||
{
|
||||
if (LandBitmap[x, y])
|
||||
{
|
||||
return new Vector3(x * 4 + 4, y * 4 + 4, 0);
|
||||
return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,9 +128,21 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
|
||||
#region Constructors
|
||||
|
||||
public LandObject(LandData landData, Scene scene)
|
||||
{
|
||||
LandData = landData.Copy();
|
||||
m_scene = scene;
|
||||
}
|
||||
|
||||
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
|
||||
{
|
||||
m_scene = scene;
|
||||
if (m_scene == null)
|
||||
LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
|
||||
else
|
||||
LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
|
||||
|
||||
LandData = new LandData();
|
||||
LandData.OwnerID = owner_id;
|
||||
if (is_group_owned)
|
||||
LandData.GroupID = owner_id;
|
||||
|
@ -155,9 +167,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
/// <returns>Returns true if the piece of land contains the specified point</returns>
|
||||
public bool ContainsPoint(int x, int y)
|
||||
{
|
||||
if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize)
|
||||
if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
|
||||
{
|
||||
return (LandBitmap[x / 4, y / 4] == true);
|
||||
return LandBitmap[x / landUnit, y / landUnit];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -197,10 +209,10 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
else
|
||||
{
|
||||
// Normal Calculations
|
||||
int parcelMax = (int)((long)LandData.Area
|
||||
int parcelMax = (int)( (long)LandData.Area
|
||||
* (long)m_scene.RegionInfo.ObjectCapacity
|
||||
* (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
|
||||
/ 65536L);
|
||||
/ (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
|
||||
//m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
|
||||
return parcelMax;
|
||||
}
|
||||
|
@ -231,8 +243,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
else
|
||||
{
|
||||
//Normal Calculations
|
||||
int simMax = (int)((long)LandData.SimwideArea
|
||||
* (long)m_scene.RegionInfo.ObjectCapacity / 65536L);
|
||||
int simMax = (int)( (long)LandData.SimwideArea
|
||||
* (long)m_scene.RegionInfo.ObjectCapacity
|
||||
/ (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
|
||||
// m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
|
||||
return simMax;
|
||||
}
|
||||
|
@ -597,8 +610,8 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
try
|
||||
{
|
||||
over =
|
||||
m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
|
||||
Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
|
||||
m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
|
||||
Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -752,9 +765,9 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
int max_y = Int32.MinValue;
|
||||
int tempArea = 0;
|
||||
int x, y;
|
||||
for (x = 0; x < 64; x++)
|
||||
for (x = 0; x < LandBitmap.GetLength(0); x++)
|
||||
{
|
||||
for (y = 0; y < 64; y++)
|
||||
for (y = 0; y < LandBitmap.GetLength(1); y++)
|
||||
{
|
||||
if (LandBitmap[x, y] == true)
|
||||
{
|
||||
|
@ -766,23 +779,25 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
max_x = x;
|
||||
if (max_y < y)
|
||||
max_y = y;
|
||||
tempArea += 16; //16sqm peice of land
|
||||
tempArea += landUnit * landUnit; //16sqm peice of land
|
||||
}
|
||||
}
|
||||
}
|
||||
int tx = min_x * landUnit;
|
||||
if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
|
||||
tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
|
||||
|
||||
int tx = min_x * 4;
|
||||
int htx;
|
||||
if (tx == ((int)Constants.RegionSize))
|
||||
htx = tx - 1;
|
||||
if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
|
||||
htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
|
||||
else
|
||||
htx = tx;
|
||||
|
||||
int ty = min_y * 4;
|
||||
int ty = min_y * landUnit;
|
||||
int hty;
|
||||
|
||||
if (ty == ((int)Constants.RegionSize))
|
||||
hty = ty - 1;
|
||||
if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
|
||||
hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
|
||||
else
|
||||
hty = ty;
|
||||
|
||||
|
@ -791,17 +806,17 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
(float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
|
||||
|
||||
max_x++;
|
||||
tx = max_x * 4;
|
||||
if (tx == ((int)Constants.RegionSize))
|
||||
htx = tx - 1;
|
||||
tx = max_x * landUnit;
|
||||
if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
|
||||
htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
|
||||
else
|
||||
htx = tx;
|
||||
|
||||
max_y++;
|
||||
ty = max_y * 4;
|
||||
|
||||
if (ty == ((int)Constants.RegionSize))
|
||||
hty = ty - 1;
|
||||
if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
|
||||
hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
|
||||
else
|
||||
hty = ty;
|
||||
|
||||
|
@ -819,20 +834,11 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
/// <summary>
|
||||
/// Sets the land's bitmap manually
|
||||
/// </summary>
|
||||
/// <param name="bitmap">64x64 block representing where this land is on a map</param>
|
||||
/// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
|
||||
public void SetLandBitmap(bool[,] bitmap)
|
||||
{
|
||||
if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
|
||||
{
|
||||
//Throw an exception - The bitmap is not 64x64
|
||||
//throw new Exception("Error: Invalid Parcel Bitmap");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Valid: Lets set it
|
||||
LandBitmap = bitmap;
|
||||
ForceUpdateLandInfo();
|
||||
}
|
||||
LandBitmap = bitmap;
|
||||
ForceUpdateLandInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -846,14 +852,16 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
|
||||
public bool[,] BasicFullRegionLandBitmap()
|
||||
{
|
||||
return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
|
||||
return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
|
||||
}
|
||||
|
||||
public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
|
||||
{
|
||||
bool[,] tempBitmap = new bool[64,64];
|
||||
// Empty bitmap for the whole region
|
||||
bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
|
||||
tempBitmap.Initialize();
|
||||
|
||||
// Fill the bitmap square area specified by state and end
|
||||
tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
|
||||
return tempBitmap;
|
||||
}
|
||||
|
@ -871,19 +879,13 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
|
||||
bool set_value)
|
||||
{
|
||||
if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
|
||||
{
|
||||
//Throw an exception - The bitmap is not 64x64
|
||||
//throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
|
||||
}
|
||||
|
||||
int x, y;
|
||||
for (y = 0; y < 64; y++)
|
||||
for (y = 0; y < land_bitmap.GetLength(1); y++)
|
||||
{
|
||||
for (x = 0; x < 64; x++)
|
||||
for (x = 0; x < land_bitmap.GetLength(0); x++)
|
||||
{
|
||||
if (x >= start_x / 4 && x < end_x / 4
|
||||
&& y >= start_y / 4 && y < end_y / 4)
|
||||
if (x >= start_x / landUnit && x < end_x / landUnit
|
||||
&& y >= start_y / landUnit && y < end_y / landUnit)
|
||||
{
|
||||
land_bitmap[x, y] = set_value;
|
||||
}
|
||||
|
@ -900,21 +902,21 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
/// <returns></returns>
|
||||
public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
|
||||
{
|
||||
if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
|
||||
if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
|
||||
|| bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
|
||||
|| bitmap_add.Rank != 2
|
||||
|| bitmap_base.Rank != 2)
|
||||
{
|
||||
//Throw an exception - The bitmap is not 64x64
|
||||
throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
|
||||
}
|
||||
if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
|
||||
{
|
||||
//Throw an exception - The bitmap is not 64x64
|
||||
throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
|
||||
throw new Exception(
|
||||
String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
|
||||
LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
|
||||
);
|
||||
}
|
||||
|
||||
int x, y;
|
||||
for (y = 0; y < 64; y++)
|
||||
for (y = 0; y < bitmap_base.GetLength(1); y++)
|
||||
{
|
||||
for (x = 0; x < 64; x++)
|
||||
for (x = 0; x < bitmap_add.GetLength(0); x++)
|
||||
{
|
||||
if (bitmap_add[x, y])
|
||||
{
|
||||
|
@ -931,14 +933,14 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
/// <returns></returns>
|
||||
private byte[] ConvertLandBitmapToBytes()
|
||||
{
|
||||
byte[] tempConvertArr = new byte[512];
|
||||
byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
|
||||
int tempByte = 0;
|
||||
int x, y, i, byteNum = 0;
|
||||
int i, byteNum = 0;
|
||||
int mask = 1;
|
||||
i = 0;
|
||||
for (y = 0; y < 64; y++)
|
||||
for (int y = 0; y < LandBitmap.GetLength(1); y++)
|
||||
{
|
||||
for (x = 0; x < 64; x++)
|
||||
for (int x = 0; x < LandBitmap.GetLength(0); x++)
|
||||
{
|
||||
if (LandBitmap[x, y])
|
||||
tempByte |= mask;
|
||||
|
@ -971,25 +973,45 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
|
||||
private bool[,] ConvertBytesToLandBitmap()
|
||||
{
|
||||
bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
|
||||
bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
|
||||
tempConvertMap.Initialize();
|
||||
byte tempByte = 0;
|
||||
int x = 0, y = 0, i = 0, bitNum = 0;
|
||||
for (i = 0; i < 512; i++)
|
||||
// Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
|
||||
int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
|
||||
int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
|
||||
|
||||
if (bitmapLen == 512)
|
||||
{
|
||||
// Legacy bitmap being passed in. Use the legacy region size
|
||||
// and only set the lower area of the larger region.
|
||||
xLen = (int)(Constants.RegionSize / landUnit);
|
||||
}
|
||||
// m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
|
||||
|
||||
int x = 0, y = 0;
|
||||
for (int i = 0; i < bitmapLen; i++)
|
||||
{
|
||||
tempByte = LandData.Bitmap[i];
|
||||
for (bitNum = 0; bitNum < 8; bitNum++)
|
||||
for (int bitNum = 0; bitNum < 8; bitNum++)
|
||||
{
|
||||
bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
|
||||
tempConvertMap[x, y] = bit;
|
||||
try
|
||||
{
|
||||
tempConvertMap[x, y] = bit;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
|
||||
}
|
||||
x++;
|
||||
if (x > 63)
|
||||
if (x >= xLen)
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempConvertMap;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
|
||||
terrainRenderer.Initialise(m_scene, m_config);
|
||||
|
||||
mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
|
||||
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
//long t = System.Environment.TickCount;
|
||||
//for (int i = 0; i < 10; ++i) {
|
||||
terrainRenderer.TerrainToBitmap(mapbmp);
|
||||
|
@ -277,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
|
||||
{
|
||||
int tc = 0;
|
||||
double[,] hm = whichScene.Heightmap.GetDoubles();
|
||||
ITerrainChannel hm = whichScene.Heightmap;
|
||||
tc = Environment.TickCount;
|
||||
m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
|
||||
EntityBase[] objs = whichScene.GetEntities();
|
||||
|
@ -363,7 +364,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
Vector3 pos = part.GetWorldPosition();
|
||||
|
||||
// skip prim outside of retion
|
||||
if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
|
||||
if (!m_scene.PositionIsInCurrentRegion(pos))
|
||||
continue;
|
||||
|
||||
// skip prim in non-finite position
|
||||
|
@ -388,7 +389,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
|
||||
Vector3 scale = new Vector3();
|
||||
Vector3 tScale = new Vector3();
|
||||
Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
|
||||
Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
|
||||
|
||||
Quaternion llrot = part.GetWorldRotation();
|
||||
Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
|
||||
|
@ -406,9 +407,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
int mapdrawendY = (int)(pos.Y + scale.Y);
|
||||
|
||||
// If object is beyond the edge of the map, don't draw it to avoid errors
|
||||
if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
|
||||
|| mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
|
||||
|| mapdrawendY > ((int)Constants.RegionSize - 1))
|
||||
if (mapdrawstartX < 0
|
||||
|| mapdrawstartX > (hm.Width - 1)
|
||||
|| mapdrawendX < 0
|
||||
|| mapdrawendX > (hm.Width - 1)
|
||||
|| mapdrawstartY < 0
|
||||
|| mapdrawstartY > (hm.Height - 1)
|
||||
|| mapdrawendY < 0
|
||||
|| mapdrawendY > (hm.Height - 1))
|
||||
continue;
|
||||
|
||||
#region obb face reconstruction part duex
|
||||
|
@ -530,11 +536,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
for (int i = 0; i < FaceA.Length; i++)
|
||||
{
|
||||
Point[] working = new Point[5];
|
||||
working[0] = project(FaceA[i], axPos);
|
||||
working[1] = project(FaceB[i], axPos);
|
||||
working[2] = project(FaceD[i], axPos);
|
||||
working[3] = project(FaceC[i], axPos);
|
||||
working[4] = project(FaceA[i], axPos);
|
||||
working[0] = project(hm, FaceA[i], axPos);
|
||||
working[1] = project(hm, FaceB[i], axPos);
|
||||
working[2] = project(hm, FaceD[i], axPos);
|
||||
working[3] = project(hm, FaceC[i], axPos);
|
||||
working[4] = project(hm, FaceA[i], axPos);
|
||||
|
||||
face workingface = new face();
|
||||
workingface.pts = working;
|
||||
|
@ -609,17 +615,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
return mapbmp;
|
||||
}
|
||||
|
||||
private Point project(Vector3 point3d, Vector3 originpos)
|
||||
private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
|
||||
{
|
||||
Point returnpt = new Point();
|
||||
//originpos = point3d;
|
||||
//int d = (int)(256f / 1.5f);
|
||||
|
||||
//Vector3 topos = new Vector3(0, 0, 0);
|
||||
// float z = -point3d.z - topos.z;
|
||||
// float z = -point3d.z - topos.z;
|
||||
|
||||
returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
|
||||
returnpt.Y = (int)(((int)Constants.RegionSize - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
|
||||
returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
|
||||
|
||||
return returnpt;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Reflection;
|
|||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.LegacyMap
|
||||
|
@ -39,8 +40,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
{
|
||||
private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
|
||||
|
||||
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 = "[SHADED MAPTILE RENDERER]";
|
||||
|
||||
private Scene m_scene;
|
||||
//private IConfigSource m_config; // not used currently
|
||||
|
@ -53,19 +54,26 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
|
||||
public void TerrainToBitmap(Bitmap mapbmp)
|
||||
{
|
||||
m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
|
||||
int tc = Environment.TickCount;
|
||||
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
|
||||
|
||||
double[,] hm = m_scene.Heightmap.GetDoubles();
|
||||
ITerrainChannel hm = m_scene.Heightmap;
|
||||
|
||||
if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
|
||||
{
|
||||
m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
|
||||
LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
|
||||
}
|
||||
|
||||
bool ShadowDebugContinue = true;
|
||||
|
||||
bool terraincorruptedwarningsaid = false;
|
||||
|
||||
float low = 255;
|
||||
float high = 0;
|
||||
for (int x = 0; x < (int)Constants.RegionSize; x++)
|
||||
for (int x = 0; x < hm.Width; x++)
|
||||
{
|
||||
for (int y = 0; y < (int)Constants.RegionSize; y++)
|
||||
for (int y = 0; y < hm.Height; y++)
|
||||
{
|
||||
float hmval = (float)hm[x, y];
|
||||
if (hmval < low)
|
||||
|
@ -77,12 +85,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
|
||||
float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
|
||||
|
||||
for (int x = 0; x < (int)Constants.RegionSize; x++)
|
||||
for (int x = 0; x < hm.Width; x++)
|
||||
{
|
||||
for (int y = 0; y < (int)Constants.RegionSize; y++)
|
||||
for (int y = 0; y < hm.Height; y++)
|
||||
{
|
||||
// Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
|
||||
int yr = ((int)Constants.RegionSize - 1) - y;
|
||||
int yr = ((int)hm.Height - 1) - y;
|
||||
|
||||
float heightvalue = (float)hm[x, y];
|
||||
|
||||
|
@ -109,12 +117,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
// .
|
||||
//
|
||||
// Shade the terrain for shadows
|
||||
if (x < ((int)Constants.RegionSize - 1) && yr < ((int)Constants.RegionSize - 1))
|
||||
if (x < (hm.Width - 1) && yr < (hm.Height - 1))
|
||||
{
|
||||
float hfvalue = (float)hm[x, y];
|
||||
float hfvaluecompare = 0f;
|
||||
|
||||
if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
|
||||
if ((x + 1 < hm.Width) && (y + 1 < hm.Height))
|
||||
{
|
||||
hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
|
||||
}
|
||||
|
@ -179,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
|
||||
if (ShadowDebugContinue)
|
||||
{
|
||||
if ((x - 1 > 0) && (yr + 1 < (int)Constants.RegionSize))
|
||||
if ((x - 1 > 0) && (yr + 1 < hm.Height))
|
||||
{
|
||||
color = mapbmp.GetPixel(x - 1, yr + 1);
|
||||
int r = color.R;
|
||||
|
@ -233,7 +241,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
terraincorruptedwarningsaid = true;
|
||||
}
|
||||
Color black = Color.Black;
|
||||
mapbmp.SetPixel(x, ((int)Constants.RegionSize - y) - 1, black);
|
||||
mapbmp.SetPixel(x, (hm.Width - y) - 1, black);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -242,4 +250,4 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
|
|||
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,14 +151,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
|
|||
break;
|
||||
|
||||
case 2: // Sell a copy
|
||||
Vector3 inventoryStoredPosition = new Vector3
|
||||
(((group.AbsolutePosition.X > (int)Constants.RegionSize)
|
||||
? 250
|
||||
: group.AbsolutePosition.X)
|
||||
,
|
||||
(group.AbsolutePosition.X > (int)Constants.RegionSize)
|
||||
? 250
|
||||
: group.AbsolutePosition.X,
|
||||
Vector3 inventoryStoredPosition = new Vector3(
|
||||
Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
|
||||
Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
|
||||
group.AbsolutePosition.Z);
|
||||
|
||||
Vector3 originalPosition = group.AbsolutePosition;
|
||||
|
|
|
@ -1571,10 +1571,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
|||
float X = position.X;
|
||||
float Y = position.Y;
|
||||
|
||||
if (X > ((int)Constants.RegionSize - 1))
|
||||
X = ((int)Constants.RegionSize - 1);
|
||||
if (Y > ((int)Constants.RegionSize - 1))
|
||||
Y = ((int)Constants.RegionSize - 1);
|
||||
if (X > ((int)m_scene.RegionInfo.RegionSizeX - 1))
|
||||
X = ((int)m_scene.RegionInfo.RegionSizeX - 1);
|
||||
if (Y > ((int)m_scene.RegionInfo.RegionSizeY - 1))
|
||||
Y = ((int)m_scene.RegionInfo.RegionSizeY - 1);
|
||||
if (X < 0)
|
||||
X = 0;
|
||||
if (Y < 0)
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
|
|||
for (y = 0; y < map.Height; y++)
|
||||
{
|
||||
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
|
||||
double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01;
|
||||
double spherFac = TerrainUtil.SphericalFactor(x, y, map.Width / 2, map.Height / 2, 50) * 0.01;
|
||||
if (map[x, y] < spherFac)
|
||||
{
|
||||
map[x, y] = spherFac;
|
||||
|
@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
|
|||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
{
|
||||
using (Bitmap bitmap = new Bitmap(filename))
|
||||
{
|
||||
ITerrainChannel retval = new TerrainChannel(true);
|
||||
ITerrainChannel retval = new TerrainChannel(w, h);
|
||||
|
||||
for (int x = 0; x < retval.Width; x++)
|
||||
{
|
||||
|
|
|
@ -154,10 +154,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
|
||||
public ITerrainChannel LoadStream(Stream s)
|
||||
{
|
||||
|
||||
// Set to default size
|
||||
int w = (int)Constants.RegionSize;
|
||||
int h = (int)Constants.RegionSize;
|
||||
|
||||
// create a dummy channel (in case data is bad)
|
||||
TerrainChannel retval = new TerrainChannel(w, h);
|
||||
|
||||
BinaryReader bs = new BinaryReader(s);
|
||||
|
@ -165,8 +166,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
bool eof = false;
|
||||
if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
|
||||
{
|
||||
// int fileWidth = w;
|
||||
// int fileHeight = h;
|
||||
|
||||
// Terragen file
|
||||
while (eof == false)
|
||||
|
@ -175,31 +174,29 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
switch (tmp)
|
||||
{
|
||||
case "SIZE":
|
||||
// int sztmp = bs.ReadInt16() + 1;
|
||||
// fileWidth = sztmp;
|
||||
// fileHeight = sztmp;
|
||||
bs.ReadInt16();
|
||||
w = bs.ReadInt16() + 1;
|
||||
h = w;
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "XPTS":
|
||||
// fileWidth = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
w = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "YPTS":
|
||||
// fileHeight = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
h = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "ALTW":
|
||||
eof = true;
|
||||
Int16 heightScale = bs.ReadInt16();
|
||||
Int16 baseHeight = bs.ReadInt16();
|
||||
// create new channel of proper size (now that we know it)
|
||||
retval = new TerrainChannel(w, h);
|
||||
double heightScale = (double)bs.ReadInt16() / 65536.0;
|
||||
double baseHeight = (double)bs.ReadInt16();
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0;
|
||||
retval[x, y] = baseHeight + (double)bs.ReadInt16() * heightScale;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -257,17 +254,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
|
||||
|
||||
bs.Write(enc.GetBytes("SIZE"));
|
||||
bs.Write(Convert.ToInt16(Constants.RegionSize));
|
||||
bs.Write(Convert.ToInt16(map.Width));
|
||||
bs.Write(Convert.ToInt16(0)); // necessary padding
|
||||
|
||||
//The XPTS and YPTS chunks are not needed for square regions
|
||||
//but L3DT won't load the terrain file properly without them.
|
||||
bs.Write(enc.GetBytes("XPTS"));
|
||||
bs.Write(Convert.ToInt16(Constants.RegionSize));
|
||||
bs.Write(Convert.ToInt16(map.Width));
|
||||
bs.Write(Convert.ToInt16(0)); // necessary padding
|
||||
|
||||
bs.Write(enc.GetBytes("YPTS"));
|
||||
bs.Write(Convert.ToInt16(Constants.RegionSize));
|
||||
bs.Write(Convert.ToInt16(map.Height));
|
||||
bs.Write(Convert.ToInt16(0)); // necessary padding
|
||||
|
||||
bs.Write(enc.GetBytes("SCAL"));
|
||||
|
@ -283,11 +280,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
|||
bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min
|
||||
bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point
|
||||
|
||||
double factor = 65536.0 / horizontalScale; // avoid computing this on each iteration
|
||||
|
||||
for (int y = 0; y < map.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < map.Width; x++)
|
||||
{
|
||||
float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse
|
||||
float elevation = (float)((map[x,y] - baseHeight) * factor); // see LoadStream for inverse
|
||||
|
||||
// clamp rounding issues
|
||||
if (elevation > Int16.MaxValue)
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
|
|||
{
|
||||
if (fillArea[x, y])
|
||||
{
|
||||
double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0);
|
||||
double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
|
||||
|
||||
map[x, y] += noise * strength;
|
||||
}
|
||||
|
@ -55,4 +55,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
|
|||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
|
|||
z *= z;
|
||||
z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
|
||||
|
||||
double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0);
|
||||
double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
|
||||
|
||||
if (z > 0.0)
|
||||
map[x, y] += noise * z * duration;
|
||||
|
|
|
@ -71,6 +71,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
#pragma warning disable 414
|
||||
private static readonly string LogHeader = "[TERRAIN MODULE]";
|
||||
#pragma warning restore 414
|
||||
|
||||
private readonly Commander m_commander = new Commander("terrain");
|
||||
|
||||
private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
|
||||
|
@ -81,8 +85,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
|
||||
new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
|
||||
|
||||
private ITerrainChannel m_channel;
|
||||
private Dictionary<string, ITerrainEffect> m_plugineffects;
|
||||
private ITerrainChannel m_channel;
|
||||
private ITerrainChannel m_revert;
|
||||
private Scene m_scene;
|
||||
private volatile bool m_tainted;
|
||||
|
@ -90,6 +94,85 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
|
||||
private String m_InitialTerrain = "pinhead-island";
|
||||
|
||||
// If true, send terrain patch updates to clients based on their view distance
|
||||
private bool m_sendTerrainUpdatesByViewDistance = true;
|
||||
|
||||
// Class to keep the per client collection of terrain patches that must be sent.
|
||||
// A patch is set to 'true' meaning it should be sent to the client. Once the
|
||||
// patch packet is queued to the client, the bit for that patch is set to 'false'.
|
||||
private class PatchUpdates
|
||||
{
|
||||
private bool[,] updated; // for each patch, whether it needs to be sent to this client
|
||||
private int updateCount; // number of patches that need to be sent
|
||||
public ScenePresence Presence; // a reference to the client to send to
|
||||
public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
|
||||
{
|
||||
updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
|
||||
updateCount = 0;
|
||||
Presence = pPresence;
|
||||
// Initially, send all patches to the client
|
||||
SetAll(true);
|
||||
}
|
||||
// Returns 'true' if there are any patches marked for sending
|
||||
public bool HasUpdates()
|
||||
{
|
||||
return (updateCount > 0);
|
||||
}
|
||||
public void SetByXY(int x, int y, bool state)
|
||||
{
|
||||
this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
|
||||
}
|
||||
public bool GetByPatch(int patchX, int patchY)
|
||||
{
|
||||
return updated[patchX, patchY];
|
||||
}
|
||||
public void SetByPatch(int patchX, int patchY, bool state)
|
||||
{
|
||||
bool prevState = updated[patchX, patchY];
|
||||
if (!prevState && state)
|
||||
updateCount++;
|
||||
if (prevState && !state)
|
||||
updateCount--;
|
||||
updated[patchX, patchY] = state;
|
||||
}
|
||||
public void SetAll(bool state)
|
||||
{
|
||||
updateCount = 0;
|
||||
for (int xx = 0; xx < updated.GetLength(0); xx++)
|
||||
for (int yy = 0; yy < updated.GetLength(1); yy++)
|
||||
updated[xx, yy] = state;
|
||||
if (state)
|
||||
updateCount = updated.GetLength(0) * updated.GetLength(1);
|
||||
}
|
||||
// Logically OR's the terrain data's patch taint map into this client's update map.
|
||||
public void SetAll(TerrainData terrData)
|
||||
{
|
||||
if (updated.GetLength(0) != (terrData.SizeX / Constants.TerrainPatchSize)
|
||||
|| updated.GetLength(1) != (terrData.SizeY / Constants.TerrainPatchSize))
|
||||
{
|
||||
throw new Exception(
|
||||
String.Format("{0} PatchUpdates.SetAll: patch array not same size as terrain. arr=<{1},{2}>, terr=<{3},{4}>",
|
||||
LogHeader, updated.GetLength(0), updated.GetLength(1),
|
||||
terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
|
||||
);
|
||||
}
|
||||
for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
|
||||
{
|
||||
for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
|
||||
{
|
||||
// Only set tainted. The patch bit may be set if the patch was to be sent later.
|
||||
if (terrData.IsTaintedAt(xx, yy, false))
|
||||
{
|
||||
this.SetByXY(xx, yy, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The flags of which terrain patches to send for each of the ScenePresence's
|
||||
private Dictionary<UUID, PatchUpdates> m_perClientPatchUpdates = new Dictionary<UUID, PatchUpdates>();
|
||||
|
||||
/// <summary>
|
||||
/// Human readable list of terrain file extensions that are supported.
|
||||
/// </summary>
|
||||
|
@ -118,7 +201,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
IConfig terrainConfig = config.Configs["Terrain"];
|
||||
if (terrainConfig != null)
|
||||
{
|
||||
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
|
||||
m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
|
@ -130,22 +216,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
if (m_scene.Heightmap == null)
|
||||
{
|
||||
m_channel = new TerrainChannel(m_InitialTerrain);
|
||||
m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
|
||||
(int)m_scene.RegionInfo.RegionSizeY,
|
||||
(int)m_scene.RegionInfo.RegionSizeZ);
|
||||
m_scene.Heightmap = m_channel;
|
||||
m_revert = new TerrainChannel();
|
||||
UpdateRevertMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channel = m_scene.Heightmap;
|
||||
m_revert = new TerrainChannel();
|
||||
UpdateRevertMap();
|
||||
}
|
||||
|
||||
m_scene.RegisterModuleInterface<ITerrainModule>(this);
|
||||
m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
|
||||
m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
|
||||
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
|
||||
m_scene.EventManager.OnFrame += EventManager_OnFrame;
|
||||
}
|
||||
|
||||
InstallDefaultEffects();
|
||||
|
@ -184,8 +272,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
// remove the commands
|
||||
m_scene.UnregisterModuleCommander(m_commander.Name);
|
||||
// remove the event-handlers
|
||||
m_scene.EventManager.OnFrame -= EventManager_OnFrame;
|
||||
m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
|
||||
m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
|
||||
m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
|
||||
m_scene.EventManager.OnNewClient -= EventManager_OnNewClient;
|
||||
// remove the interface
|
||||
m_scene.UnregisterModuleInterface<ITerrainModule>(this);
|
||||
|
@ -230,11 +320,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
try
|
||||
{
|
||||
ITerrainChannel channel = loader.Value.LoadFile(filename);
|
||||
if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize)
|
||||
if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY)
|
||||
{
|
||||
// TerrainChannel expects a RegionSize x RegionSize map, currently
|
||||
throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
|
||||
Constants.RegionSize, Constants.RegionSize));
|
||||
m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY));
|
||||
}
|
||||
m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
|
||||
m_scene.Heightmap = channel;
|
||||
|
@ -261,7 +351,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
String.Format("Unable to load heightmap: {0}", e.Message));
|
||||
}
|
||||
}
|
||||
CheckForTerrainUpdates();
|
||||
m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
|
||||
return;
|
||||
}
|
||||
|
@ -309,12 +398,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
LoadFromStream(filename, URIFetch(pathToTerrainHeightmap));
|
||||
}
|
||||
|
||||
public void LoadFromStream(string filename, Stream stream)
|
||||
{
|
||||
LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a terrain file from a stream and installs it in the scene.
|
||||
/// </summary>
|
||||
/// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
|
||||
/// <param name="stream"></param>
|
||||
public void LoadFromStream(string filename, Stream stream)
|
||||
public void LoadFromStream(string filename, Vector3 displacement,
|
||||
float radianRotation, Vector2 rotationDisplacement, Stream stream)
|
||||
{
|
||||
foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
|
||||
{
|
||||
|
@ -325,8 +420,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
try
|
||||
{
|
||||
ITerrainChannel channel = loader.Value.LoadStream(stream);
|
||||
m_scene.Heightmap = channel;
|
||||
m_channel = channel;
|
||||
m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
|
||||
UpdateRevertMap();
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
|
@ -337,7 +431,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
}
|
||||
}
|
||||
|
||||
CheckForTerrainUpdates();
|
||||
m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
|
||||
return;
|
||||
}
|
||||
|
@ -406,9 +499,46 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
}
|
||||
}
|
||||
|
||||
// Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
|
||||
// ITerrainModule.TaintTerrain()
|
||||
public void TaintTerrain ()
|
||||
{
|
||||
CheckForTerrainUpdates();
|
||||
lock (m_perClientPatchUpdates)
|
||||
{
|
||||
// Set the flags for all clients so the tainted patches will be sent out
|
||||
foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
|
||||
{
|
||||
pups.SetAll(m_scene.Heightmap.GetTerrainData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ITerrainModule.PushTerrain()
|
||||
public void PushTerrain(IClientAPI pClient)
|
||||
{
|
||||
if (m_sendTerrainUpdatesByViewDistance)
|
||||
{
|
||||
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
|
||||
if (presence != null)
|
||||
{
|
||||
lock (m_perClientPatchUpdates)
|
||||
{
|
||||
PatchUpdates pups;
|
||||
if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
|
||||
{
|
||||
// There is a ScenePresence without a send patch map. Create one.
|
||||
pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
|
||||
m_perClientPatchUpdates.Add(presence.UUID, pups);
|
||||
}
|
||||
pups.SetAll(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The traditional way is to call into the protocol stack to send them all.
|
||||
pClient.SendLayerData(new float[10]);
|
||||
}
|
||||
}
|
||||
|
||||
#region Plugin Loading Methods
|
||||
|
@ -532,6 +662,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
/// </summary>
|
||||
public void UpdateRevertMap()
|
||||
{
|
||||
/*
|
||||
int x;
|
||||
for (x = 0; x < m_channel.Width; x++)
|
||||
{
|
||||
|
@ -541,6 +672,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_revert[x, y] = m_channel[x, y];
|
||||
}
|
||||
}
|
||||
*/
|
||||
m_revert = m_channel.MakeCopy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -567,8 +700,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
|
||||
fileWidth, fileHeight,
|
||||
(int) Constants.RegionSize,
|
||||
(int) Constants.RegionSize);
|
||||
(int) m_scene.RegionInfo.RegionSizeX,
|
||||
(int) m_scene.RegionInfo.RegionSizeY);
|
||||
m_scene.Heightmap = channel;
|
||||
m_channel = channel;
|
||||
UpdateRevertMap();
|
||||
|
@ -615,8 +748,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
|
||||
fileWidth, fileHeight,
|
||||
(int)Constants.RegionSize,
|
||||
(int)Constants.RegionSize);
|
||||
(int)m_scene.RegionInfo.RegionSizeX,
|
||||
(int)m_scene.RegionInfo.RegionSizeY);
|
||||
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}",
|
||||
|
@ -633,8 +766,45 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called before processing of every simulation frame.
|
||||
/// This is used to check to see of any of the terrain is tainted and, if so, schedule
|
||||
/// updates for all the presences.
|
||||
/// This also checks to see if there are updates that need to be sent for each presence.
|
||||
/// This is where the logic is to send terrain updates to clients.
|
||||
/// </summary>
|
||||
private void EventManager_OnFrame()
|
||||
{
|
||||
TerrainData terrData = m_channel.GetTerrainData();
|
||||
|
||||
bool shouldTaint = false;
|
||||
for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
|
||||
{
|
||||
for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y))
|
||||
{
|
||||
// Found a patch that was modified. Push this flag into the clients.
|
||||
SendToClients(terrData, x, y);
|
||||
shouldTaint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This event also causes changes to be sent to the clients
|
||||
CheckSendingPatchesToClients();
|
||||
|
||||
// If things changes, generate some events
|
||||
if (shouldTaint)
|
||||
{
|
||||
m_scene.EventManager.TriggerTerrainTainted();
|
||||
m_tainted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
|
||||
/// Called infrequently (like every 5 seconds or so). Best used for storing terrain.
|
||||
/// </summary>
|
||||
private void EventManager_OnTerrainTick()
|
||||
{
|
||||
|
@ -644,8 +814,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
|
||||
m_scene.SaveTerrain();
|
||||
|
||||
m_scene.EventManager.TriggerTerrainUpdate();
|
||||
|
||||
// Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
|
||||
//m_scene.CreateTerrainTexture(true);
|
||||
}
|
||||
|
@ -687,54 +855,48 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the terrain has been modified since last check
|
||||
/// but won't attempt to limit those changes to the limits specified in the estate settings
|
||||
/// currently invoked by the command line operations in the region server only
|
||||
/// Installs terrain brush hook to IClientAPI
|
||||
/// </summary>
|
||||
private void CheckForTerrainUpdates()
|
||||
/// <param name="client"></param>
|
||||
private void EventManager_OnClientClosed(UUID client, Scene scene)
|
||||
{
|
||||
CheckForTerrainUpdates(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the terrain has been modified since last check.
|
||||
/// If it has been modified, every all the terrain patches are sent to the client.
|
||||
/// If the call is asked to respect the estate settings for terrain_raise_limit and
|
||||
/// terrain_lower_limit, it will clamp terrain updates between these values
|
||||
/// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
|
||||
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
|
||||
/// </summary>
|
||||
private void CheckForTerrainUpdates(bool respectEstateSettings)
|
||||
{
|
||||
bool shouldTaint = false;
|
||||
float[] serialised = m_channel.GetFloatsSerialised();
|
||||
int x;
|
||||
for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
|
||||
ScenePresence presence = scene.GetScenePresence(client);
|
||||
if (presence != null)
|
||||
{
|
||||
int y;
|
||||
for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
|
||||
{
|
||||
if (m_channel.Tainted(x, y))
|
||||
{
|
||||
// if we should respect the estate settings then
|
||||
// fixup and height deltas that don't respect them
|
||||
if (respectEstateSettings && LimitChannelChanges(x, y))
|
||||
{
|
||||
// this has been vetoed, so update
|
||||
// what we are going to send to the client
|
||||
serialised = m_channel.GetFloatsSerialised();
|
||||
}
|
||||
presence.ControllingClient.OnModifyTerrain -= client_OnModifyTerrain;
|
||||
presence.ControllingClient.OnBakeTerrain -= client_OnBakeTerrain;
|
||||
presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
|
||||
presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
|
||||
}
|
||||
|
||||
SendToClients(serialised, x, y);
|
||||
shouldTaint = true;
|
||||
lock (m_perClientPatchUpdates)
|
||||
m_perClientPatchUpdates.Remove(client);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan over changes in the terrain and limit height changes. This enforces the
|
||||
/// non-estate owner limits on rate of terrain editting.
|
||||
/// Returns 'true' if any heights were limited.
|
||||
/// </summary>
|
||||
private bool EnforceEstateLimits()
|
||||
{
|
||||
TerrainData terrData = m_channel.GetTerrainData();
|
||||
|
||||
bool wasLimited = false;
|
||||
for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
|
||||
{
|
||||
for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
|
||||
{
|
||||
// If we should respect the estate settings then
|
||||
// fixup and height deltas that don't respect them.
|
||||
// Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
|
||||
wasLimited |= LimitChannelChanges(terrData, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldTaint)
|
||||
{
|
||||
m_scene.EventManager.TriggerTerrainTainted();
|
||||
m_tainted = true;
|
||||
}
|
||||
return wasLimited;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -742,11 +904,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
/// are all within the current estate limits
|
||||
/// <returns>true if changes were limited, false otherwise</returns>
|
||||
/// </summary>
|
||||
private bool LimitChannelChanges(int xStart, int yStart)
|
||||
private bool LimitChannelChanges(TerrainData terrData, int xStart, int yStart)
|
||||
{
|
||||
bool changesLimited = false;
|
||||
double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
|
||||
double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
|
||||
float minDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
|
||||
float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
|
||||
|
||||
// loop through the height map for this patch and compare it against
|
||||
// the revert map
|
||||
|
@ -754,19 +916,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
|
||||
{
|
||||
|
||||
double requestedHeight = m_channel[x, y];
|
||||
double bakedHeight = m_revert[x, y];
|
||||
double requestedDelta = requestedHeight - bakedHeight;
|
||||
float requestedHeight = terrData[x, y];
|
||||
float bakedHeight = (float)m_revert[x, y];
|
||||
float requestedDelta = requestedHeight - bakedHeight;
|
||||
|
||||
if (requestedDelta > maxDelta)
|
||||
{
|
||||
m_channel[x, y] = bakedHeight + maxDelta;
|
||||
terrData[x, y] = bakedHeight + maxDelta;
|
||||
changesLimited = true;
|
||||
}
|
||||
else if (requestedDelta < minDelta)
|
||||
{
|
||||
m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
|
||||
terrData[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
|
||||
changesLimited = true;
|
||||
}
|
||||
}
|
||||
|
@ -794,14 +955,154 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
/// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
|
||||
/// <param name="x">The patch corner to send</param>
|
||||
/// <param name="y">The patch corner to send</param>
|
||||
private void SendToClients(float[] serialised, int x, int y)
|
||||
private void SendToClients(TerrainData terrData, int x, int y)
|
||||
{
|
||||
m_scene.ForEachClient(
|
||||
delegate(IClientAPI controller)
|
||||
{ controller.SendLayerData(
|
||||
x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
|
||||
if (m_sendTerrainUpdatesByViewDistance)
|
||||
{
|
||||
// Add that this patch needs to be sent to the accounting for each client.
|
||||
lock (m_perClientPatchUpdates)
|
||||
{
|
||||
m_scene.ForEachScenePresence(presence =>
|
||||
{
|
||||
PatchUpdates thisClientUpdates;
|
||||
if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
|
||||
{
|
||||
// There is a ScenePresence without a send patch map. Create one.
|
||||
thisClientUpdates = new PatchUpdates(terrData, presence);
|
||||
m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
|
||||
}
|
||||
thisClientUpdates.SetByXY(x, y, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy update sending where the update is sent out as soon as noticed
|
||||
// We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
|
||||
//float[] heightMap = terrData.GetFloatsSerialized();
|
||||
float[] heightMap = new float[10];
|
||||
m_scene.ForEachClient(
|
||||
delegate(IClientAPI controller)
|
||||
{
|
||||
controller.SendLayerData(x / Constants.TerrainPatchSize,
|
||||
y / Constants.TerrainPatchSize,
|
||||
heightMap);
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private class PatchesToSend : IComparable<PatchesToSend>
|
||||
{
|
||||
public int PatchX;
|
||||
public int PatchY;
|
||||
public float Dist;
|
||||
public PatchesToSend(int pX, int pY, float pDist)
|
||||
{
|
||||
PatchX = pX;
|
||||
PatchY = pY;
|
||||
Dist = pDist;
|
||||
}
|
||||
public int CompareTo(PatchesToSend other)
|
||||
{
|
||||
return Dist.CompareTo(other.Dist);
|
||||
}
|
||||
}
|
||||
|
||||
// Called each frame time to see if there are any patches to send to any of the
|
||||
// ScenePresences.
|
||||
// Loop through all the per-client info and send any patches necessary.
|
||||
private void CheckSendingPatchesToClients()
|
||||
{
|
||||
lock (m_perClientPatchUpdates)
|
||||
{
|
||||
foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
|
||||
{
|
||||
if (pups.HasUpdates())
|
||||
{
|
||||
// There is something that could be sent to this client.
|
||||
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
|
||||
if (toSend.Count > 0)
|
||||
{
|
||||
// m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
|
||||
// LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
|
||||
// Sort the patches to send by the distance from the presence
|
||||
toSend.Sort();
|
||||
/*
|
||||
foreach (PatchesToSend pts in toSend)
|
||||
{
|
||||
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
|
||||
// presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
|
||||
}
|
||||
*/
|
||||
|
||||
int[] xPieces = new int[toSend.Count];
|
||||
int[] yPieces = new int[toSend.Count];
|
||||
float[] patchPieces = new float[toSend.Count * 2];
|
||||
int pieceIndex = 0;
|
||||
foreach (PatchesToSend pts in toSend)
|
||||
{
|
||||
patchPieces[pieceIndex++] = pts.PatchX;
|
||||
patchPieces[pieceIndex++] = pts.PatchY;
|
||||
}
|
||||
pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
|
||||
{
|
||||
List<PatchesToSend> ret = new List<PatchesToSend>();
|
||||
|
||||
ScenePresence presence = pups.Presence;
|
||||
if (presence == null)
|
||||
return ret;
|
||||
|
||||
// Compute the area of patches within our draw distance
|
||||
int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
|
||||
startX = Math.Max(startX, 0);
|
||||
startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
|
||||
int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
|
||||
startY = Math.Max(startY, 0);
|
||||
startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
|
||||
int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
|
||||
endX = Math.Max(endX, 0);
|
||||
endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
|
||||
int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
|
||||
endY = Math.Max(endY, 0);
|
||||
endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
|
||||
// m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
|
||||
// LogHeader, m_scene.RegionInfo.RegionName,
|
||||
// presence.DrawDistance, presence.AbsolutePosition,
|
||||
// startX, startY, endX, endY);
|
||||
for (int x = startX; x < endX; x++)
|
||||
{
|
||||
for (int y = startY; y < endY; y++)
|
||||
{
|
||||
//Need to make sure we don't send the same ones over and over
|
||||
Vector3 presencePos = presence.AbsolutePosition;
|
||||
Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
|
||||
if (pups.GetByPatch(x, y))
|
||||
{
|
||||
//Check which has less distance, camera or avatar position, both have to be done.
|
||||
//Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off
|
||||
if (Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
|
||||
|| Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
|
||||
{
|
||||
//They can see it, send it to them
|
||||
pups.SetByPatch(x, y, false);
|
||||
float dist = Vector3.DistanceSquared(presencePos, patchPos);
|
||||
ret.Add(new PatchesToSend(x, y, dist));
|
||||
//Wait and send them all at once
|
||||
// pups.client.SendLayerData(x, y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
|
||||
|
@ -846,7 +1147,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_painteffects[(StandardTerrainEffects) action].PaintEffect(
|
||||
m_channel, allowMask, west, south, height, size, seconds);
|
||||
|
||||
CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
||||
//revert changes outside estate limits
|
||||
if (!god)
|
||||
EnforceEstateLimits();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -884,10 +1187,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
if (allowed)
|
||||
{
|
||||
StoreUndoState();
|
||||
m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
|
||||
m_channel, fillArea, size);
|
||||
m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size);
|
||||
|
||||
CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
||||
//revert changes outside estate limits
|
||||
if (!god)
|
||||
EnforceEstateLimits();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -911,7 +1215,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY)
|
||||
{
|
||||
//m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY);
|
||||
client.SendLayerData(patchX, patchY, m_scene.Heightmap.GetFloatsSerialised());
|
||||
// SendLayerData does not use the heightmap parameter. This kludge is so as to not change IClientAPI.
|
||||
float[] heightMap = new float[10];
|
||||
client.SendLayerData(patchX, patchY, heightMap);
|
||||
}
|
||||
|
||||
private void StoreUndoState()
|
||||
|
@ -938,7 +1244,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
private void InterfaceLoadFile(Object[] args)
|
||||
{
|
||||
LoadFromFile((string) args[0]);
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceLoadTileFile(Object[] args)
|
||||
|
@ -948,7 +1253,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
(int) args[2],
|
||||
(int) args[3],
|
||||
(int) args[4]);
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceSaveFile(Object[] args)
|
||||
|
@ -977,7 +1281,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
for (y = 0; y < m_channel.Height; y++)
|
||||
m_channel[x, y] = m_revert[x, y];
|
||||
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceFlipTerrain(Object[] args)
|
||||
|
@ -986,28 +1289,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
|
||||
if (direction.ToLower().StartsWith("y"))
|
||||
{
|
||||
for (int x = 0; x < Constants.RegionSize; x++)
|
||||
for (int x = 0; x < m_channel.Width; x++)
|
||||
{
|
||||
for (int y = 0; y < Constants.RegionSize / 2; y++)
|
||||
for (int y = 0; y < m_channel.Height / 2; y++)
|
||||
{
|
||||
double height = m_channel[x, y];
|
||||
double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y];
|
||||
double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
|
||||
m_channel[x, y] = flippedHeight;
|
||||
m_channel[x, (int)Constants.RegionSize - 1 - y] = height;
|
||||
m_channel[x, (int)m_channel.Height - 1 - y] = height;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (direction.ToLower().StartsWith("x"))
|
||||
{
|
||||
for (int y = 0; y < Constants.RegionSize; y++)
|
||||
for (int y = 0; y < m_channel.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < Constants.RegionSize / 2; x++)
|
||||
for (int x = 0; x < m_channel.Width / 2; x++)
|
||||
{
|
||||
double height = m_channel[x, y];
|
||||
double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y];
|
||||
double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
|
||||
m_channel[x, y] = flippedHeight;
|
||||
m_channel[(int)Constants.RegionSize - 1 - x, y] = height;
|
||||
m_channel[(int)m_channel.Width - 1 - x, y] = height;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1016,9 +1319,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
{
|
||||
m_log.Error("Unrecognised direction - need x or y");
|
||||
}
|
||||
|
||||
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceRescaleTerrain(Object[] args)
|
||||
|
@ -1076,7 +1376,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
}
|
||||
}
|
||||
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1087,7 +1386,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
for (x = 0; x < m_channel.Width; x++)
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
m_channel[x, y] += (double) args[0];
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceMultiplyTerrain(Object[] args)
|
||||
|
@ -1096,7 +1394,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
for (x = 0; x < m_channel.Width; x++)
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
m_channel[x, y] *= (double) args[0];
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceLowerTerrain(Object[] args)
|
||||
|
@ -1105,17 +1402,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
for (x = 0; x < m_channel.Width; x++)
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
m_channel[x, y] -= (double) args[0];
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceFillTerrain(Object[] args)
|
||||
public void InterfaceFillTerrain(Object[] args)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (x = 0; x < m_channel.Width; x++)
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
m_channel[x, y] = (double) args[0];
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceMinTerrain(Object[] args)
|
||||
|
@ -1128,7 +1423,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
|
||||
}
|
||||
}
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceMaxTerrain(Object[] args)
|
||||
|
@ -1141,7 +1435,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
|
||||
}
|
||||
}
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceShowDebugStats(Object[] args)
|
||||
|
@ -1204,7 +1497,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
if (m_plugineffects.ContainsKey(firstArg))
|
||||
{
|
||||
m_plugineffects[firstArg].RunEffect(m_channel);
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -40,10 +40,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
|
|||
[Test]
|
||||
public void BrushTest()
|
||||
{
|
||||
int midRegion = (int)Constants.RegionSize / 2;
|
||||
|
||||
// Create a mask that covers only the left half of the region
|
||||
bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
|
||||
int x;
|
||||
int y;
|
||||
for (x = 0; x < (int)((int)Constants.RegionSize * 0.5f); x++)
|
||||
for (x = 0; x < midRegion; x++)
|
||||
{
|
||||
for (y = 0; y < (int)Constants.RegionSize; y++)
|
||||
{
|
||||
|
@ -57,13 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
|
|||
TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
|
||||
ITerrainPaintableEffect effect = new RaiseSphere();
|
||||
|
||||
effect.PaintEffect(map, allowMask, (int)Constants.RegionSize * 0.5f, (int)Constants.RegionSize * 0.5f, -1.0, 2, 0.1);
|
||||
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (127,128).");
|
||||
Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (124,128).");
|
||||
Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (123,128).");
|
||||
Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (128,128).");
|
||||
Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (0,128).");
|
||||
|
||||
effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
|
||||
Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
|
||||
Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
|
||||
Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
|
||||
Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
|
||||
Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
|
||||
//
|
||||
// Test LowerSphere
|
||||
//
|
||||
|
@ -77,13 +79,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
|
|||
}
|
||||
effect = new LowerSphere();
|
||||
|
||||
effect.PaintEffect(map, allowMask, ((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), -1.0, 2, 6.0);
|
||||
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
|
||||
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
|
||||
Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] < 1.0, "Lower brush should lowering value at this point (124,128).");
|
||||
Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (123,128).");
|
||||
Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (128,128).");
|
||||
Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (0,128).");
|
||||
effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
|
||||
Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
|
||||
Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
|
||||
Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
|
||||
Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
|
||||
Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
|
||||
Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -55,5 +55,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// Currently, will throw an exception if this does not match a root region.
|
||||
/// </param>
|
||||
Vector2 GetSizeOfMegaregion(UUID regionId);
|
||||
|
||||
/// <summary>
|
||||
/// Tests to see of position (relative to the region) is within the megaregion
|
||||
/// </summary>
|
||||
bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy);
|
||||
}
|
||||
}
|
|
@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// </summary>
|
||||
/// <param name="ter">HeightField data</param>
|
||||
/// <param name="regionID">region UUID</param>
|
||||
void StoreTerrain(TerrainData terrain, UUID regionID);
|
||||
|
||||
// Legacy version kept for downward compabibility
|
||||
void StoreTerrain(double[,] terrain, UUID regionID);
|
||||
|
||||
/// <summary>
|
||||
/// Load the latest terrain revision from region storage
|
||||
/// </summary>
|
||||
/// <param name="regionID">the region UUID</param>
|
||||
/// <param name="sizeX">the X dimension of the region being filled</param>
|
||||
/// <param name="sizeY">the Y dimension of the region being filled</param>
|
||||
/// <param name="sizeZ">the Z dimension of the region being filled</param>
|
||||
/// <returns>Heightfield data</returns>
|
||||
TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
|
||||
|
||||
// Legacy version kept for downward compabibility
|
||||
double[,] LoadTerrain(UUID regionID);
|
||||
|
||||
void StoreLandObject(ILandObject Parcel);
|
||||
|
|
|
@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// </summary>
|
||||
/// <param name="ter">HeightField data</param>
|
||||
/// <param name="regionID">region UUID</param>
|
||||
void StoreTerrain(TerrainData terrain, UUID regionID);
|
||||
|
||||
// Legacy version kept for downward compabibility
|
||||
void StoreTerrain(double[,] terrain, UUID regionID);
|
||||
|
||||
/// <summary>
|
||||
/// Load the latest terrain revision from region storage
|
||||
/// </summary>
|
||||
/// <param name="regionID">the region UUID</param>
|
||||
/// <param name="pSizeX">the X dimension of the terrain being filled</param>
|
||||
/// <param name="pSizeY">the Y dimension of the terrain being filled</param>
|
||||
/// <param name="pSizeZ">the Z dimension of the terrain being filled</param>
|
||||
/// <returns>Heightfield data</returns>
|
||||
TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
|
||||
|
||||
// Legacy version kept for downward compabibility
|
||||
double[,] LoadTerrain(UUID regionID);
|
||||
|
||||
void StoreLandObject(ILandObject Parcel);
|
||||
|
@ -136,4 +145,5 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
|
||||
void Shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,13 +25,23 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Framework.Interfaces
|
||||
{
|
||||
public interface ITerrainChannel
|
||||
{
|
||||
int Height { get; }
|
||||
int Width { get;} // X dimension
|
||||
int Height { get;} // Y dimension
|
||||
int Altitude { get;} // Z dimension
|
||||
|
||||
double this[int x, int y] { get; set; }
|
||||
int Width { get; }
|
||||
|
||||
float GetHeightAtXYZ(float x, float y, float z);
|
||||
|
||||
// Return the packaged terrain data for passing into lower levels of communication
|
||||
TerrainData GetTerrainData();
|
||||
|
||||
/// <summary>
|
||||
/// Squash the entire heightmap into a single dimensioned array
|
||||
|
@ -40,9 +50,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
float[] GetFloatsSerialised();
|
||||
|
||||
double[,] GetDoubles();
|
||||
|
||||
// Check if a location has been updated. Clears the taint flag as a side effect.
|
||||
bool Tainted(int x, int y);
|
||||
|
||||
ITerrainChannel MakeCopy();
|
||||
string SaveToXmlString();
|
||||
void LoadFromXmlString(string data);
|
||||
// Merge some terrain into this channel
|
||||
void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2221,14 +2221,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
itemID = UUID.Zero;
|
||||
if (grp != null)
|
||||
{
|
||||
Vector3 inventoryStoredPosition = new Vector3
|
||||
(((grp.AbsolutePosition.X > (int)Constants.RegionSize)
|
||||
? 250
|
||||
: grp.AbsolutePosition.X)
|
||||
,
|
||||
(grp.AbsolutePosition.X > (int)Constants.RegionSize)
|
||||
? 250
|
||||
: grp.AbsolutePosition.X,
|
||||
Vector3 inventoryStoredPosition = new Vector3(
|
||||
Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
|
||||
Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
|
||||
grp.AbsolutePosition.Z);
|
||||
|
||||
Vector3 originalPosition = grp.AbsolutePosition;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
|
@ -103,7 +103,29 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <summary>
|
||||
/// If false then physical objects are disabled, though collisions will continue as normal.
|
||||
/// </summary>
|
||||
public bool PhysicsEnabled { get; set; }
|
||||
public bool PhysicsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_physicsEnabled;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
m_physicsEnabled = value;
|
||||
|
||||
if (PhysicsScene != null)
|
||||
{
|
||||
IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters;
|
||||
|
||||
if (physScene != null)
|
||||
physScene.SetPhysicsParameter(
|
||||
"Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_physicsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// If false then scripts are not enabled on the smiulator
|
||||
|
@ -160,11 +182,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public SimStatsReporter StatsReporter { get; private set; }
|
||||
|
||||
public List<Border> NorthBorders = new List<Border>();
|
||||
public List<Border> EastBorders = new List<Border>();
|
||||
public List<Border> SouthBorders = new List<Border>();
|
||||
public List<Border> WestBorders = new List<Border>();
|
||||
|
||||
/// <summary>
|
||||
/// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
|
||||
/// PhysicsScene in order to perform collision detection
|
||||
|
@ -204,15 +221,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public int m_linksetCapacity = 0;
|
||||
|
||||
public bool m_clampPrimSize;
|
||||
public bool m_trustBinaries;
|
||||
public bool m_allowScriptCrossings = true;
|
||||
|
||||
/// <summary>
|
||||
/// Max prims an Physical object will hold
|
||||
/// </summary>
|
||||
///
|
||||
public int m_linksetPhysCapacity = 0;
|
||||
|
||||
public bool m_clampPrimSize;
|
||||
public bool m_trustBinaries;
|
||||
public bool m_allowScriptCrossings;
|
||||
public bool m_useFlySlow;
|
||||
public bool m_useTrashOnDelete = true;
|
||||
|
||||
|
@ -364,7 +382,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// TODO: Possibly stop other classes being able to manipulate this directly.
|
||||
private SceneGraph m_sceneGraph;
|
||||
private volatile int m_bordersLocked;
|
||||
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
|
||||
private volatile bool m_backingup;
|
||||
private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
|
||||
|
@ -446,18 +463,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
set { m_splitRegionID = value; }
|
||||
}
|
||||
|
||||
public bool BordersLocked
|
||||
{
|
||||
get { return m_bordersLocked == 1; }
|
||||
set
|
||||
{
|
||||
if (value == true)
|
||||
m_bordersLocked = 1;
|
||||
else
|
||||
m_bordersLocked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public new float TimeDilation
|
||||
{
|
||||
get { return m_sceneGraph.PhysicsScene.TimeDilation; }
|
||||
|
@ -1075,28 +1080,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
PeriodicBackup = true;
|
||||
UseBackup = true;
|
||||
|
||||
BordersLocked = true;
|
||||
Border northBorder = new Border();
|
||||
northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<---
|
||||
northBorder.CrossDirection = Cardinals.N;
|
||||
NorthBorders.Add(northBorder);
|
||||
|
||||
Border southBorder = new Border();
|
||||
southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
|
||||
southBorder.CrossDirection = Cardinals.S;
|
||||
SouthBorders.Add(southBorder);
|
||||
|
||||
Border eastBorder = new Border();
|
||||
eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<---
|
||||
eastBorder.CrossDirection = Cardinals.E;
|
||||
EastBorders.Add(eastBorder);
|
||||
|
||||
Border westBorder = new Border();
|
||||
westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
|
||||
westBorder.CrossDirection = Cardinals.W;
|
||||
WestBorders.Add(westBorder);
|
||||
BordersLocked = false;
|
||||
|
||||
m_eventManager = new EventManager();
|
||||
|
||||
m_permissions = new ScenePermissions(this);
|
||||
|
@ -1975,7 +1958,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
|
||||
|
@ -1986,7 +1969,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
|
||||
|
||||
m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
|
||||
Heightmap = new TerrainChannel(m_InitialTerrain);
|
||||
Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
|
||||
|
||||
SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
|
||||
}
|
||||
|
@ -2611,185 +2594,35 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
EntityTransferModule.Cross(grp, attemptedPosition, silent);
|
||||
}
|
||||
|
||||
public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
|
||||
// Simple test to see if a position is in the current region.
|
||||
// This test is mostly used to see if a region crossing is necessary.
|
||||
// Assuming the position is relative to the region so anything outside its bounds.
|
||||
// Return 'true' if position inside region.
|
||||
public bool PositionIsInCurrentRegion(Vector3 pos)
|
||||
{
|
||||
if (BordersLocked)
|
||||
bool ret = false;
|
||||
int xx = (int)Math.Floor(pos.X);
|
||||
int yy = (int)Math.Floor(pos.Y);
|
||||
if (xx < 0 || yy < 0)
|
||||
return false;
|
||||
|
||||
IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>();
|
||||
if (regionCombinerModule == null)
|
||||
{
|
||||
switch (gridline)
|
||||
{
|
||||
case Cardinals.N:
|
||||
lock (NorthBorders)
|
||||
{
|
||||
foreach (Border b in NorthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Cardinals.S:
|
||||
lock (SouthBorders)
|
||||
{
|
||||
foreach (Border b in SouthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Cardinals.E:
|
||||
lock (EastBorders)
|
||||
{
|
||||
foreach (Border b in EastBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Cardinals.W:
|
||||
|
||||
lock (WestBorders)
|
||||
{
|
||||
foreach (Border b in WestBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
// Regular region. Just check for region size
|
||||
if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gridline)
|
||||
{
|
||||
case Cardinals.N:
|
||||
foreach (Border b in NorthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
|
||||
break;
|
||||
case Cardinals.S:
|
||||
foreach (Border b in SouthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
break;
|
||||
case Cardinals.E:
|
||||
foreach (Border b in EastBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
|
||||
break;
|
||||
case Cardinals.W:
|
||||
foreach (Border b in WestBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return b;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
// We're in a mega-region so see if we are still in that larger region
|
||||
ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
|
||||
}
|
||||
|
||||
return null;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
public bool TestBorderCross(Vector3 position, Cardinals border)
|
||||
{
|
||||
if (BordersLocked)
|
||||
{
|
||||
switch (border)
|
||||
{
|
||||
case Cardinals.N:
|
||||
lock (NorthBorders)
|
||||
{
|
||||
foreach (Border b in NorthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Cardinals.E:
|
||||
lock (EastBorders)
|
||||
{
|
||||
foreach (Border b in EastBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Cardinals.S:
|
||||
lock (SouthBorders)
|
||||
{
|
||||
foreach (Border b in SouthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Cardinals.W:
|
||||
lock (WestBorders)
|
||||
{
|
||||
foreach (Border b in WestBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (border)
|
||||
{
|
||||
case Cardinals.N:
|
||||
foreach (Border b in NorthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Cardinals.E:
|
||||
foreach (Border b in EastBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Cardinals.S:
|
||||
foreach (Border b in SouthBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Cardinals.W:
|
||||
foreach (Border b in WestBorders)
|
||||
{
|
||||
if (b.TestCross(position))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when objects or attachments cross the border, or teleport, between regions.
|
||||
/// </summary>
|
||||
|
@ -4116,60 +3949,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
// CleanDroppedAttachments();
|
||||
|
||||
if (TestBorderCross(acd.startpos, Cardinals.E))
|
||||
{
|
||||
Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
|
||||
acd.startpos.X = crossedBorder.BorderLine.Z - 1;
|
||||
}
|
||||
|
||||
if (TestBorderCross(acd.startpos, Cardinals.N))
|
||||
{
|
||||
Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
|
||||
acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
|
||||
}
|
||||
|
||||
//Mitigate http://opensimulator.org/mantis/view.php?id=3522
|
||||
// Check if start position is outside of region
|
||||
// If it is, check the Z start position also.. if not, leave it alone.
|
||||
if (BordersLocked)
|
||||
{
|
||||
lock (EastBorders)
|
||||
{
|
||||
if (acd.startpos.X > EastBorders[0].BorderLine.Z)
|
||||
{
|
||||
m_log.Warn("FIX AGENT POSITION");
|
||||
acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
|
||||
if (acd.startpos.Z > 720)
|
||||
acd.startpos.Z = 720;
|
||||
}
|
||||
}
|
||||
lock (NorthBorders)
|
||||
{
|
||||
if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
|
||||
{
|
||||
m_log.Warn("FIX Agent POSITION");
|
||||
acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
|
||||
if (acd.startpos.Z > 720)
|
||||
acd.startpos.Z = 720;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (acd.startpos.X > EastBorders[0].BorderLine.Z)
|
||||
{
|
||||
m_log.Warn("FIX AGENT POSITION");
|
||||
acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
|
||||
if (acd.startpos.Z > 720)
|
||||
acd.startpos.Z = 720;
|
||||
}
|
||||
if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
|
||||
{
|
||||
m_log.Warn("FIX Agent POSITION");
|
||||
acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
|
||||
if (acd.startpos.Z > 720)
|
||||
acd.startpos.Z = 720;
|
||||
}
|
||||
}
|
||||
// Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
|
||||
if (acd.startpos.X < 0) acd.startpos.X = 1f;
|
||||
if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
|
||||
if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
|
||||
if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
|
||||
|
@ -4883,44 +4667,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
|
||||
if (sp != null)
|
||||
{
|
||||
uint regionX = RegionInfo.RegionLocX;
|
||||
uint regionY = RegionInfo.RegionLocY;
|
||||
|
||||
Utils.LongToUInts(regionHandle, out regionX, out regionY);
|
||||
|
||||
int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
|
||||
int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
|
||||
|
||||
position.X += shiftx;
|
||||
position.Y += shifty;
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (TestBorderCross(position,Cardinals.N))
|
||||
result = true;
|
||||
|
||||
if (TestBorderCross(position, Cardinals.S))
|
||||
result = true;
|
||||
|
||||
if (TestBorderCross(position, Cardinals.E))
|
||||
result = true;
|
||||
|
||||
if (TestBorderCross(position, Cardinals.W))
|
||||
result = true;
|
||||
|
||||
// bordercross if position is outside of region
|
||||
|
||||
if (!result)
|
||||
{
|
||||
regionHandle = RegionInfo.RegionHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not in this region, undo the shift!
|
||||
position.X -= shiftx;
|
||||
position.Y -= shifty;
|
||||
}
|
||||
|
||||
if (EntityTransferModule != null)
|
||||
{
|
||||
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public class SceneCommunicationService //one instance per region
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[SCENE COMMUNICATION SERVICE]";
|
||||
|
||||
protected RegionInfo m_regionInfo;
|
||||
protected Scene m_scene;
|
||||
|
@ -100,7 +101,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_log.WarnFormat(
|
||||
"[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
|
||||
m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize);
|
||||
m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// we only want to send one update to each simulator; the simulator will
|
||||
// hand it off to the regions where a child agent exists, this does assume
|
||||
// that the region position is cached or performance will degrade
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
|
||||
GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
|
||||
if (dest == null)
|
||||
continue;
|
||||
|
@ -206,7 +207,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
//m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
|
||||
uint x = 0, y = 0;
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
|
||||
|
||||
GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
|
||||
|
||||
|
@ -226,6 +227,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
foreach (ulong handle in regionslst)
|
||||
{
|
||||
// We must take a copy here since handle acts like a reference when used in an iterator.
|
||||
// This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region.
|
||||
ulong handleCopy = handle;
|
||||
Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
|
||||
}
|
||||
|
|
|
@ -412,7 +412,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
get
|
||||
{
|
||||
Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
|
||||
Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
|
||||
Vector3 maxScale = Vector3.Zero;
|
||||
Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
|
||||
|
@ -529,12 +529,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
set
|
||||
{
|
||||
Vector3 val = value;
|
||||
if (Scene != null && !IsAttachmentCheckFull()
|
||||
&& !Scene.LoadingPrims &&
|
||||
(Scene.TestBorderCross(val, Cardinals.E) ||
|
||||
Scene.TestBorderCross(val, Cardinals.W) ||
|
||||
Scene.TestBorderCross(val, Cardinals.N) ||
|
||||
Scene.TestBorderCross(val, Cardinals.S))
|
||||
if (Scene != null
|
||||
&& Scene.PositionIsInCurrentRegion(val)
|
||||
&& !IsAttachmentCheckFull()
|
||||
&& !Scene.LoadingPrims
|
||||
)
|
||||
{
|
||||
if (!inTransit)
|
||||
|
|
|
@ -2979,10 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
|
||||
|
||||
if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
|
||||
|| ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
|
||||
|| ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
|
||||
|| ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
|
||||
if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
|
||||
{
|
||||
ParentGroup.AbsolutePosition = newpos;
|
||||
return;
|
||||
|
|
|
@ -842,9 +842,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
foreach (ulong handle in seeds.Keys)
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(handle, out x, out y);
|
||||
x = x / Constants.RegionSize;
|
||||
y = y / Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(handle, out x, out y);
|
||||
|
||||
if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
|
||||
{
|
||||
old.Add(handle);
|
||||
|
@ -866,9 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(kvp.Key, out x, out y);
|
||||
x = x / Constants.RegionSize;
|
||||
y = y / Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
|
||||
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
|
||||
}
|
||||
}
|
||||
|
@ -1170,18 +1167,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
if (ParentID == 0)
|
||||
{
|
||||
if (m_scene.TestBorderCross(pos, Cardinals.E))
|
||||
{
|
||||
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
|
||||
pos.X = crossedBorder.BorderLine.Z - 1;
|
||||
}
|
||||
|
||||
if (m_scene.TestBorderCross(pos, Cardinals.N))
|
||||
{
|
||||
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
|
||||
pos.Y = crossedBorder.BorderLine.Z - 1;
|
||||
}
|
||||
|
||||
CheckAndAdjustLandingPoint(ref pos);
|
||||
|
||||
if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
|
||||
|
@ -1201,7 +1186,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
float posZLimit = 0;
|
||||
|
||||
if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
|
||||
if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
|
||||
posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
|
||||
|
||||
float newPosZ = posZLimit + localAVHeight / 2;
|
||||
|
@ -2612,7 +2597,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (regionCombinerModule != null)
|
||||
regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
|
||||
else
|
||||
regionSize = new Vector2(Constants.RegionSize);
|
||||
regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
|
||||
|
||||
if (pos.X < 0 || pos.X >= regionSize.X
|
||||
|| pos.Y < 0 || pos.Y >= regionSize.Y
|
||||
|
@ -2630,8 +2615,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// }
|
||||
|
||||
// Get terrain height for sub-region in a megaregion if necessary
|
||||
int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
|
||||
int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
|
||||
int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
|
||||
int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
|
||||
GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
|
||||
// If X and Y is NaN, target_region will be null
|
||||
if (target_region == null)
|
||||
|
@ -2642,7 +2627,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
|
||||
targetScene = m_scene;
|
||||
|
||||
float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
|
||||
float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
|
||||
// dont try to land underground
|
||||
terrainHeight += Appearance.AvatarHeight / 2;
|
||||
pos.Z = Math.Max(terrainHeight, pos.Z);
|
||||
|
@ -3872,32 +3857,28 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
|
||||
// pos2, Name, Scene.Name);
|
||||
|
||||
if( Scene.TestBorderCross(pos2, Cardinals.E) ||
|
||||
Scene.TestBorderCross(pos2, Cardinals.W) ||
|
||||
Scene.TestBorderCross(pos2, Cardinals.N) ||
|
||||
Scene.TestBorderCross(pos2, Cardinals.S)
|
||||
)
|
||||
|
||||
if (Scene.PositionIsInCurrentRegion(pos2))
|
||||
return;
|
||||
|
||||
if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
|
||||
{
|
||||
if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
|
||||
{
|
||||
// we don't have entity transfer module
|
||||
Vector3 pos = AbsolutePosition;
|
||||
float px = pos.X;
|
||||
if (px < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (px > m_scene.RegionInfo.RegionSizeX)
|
||||
pos.X -= Velocity.X * 2;
|
||||
// we don't have entity transfer module
|
||||
Vector3 pos = AbsolutePosition;
|
||||
float px = pos.X;
|
||||
if (px < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (px > m_scene.RegionInfo.RegionSizeX)
|
||||
pos.X -= Velocity.X * 2;
|
||||
|
||||
float py = pos.Y;
|
||||
if (py < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (py > m_scene.RegionInfo.RegionSizeY)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
float py = pos.Y;
|
||||
if (py < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (py > m_scene.RegionInfo.RegionSizeY)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
}
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3962,7 +3943,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// Put the child agent back at the center
|
||||
AbsolutePosition
|
||||
= new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
|
||||
= new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
|
||||
|
||||
Animator.ResetAnimations();
|
||||
}
|
||||
|
@ -3989,9 +3970,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (handle != Scene.RegionInfo.RegionHandle)
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(handle, out x, out y);
|
||||
x = x / Constants.RegionSize;
|
||||
y = y / Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(handle, out x, out y);
|
||||
|
||||
// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
|
||||
// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
|
||||
|
|
|
@ -25,13 +25,20 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using OpenSim.Data;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
|
@ -40,140 +47,136 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public class TerrainChannel : ITerrainChannel
|
||||
{
|
||||
private readonly bool[,] taint;
|
||||
private double[,] map;
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[TERRAIN CHANNEL]";
|
||||
|
||||
protected TerrainData m_terrainData;
|
||||
|
||||
public int Width { get { return m_terrainData.SizeX; } } // X dimension
|
||||
// Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
|
||||
public int Height { get { return m_terrainData.SizeY; } } // Y dimension
|
||||
public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
|
||||
|
||||
// Default, not-often-used builder
|
||||
public TerrainChannel()
|
||||
{
|
||||
map = new double[Constants.RegionSize, Constants.RegionSize];
|
||||
taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
|
||||
|
||||
PinHeadIsland();
|
||||
m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
|
||||
FlatLand();
|
||||
// PinHeadIsland();
|
||||
}
|
||||
|
||||
public TerrainChannel(String type)
|
||||
// Create terrain of given size
|
||||
public TerrainChannel(int pX, int pY)
|
||||
{
|
||||
map = new double[Constants.RegionSize, Constants.RegionSize];
|
||||
taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
|
||||
m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
|
||||
}
|
||||
|
||||
// Create terrain of specified size and initialize with specified terrain.
|
||||
// TODO: join this with the terrain initializers.
|
||||
public TerrainChannel(String type, int pX, int pY, int pZ)
|
||||
{
|
||||
m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
|
||||
if (type.Equals("flat"))
|
||||
FlatLand();
|
||||
else
|
||||
PinHeadIsland();
|
||||
}
|
||||
|
||||
public TerrainChannel(double[,] import)
|
||||
// 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)
|
||||
{
|
||||
map = import;
|
||||
taint = new bool[import.GetLength(0),import.GetLength(1)];
|
||||
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(bool createMap)
|
||||
public TerrainChannel(TerrainData pTerrData)
|
||||
{
|
||||
if (createMap)
|
||||
{
|
||||
map = new double[Constants.RegionSize,Constants.RegionSize];
|
||||
taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16];
|
||||
}
|
||||
}
|
||||
|
||||
public TerrainChannel(int w, int h)
|
||||
{
|
||||
map = new double[w,h];
|
||||
taint = new bool[w / 16,h / 16];
|
||||
m_terrainData = pTerrData;
|
||||
}
|
||||
|
||||
#region ITerrainChannel Members
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return map.GetLength(0); }
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return map.GetLength(1); }
|
||||
}
|
||||
|
||||
// ITerrainChannel.MakeCopy()
|
||||
public ITerrainChannel MakeCopy()
|
||||
{
|
||||
TerrainChannel copy = new TerrainChannel(false);
|
||||
copy.map = (double[,]) map.Clone();
|
||||
|
||||
return copy;
|
||||
return this.Copy();
|
||||
}
|
||||
|
||||
// ITerrainChannel.GetTerrainData()
|
||||
public TerrainData GetTerrainData()
|
||||
{
|
||||
return m_terrainData;
|
||||
}
|
||||
|
||||
// ITerrainChannel.GetFloatsSerialized()
|
||||
// This one dimensional version is ordered so height = map[y*sizeX+x];
|
||||
// DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
|
||||
// and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
|
||||
public float[] GetFloatsSerialised()
|
||||
{
|
||||
// Move the member variables into local variables, calling
|
||||
// member variables 256*256 times gets expensive
|
||||
int w = Width;
|
||||
int h = Height;
|
||||
float[] heights = new float[w * h];
|
||||
return m_terrainData.GetFloatsSerialized();
|
||||
}
|
||||
|
||||
// ITerrainChannel.GetDoubles()
|
||||
public double[,] GetDoubles()
|
||||
{
|
||||
double[,] heights = new double[Width, Height];
|
||||
|
||||
int i, j; // map coordinates
|
||||
int idx = 0; // index into serialized array
|
||||
for (i = 0; i < h; i++)
|
||||
for (int ii = 0; ii < Width; ii++)
|
||||
{
|
||||
for (j = 0; j < w; j++)
|
||||
for (int jj = 0; jj < Height; jj++)
|
||||
{
|
||||
heights[idx++] = (float)map[j, i];
|
||||
heights[ii, jj] = (double)m_terrainData[ii, jj];
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return heights;
|
||||
}
|
||||
|
||||
public double[,] GetDoubles()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
// ITerrainChannel.this[x,y]
|
||||
public double this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) y = 0;
|
||||
if (x >= (int)Constants.RegionSize) x = (int)Constants.RegionSize - 1;
|
||||
if (y >= (int)Constants.RegionSize) y = (int)Constants.RegionSize - 1;
|
||||
|
||||
return map[x, y];
|
||||
get {
|
||||
if (x < 0 || x >= Width || y < 0 || y >= Height)
|
||||
return 0;
|
||||
return (double)m_terrainData[x, y];
|
||||
}
|
||||
set
|
||||
{
|
||||
// Will "fix" terrain hole problems. Although not fantastically.
|
||||
if (Double.IsNaN(value) || Double.IsInfinity(value))
|
||||
return;
|
||||
|
||||
if (map[x, y] != value)
|
||||
{
|
||||
taint[x / 16, y / 16] = true;
|
||||
map[x, y] = value;
|
||||
}
|
||||
m_terrainData[x, y] = (float)value;
|
||||
}
|
||||
}
|
||||
|
||||
// ITerrainChannel.GetHieghtAtXYZ(x, y, z)
|
||||
public float GetHeightAtXYZ(float x, float y, float z)
|
||||
{
|
||||
if (x < 0 || x >= Width || y < 0 || y >= Height)
|
||||
return 0;
|
||||
return m_terrainData[(int)x, (int)y];
|
||||
}
|
||||
|
||||
// ITerrainChannel.Tainted()
|
||||
public bool Tainted(int x, int y)
|
||||
{
|
||||
if (taint[x / 16, y / 16])
|
||||
{
|
||||
taint[x / 16, y / 16] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public TerrainChannel Copy()
|
||||
{
|
||||
TerrainChannel copy = new TerrainChannel(false);
|
||||
copy.map = (double[,]) map.Clone();
|
||||
|
||||
return copy;
|
||||
return m_terrainData.IsTaintedAt(x, y);
|
||||
}
|
||||
|
||||
// ITerrainChannel.SaveToXmlString()
|
||||
public string SaveToXmlString()
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings();
|
||||
|
@ -189,13 +192,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
private void WriteXml(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
|
||||
ToXml(writer);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
// ITerrainChannel.LoadFromXmlString()
|
||||
public void LoadFromXmlString(string data)
|
||||
{
|
||||
StringReader sr = new StringReader(data);
|
||||
|
@ -207,12 +204,124 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
sr.Close();
|
||||
}
|
||||
|
||||
private void ReadXml(XmlReader reader)
|
||||
// ITerrainChannel.Merge
|
||||
public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
|
||||
{
|
||||
reader.ReadStartElement("TerrainMap");
|
||||
FromXml(reader);
|
||||
m_log.DebugFormat("{0} Merge. inSize=<{1},{2}>, disp={3}, rot={4}, rotDisp={5}, outSize=<{6},{7}>", LogHeader,
|
||||
newTerrain.Width, newTerrain.Height,
|
||||
displacement, radianRotation, rotationDisplacement,
|
||||
m_terrainData.SizeX, m_terrainData.SizeY);
|
||||
for (int xx = 0; xx < newTerrain.Width; xx++)
|
||||
{
|
||||
for (int yy = 0; yy < newTerrain.Height; yy++)
|
||||
{
|
||||
int dispX = (int)displacement.X;
|
||||
int dispY = (int)displacement.Y;
|
||||
float newHeight = (float)newTerrain[xx, yy] + displacement.Z;
|
||||
if (radianRotation == 0)
|
||||
{
|
||||
// If no rotation, place the new height in the specified location
|
||||
dispX += xx;
|
||||
dispY += yy;
|
||||
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
|
||||
{
|
||||
m_terrainData[dispX, dispY] = newHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If rotating, we have to smooth the result because the conversion
|
||||
// to ints will mean heightmap entries will not get changed
|
||||
// First compute the rotation location for the new height.
|
||||
dispX += (int)(rotationDisplacement.X
|
||||
+ ((float)xx - rotationDisplacement.X) * Math.Cos(radianRotation)
|
||||
- ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) );
|
||||
|
||||
dispY += (int)(rotationDisplacement.Y
|
||||
+ ((float)xx - rotationDisplacement.X) * Math.Sin(radianRotation)
|
||||
+ ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) );
|
||||
|
||||
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
|
||||
{
|
||||
float oldHeight = m_terrainData[dispX, dispY];
|
||||
// Smooth the heights around this location if the old height is far from this one
|
||||
for (int sxx = dispX - 2; sxx < dispX + 2; sxx++)
|
||||
{
|
||||
for (int syy = dispY - 2; syy < dispY + 2; syy++)
|
||||
{
|
||||
if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY)
|
||||
{
|
||||
if (sxx == dispX && syy == dispY)
|
||||
{
|
||||
// Set height for the exact rotated point
|
||||
m_terrainData[dispX, dispY] = newHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f)
|
||||
{
|
||||
// If the adjacent height is far off, force it to this height
|
||||
m_terrainData[sxx, syy] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
|
||||
{
|
||||
m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public TerrainChannel Copy()
|
||||
{
|
||||
TerrainChannel copy = new TerrainChannel();
|
||||
copy.m_terrainData = m_terrainData.Clone();
|
||||
return copy;
|
||||
}
|
||||
|
||||
private void WriteXml(XmlWriter writer)
|
||||
{
|
||||
if (Width == Constants.RegionSize && Height == Constants.RegionSize)
|
||||
{
|
||||
// Downward compatibility for legacy region terrain maps.
|
||||
// If region is exactly legacy size, return the old format XML.
|
||||
writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
|
||||
ToXml(writer);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
// New format XML that includes width and length.
|
||||
writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
|
||||
ToXml2(writer);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadXml(XmlReader reader)
|
||||
{
|
||||
// Check the first element. If legacy element, use the legacy reader.
|
||||
if (reader.IsStartElement("TerrainMap"))
|
||||
{
|
||||
reader.ReadStartElement("TerrainMap");
|
||||
FromXml(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.ReadStartElement("TerrainMap2");
|
||||
FromXml2(reader);
|
||||
}
|
||||
}
|
||||
|
||||
// Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
|
||||
private void ToXml(XmlWriter xmlWriter)
|
||||
{
|
||||
float[] mapData = GetFloatsSerialised();
|
||||
|
@ -226,12 +335,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
serializer.Serialize(xmlWriter, buffer);
|
||||
}
|
||||
|
||||
// Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
|
||||
private void FromXml(XmlReader xmlReader)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
|
||||
byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
|
||||
int index = 0;
|
||||
|
||||
m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
|
||||
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for (int x = 0; x < Width; x++)
|
||||
|
@ -244,35 +356,63 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
private class TerrainChannelXMLPackage
|
||||
{
|
||||
public int Version;
|
||||
public int SizeX;
|
||||
public int SizeY;
|
||||
public int SizeZ;
|
||||
public float CompressionFactor;
|
||||
public int[] Map;
|
||||
public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap)
|
||||
{
|
||||
Version = 1;
|
||||
SizeX = pX;
|
||||
SizeY = pY;
|
||||
SizeZ = pZ;
|
||||
CompressionFactor = pCompressionFactor;
|
||||
Map = pMap;
|
||||
}
|
||||
}
|
||||
|
||||
// New terrain serialization format that includes the width and length.
|
||||
private void ToXml2(XmlWriter xmlWriter)
|
||||
{
|
||||
TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
|
||||
m_terrainData.GetCompressedMap());
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
|
||||
serializer.Serialize(xmlWriter, package);
|
||||
}
|
||||
|
||||
// New terrain serialization format that includes the width and length.
|
||||
private void FromXml2(XmlReader xmlReader)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
|
||||
TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
|
||||
m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
|
||||
}
|
||||
|
||||
// Fill the heightmap with the center bump terrain
|
||||
private void PinHeadIsland()
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < Constants.RegionSize; x++)
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
int y;
|
||||
for (y = 0; y < Constants.RegionSize; y++)
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
|
||||
double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01;
|
||||
double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001;
|
||||
if (map[x, y] < spherFacA)
|
||||
map[x, y] = spherFacA;
|
||||
if (map[x, y] < spherFacB)
|
||||
map[x, y] = spherFacB;
|
||||
m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
|
||||
float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
|
||||
float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
|
||||
if (m_terrainData[x, y]< spherFacA)
|
||||
m_terrainData[x, y]= spherFacA;
|
||||
if (m_terrainData[x, y]< spherFacB)
|
||||
m_terrainData[x, y] = spherFacB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FlatLand()
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < Constants.RegionSize; x++)
|
||||
{
|
||||
int y;
|
||||
for (y = 0; y < Constants.RegionSize; y++)
|
||||
map[x, y] = 21;
|
||||
}
|
||||
m_terrainData.ClearLand();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,948 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Freely adapted from the Aurora version of the terrain compressor.
|
||||
* Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using log4net;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
public static class OpenSimTerrainCompressor
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
#pragma warning disable 414
|
||||
private static string LogHeader = "[TERRAIN COMPRESSOR]";
|
||||
#pragma warning restore 414
|
||||
|
||||
public const int END_OF_PATCHES = 97;
|
||||
|
||||
private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
|
||||
private const int STRIDE = 264;
|
||||
|
||||
private const int ZERO_CODE = 0x0;
|
||||
private const int ZERO_EOB = 0x2;
|
||||
private const int POSITIVE_VALUE = 0x6;
|
||||
private const int NEGATIVE_VALUE = 0x7;
|
||||
|
||||
private static readonly float[] DequantizeTable16 =
|
||||
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
private static readonly float[] DequantizeTable32 =
|
||||
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
//private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
|
||||
private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
private static readonly float[] QuantizeTable16 =
|
||||
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
static OpenSimTerrainCompressor()
|
||||
{
|
||||
// Initialize the decompression tables
|
||||
BuildDequantizeTable16();
|
||||
SetupCosines16();
|
||||
BuildCopyMatrix16();
|
||||
BuildQuantizeTable16();
|
||||
}
|
||||
|
||||
// Used to send cloud and wind patches
|
||||
public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX,
|
||||
int pRegionSizeY)
|
||||
{
|
||||
LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
|
||||
|
||||
TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
|
||||
{Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
|
||||
|
||||
// Should be enough to fit even the most poorly packed data
|
||||
byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2];
|
||||
BitPack bitpack = new BitPack(data, 0);
|
||||
bitpack.PackBits(header.Stride, 16);
|
||||
bitpack.PackBits(header.PatchSize, 8);
|
||||
bitpack.PackBits(type, 8);
|
||||
|
||||
foreach (TerrainPatch t in patches)
|
||||
CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY);
|
||||
|
||||
bitpack.PackBits(END_OF_PATCHES, 8);
|
||||
|
||||
layer.LayerData.Data = new byte[bitpack.BytePos + 1];
|
||||
Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
// Create a land packet for a single patch.
|
||||
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
|
||||
{
|
||||
int[] xPieces = new int[1];
|
||||
int[] yPieces = new int[1];
|
||||
xPieces[0] = patchX; // patch X dimension
|
||||
yPieces[0] = patchY;
|
||||
|
||||
return CreateLandPacket(terrData, xPieces, yPieces);
|
||||
}
|
||||
|
||||
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces)
|
||||
{
|
||||
byte landPacketType = (byte)TerrainPatch.LayerType.Land;
|
||||
if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
|
||||
{
|
||||
landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
|
||||
}
|
||||
|
||||
return CreateLandPacket(terrData, xPieces, yPieces, landPacketType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LayerData packet for compressed land data given a full
|
||||
/// simulator heightmap and an array of indices of patches to compress
|
||||
/// </summary>
|
||||
/// <param name="terrData">
|
||||
/// Terrain data that can result in a meter square heightmap.
|
||||
/// </param>
|
||||
/// <param name="x">
|
||||
/// Array of indexes in the grid of patches
|
||||
/// for this simulator.
|
||||
/// If creating a packet for multiple patches, there will be entries in
|
||||
/// both the X and Y arrays for each of the patches.
|
||||
/// For example if patches 1 and 17 are to be sent,
|
||||
/// x[] = {1,1} and y[] = {0,1} which specifies the patches at
|
||||
/// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
|
||||
/// </param>
|
||||
/// <param name="y">
|
||||
/// Array of indexes in the grid of patches.
|
||||
/// </param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
|
||||
{
|
||||
LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
|
||||
|
||||
TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
|
||||
{Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
|
||||
|
||||
byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
|
||||
BitPack bitpack = new BitPack(data, 0);
|
||||
bitpack.PackBits(header.Stride, 16);
|
||||
bitpack.PackBits(header.PatchSize, 8);
|
||||
bitpack.PackBits(type, 8);
|
||||
|
||||
for (int i = 0; i < x.Length; i++)
|
||||
CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
|
||||
|
||||
bitpack.PackBits(END_OF_PATCHES, 8);
|
||||
|
||||
layer.LayerData.Data = new byte[bitpack.BytePos + 1];
|
||||
Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
// Unused: left for historical reference.
|
||||
public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
|
||||
{
|
||||
TerrainPatch.Header header = PrescanPatch(patchData);
|
||||
header.QuantWBits = 136;
|
||||
if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
|
||||
{
|
||||
header.PatchIDs = (y & 0xFFFF);
|
||||
header.PatchIDs += (x << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
header.PatchIDs = (y & 0x1F);
|
||||
header.PatchIDs += (x << 5);
|
||||
}
|
||||
|
||||
// NOTE: No idea what prequant and postquant should be or what they do
|
||||
|
||||
int wbits;
|
||||
int[] patch = CompressPatch(patchData, header, 10, out wbits);
|
||||
wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits);
|
||||
EncodePatch(output, patch, 0, wbits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a patch of terrain to a BitPacker
|
||||
/// </summary>
|
||||
/// <param name="output">BitPacker to write the patch to</param>
|
||||
/// <param name="heightmap">
|
||||
/// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
|
||||
/// </param>
|
||||
/// <param name="patchX">
|
||||
/// X offset of the patch to create.
|
||||
/// </param>
|
||||
/// <param name="patchY">
|
||||
/// Y offset of the patch to create.
|
||||
/// </param>
|
||||
/// <param name="pRegionSizeX"></param>
|
||||
/// <param name="pRegionSizeY"></param>
|
||||
public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
|
||||
{
|
||||
TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
|
||||
header.QuantWBits = 136;
|
||||
|
||||
// If larger than legacy region size, pack patch X and Y info differently.
|
||||
if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
|
||||
{
|
||||
header.PatchIDs = (patchY & 0xFFFF);
|
||||
header.PatchIDs += (patchX << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
header.PatchIDs = (patchY & 0x1F);
|
||||
header.PatchIDs += (patchX << 5);
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}",
|
||||
// LogHeader, patchX, patchY, header.DCOffset, header.Range);
|
||||
|
||||
// NOTE: No idea what prequant and postquant should be or what they do
|
||||
int wbits;
|
||||
int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
|
||||
wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
|
||||
EncodePatch(output, patch, 0, wbits);
|
||||
}
|
||||
|
||||
private static TerrainPatch.Header PrescanPatch(float[] patch)
|
||||
{
|
||||
TerrainPatch.Header header = new TerrainPatch.Header();
|
||||
float zmax = -99999999.0f;
|
||||
float zmin = 99999999.0f;
|
||||
|
||||
for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
|
||||
{
|
||||
float val = patch[i];
|
||||
if (val > zmax) zmax = val;
|
||||
if (val < zmin) zmin = val;
|
||||
}
|
||||
|
||||
header.DCOffset = zmin;
|
||||
header.Range = (int) ((zmax - zmin) + 1.0f);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// Scan the height info we're returning and return a patch packet header for this patch.
|
||||
private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
|
||||
{
|
||||
TerrainPatch.Header header = new TerrainPatch.Header();
|
||||
float zmax = -99999999.0f;
|
||||
float zmin = 99999999.0f;
|
||||
|
||||
for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
|
||||
{
|
||||
for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
|
||||
{
|
||||
float val = terrData[i, j];
|
||||
if (val > zmax) zmax = val;
|
||||
if (val < zmin) zmin = val;
|
||||
}
|
||||
}
|
||||
|
||||
header.DCOffset = zmin;
|
||||
header.Range = (int)((zmax - zmin) + 1.0f);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
|
||||
{
|
||||
TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
|
||||
|
||||
// Quantized word bits
|
||||
if (header.QuantWBits == END_OF_PATCHES)
|
||||
return header;
|
||||
|
||||
// DC offset
|
||||
header.DCOffset = bitpack.UnpackFloat();
|
||||
|
||||
// Range
|
||||
header.Range = bitpack.UnpackBits(16);
|
||||
|
||||
// Patch IDs (10 bits)
|
||||
header.PatchIDs = bitpack.UnpackBits(10);
|
||||
|
||||
// Word bits
|
||||
header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX,
|
||||
uint pRegionSizeY, int wbits)
|
||||
{
|
||||
/*
|
||||
int temp;
|
||||
int wbits = (header.QuantWBits & 0x0f) + 2;
|
||||
uint maxWbits = (uint)wbits + 5;
|
||||
uint minWbits = ((uint)wbits >> 1);
|
||||
int wbitsMaxValue;
|
||||
*/
|
||||
// goal is to determ minimum number of bits to use so all data fits
|
||||
/*
|
||||
wbits = (int)minWbits;
|
||||
wbitsMaxValue = (1 << wbits);
|
||||
|
||||
for (int i = 0; i < patch.Length; i++)
|
||||
{
|
||||
temp = patch[i];
|
||||
if (temp != 0)
|
||||
{
|
||||
// Get the absolute value
|
||||
if (temp < 0) temp *= -1;
|
||||
|
||||
no coments..
|
||||
|
||||
for (int j = (int)maxWbits; j > (int)minWbits; j--)
|
||||
{
|
||||
if ((temp & (1 << j)) != 0)
|
||||
{
|
||||
if (j > wbits) wbits = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (temp > wbitsMaxValue)
|
||||
{
|
||||
wbits++;
|
||||
if (wbits == maxWbits)
|
||||
goto Done;
|
||||
wbitsMaxValue = 1 << wbits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Done:
|
||||
|
||||
// wbits += 1;
|
||||
*/
|
||||
// better check
|
||||
if (wbits > 17)
|
||||
wbits = 16;
|
||||
else if (wbits < 3)
|
||||
wbits = 3;
|
||||
|
||||
header.QuantWBits &= 0xf0;
|
||||
|
||||
header.QuantWBits |= (wbits - 2);
|
||||
|
||||
output.PackBits(header.QuantWBits, 8);
|
||||
output.PackFloat(header.DCOffset);
|
||||
output.PackBits(header.Range, 16);
|
||||
if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
|
||||
output.PackBits(header.PatchIDs, 32);
|
||||
else
|
||||
output.PackBits(header.PatchIDs, 10);
|
||||
|
||||
return wbits;
|
||||
}
|
||||
|
||||
private static void IDCTColumn16(float[] linein, float[] lineout, int column)
|
||||
{
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
float total = OO_SQRT2*linein[column];
|
||||
|
||||
for (int u = 1; u < Constants.TerrainPatchSize; u++)
|
||||
{
|
||||
int usize = u*Constants.TerrainPatchSize;
|
||||
total += linein[usize + column]*CosineTable16[usize + n];
|
||||
}
|
||||
|
||||
lineout[Constants.TerrainPatchSize*n + column] = total;
|
||||
}
|
||||
}
|
||||
|
||||
private static void IDCTLine16(float[] linein, float[] lineout, int line)
|
||||
{
|
||||
const float oosob = 2.0f/Constants.TerrainPatchSize;
|
||||
int lineSize = line*Constants.TerrainPatchSize;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
float total = OO_SQRT2*linein[lineSize];
|
||||
|
||||
for (int u = 1; u < Constants.TerrainPatchSize; u++)
|
||||
{
|
||||
total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n];
|
||||
}
|
||||
|
||||
lineout[lineSize + n] = total*oosob;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private static void DCTLine16(float[] linein, float[] lineout, int line)
|
||||
{
|
||||
float total = 0.0f;
|
||||
int lineSize = line * Constants.TerrainPatchSize;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[lineSize + n];
|
||||
}
|
||||
|
||||
lineout[lineSize] = OO_SQRT2 * total;
|
||||
|
||||
int uptr = 0;
|
||||
for (int u = 1; u < Constants.TerrainPatchSize; u++)
|
||||
{
|
||||
total = 0.0f;
|
||||
uptr += Constants.TerrainPatchSize;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[lineSize + n] * CosineTable16[uptr + n];
|
||||
}
|
||||
|
||||
lineout[lineSize + u] = total;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private static void DCTLine16(float[] linein, float[] lineout, int line)
|
||||
{
|
||||
// outputs transpose data (lines exchanged with coluns )
|
||||
// so to save a bit of cpu when doing coluns
|
||||
float total = 0.0f;
|
||||
int lineSize = line*Constants.TerrainPatchSize;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[lineSize + n];
|
||||
}
|
||||
|
||||
lineout[line] = OO_SQRT2*total;
|
||||
|
||||
for (int u = Constants.TerrainPatchSize;
|
||||
u < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
|
||||
u += Constants.TerrainPatchSize)
|
||||
{
|
||||
total = 0.0f;
|
||||
for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
|
||||
{
|
||||
total += linein[ptrn]*CosineTable16[ptru];
|
||||
}
|
||||
|
||||
lineout[line + u] = total;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private static void DCTColumn16(float[] linein, int[] lineout, int column)
|
||||
{
|
||||
float total = 0.0f;
|
||||
// const float oosob = 2.0f / Constants.TerrainPatchSize;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[Constants.TerrainPatchSize * n + column];
|
||||
}
|
||||
|
||||
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
|
||||
lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
|
||||
|
||||
for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize)
|
||||
{
|
||||
total = 0.0f;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
|
||||
}
|
||||
|
||||
// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
|
||||
lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DCTColumn16(float[] linein, int[] lineout, int column)
|
||||
{
|
||||
// input columns are in fact stored in lines now
|
||||
|
||||
float total = 0.0f;
|
||||
// const float oosob = 2.0f / Constants.TerrainPatchSize;
|
||||
int inlinesptr = Constants.TerrainPatchSize*column;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[inlinesptr + n];
|
||||
}
|
||||
|
||||
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
|
||||
lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
|
||||
|
||||
for (int uptr = Constants.TerrainPatchSize;
|
||||
uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
|
||||
uptr += Constants.TerrainPatchSize)
|
||||
{
|
||||
total = 0.0f;
|
||||
|
||||
for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
|
||||
{
|
||||
total += linein[n]*CosineTable16[ptru];
|
||||
}
|
||||
|
||||
// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
|
||||
lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits)
|
||||
{
|
||||
// input columns are in fact stored in lines now
|
||||
|
||||
bool dowbits = wbits != maxwbits;
|
||||
int wbitsMaxValue = 1 << wbits;
|
||||
|
||||
float total = 0.0f;
|
||||
// const float oosob = 2.0f / Constants.TerrainPatchSize;
|
||||
int inlinesptr = Constants.TerrainPatchSize*column;
|
||||
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
total += linein[inlinesptr + n];
|
||||
}
|
||||
|
||||
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
|
||||
int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
|
||||
lineout[CopyMatrix16[column]] = tmp;
|
||||
|
||||
if (dowbits)
|
||||
{
|
||||
if (tmp < 0) tmp *= -1;
|
||||
while (tmp > wbitsMaxValue)
|
||||
{
|
||||
wbits++;
|
||||
wbitsMaxValue = 1 << wbits;
|
||||
if (wbits == maxwbits)
|
||||
{
|
||||
dowbits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int uptr = Constants.TerrainPatchSize;
|
||||
uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
|
||||
uptr += Constants.TerrainPatchSize)
|
||||
{
|
||||
total = 0.0f;
|
||||
|
||||
for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
|
||||
{
|
||||
total += linein[n]*CosineTable16[ptru];
|
||||
}
|
||||
|
||||
tmp = (int) (total*QuantizeTable16[uptr + column]);
|
||||
lineout[CopyMatrix16[uptr + column]] = tmp;
|
||||
|
||||
if (dowbits)
|
||||
{
|
||||
if (tmp < 0) tmp *= -1;
|
||||
while (tmp > wbitsMaxValue)
|
||||
{
|
||||
wbits++;
|
||||
wbitsMaxValue = 1 << wbits;
|
||||
if (wbits == maxwbits)
|
||||
{
|
||||
dowbits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wbits;
|
||||
}
|
||||
|
||||
public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
|
||||
{
|
||||
for (int n = 0; n < size*size; n++)
|
||||
{
|
||||
// ?
|
||||
int temp = bitpack.UnpackBits(1);
|
||||
if (temp != 0)
|
||||
{
|
||||
// Value or EOB
|
||||
temp = bitpack.UnpackBits(1);
|
||||
if (temp != 0)
|
||||
{
|
||||
// Value
|
||||
temp = bitpack.UnpackBits(1);
|
||||
if (temp != 0)
|
||||
{
|
||||
// Negative
|
||||
temp = bitpack.UnpackBits((int) header.WordBits);
|
||||
patches[n] = temp*-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Positive
|
||||
temp = bitpack.UnpackBits((int) header.WordBits);
|
||||
patches[n] = temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the rest to zero
|
||||
// TODO: This might not be necessary
|
||||
for (int o = n; o < size*size; o++)
|
||||
{
|
||||
patches[o] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
patches[n] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
|
||||
{
|
||||
int maxwbitssize = (1 << wbits) - 1;
|
||||
|
||||
if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0)
|
||||
{
|
||||
Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0;
|
||||
|
||||
for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
|
||||
{
|
||||
int temp = patch[i];
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
bool eob = true;
|
||||
|
||||
for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
|
||||
{
|
||||
if (patch[j] != 0)
|
||||
{
|
||||
eob = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eob)
|
||||
{
|
||||
output.PackBits(ZERO_EOB, 2);
|
||||
return;
|
||||
}
|
||||
output.PackBits(ZERO_CODE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (temp < 0)
|
||||
{
|
||||
temp *= -1;
|
||||
|
||||
if (temp > maxwbitssize) temp = maxwbitssize;
|
||||
|
||||
output.PackBits(NEGATIVE_VALUE, 3);
|
||||
output.PackBits(temp, wbits);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (temp > maxwbitssize) temp = maxwbitssize;
|
||||
|
||||
output.PackBits(POSITIVE_VALUE, 3);
|
||||
output.PackBits(temp, wbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
|
||||
{
|
||||
float[] block = new float[group.PatchSize*group.PatchSize];
|
||||
float[] output = new float[group.PatchSize*group.PatchSize];
|
||||
int prequant = (header.QuantWBits >> 4) + 2;
|
||||
int quantize = 1 << prequant;
|
||||
float ooq = 1.0f/quantize;
|
||||
float mult = ooq*header.Range;
|
||||
float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
|
||||
|
||||
if (group.PatchSize == Constants.TerrainPatchSize)
|
||||
{
|
||||
for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
|
||||
}
|
||||
|
||||
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
IDCTColumn16(block, ftemp, o);
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
IDCTLine16(ftemp, block, o);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
|
||||
{
|
||||
block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
|
||||
}
|
||||
|
||||
Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
|
||||
}
|
||||
|
||||
for (int j = 0; j < block.Length; j++)
|
||||
{
|
||||
output[j] = block[j]*mult + addval;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
|
||||
{
|
||||
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
int wordsize = (prequant - 2) & 0x0f;
|
||||
float oozrange = 1.0f/header.Range;
|
||||
float range = (1 << prequant);
|
||||
float premult = oozrange*range;
|
||||
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
|
||||
|
||||
header.QuantWBits = wordsize;
|
||||
header.QuantWBits |= wordsize << 4;
|
||||
|
||||
int k = 0;
|
||||
for (int j = 0; j < Constants.TerrainPatchSize; j++)
|
||||
{
|
||||
for (int i = 0; i < Constants.TerrainPatchSize; i++)
|
||||
block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub;
|
||||
}
|
||||
|
||||
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
|
||||
int maxWbits = prequant + 5;
|
||||
wbits = (prequant >> 1);
|
||||
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
DCTLine16(block, ftemp, o);
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
|
||||
|
||||
return itemp;
|
||||
}
|
||||
|
||||
private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
|
||||
{
|
||||
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
float oozrange = 1.0f/header.Range;
|
||||
float range = (1 << prequant);
|
||||
float premult = oozrange*range;
|
||||
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
|
||||
int wordsize = (prequant - 2) & 0x0f;
|
||||
|
||||
header.QuantWBits = wordsize;
|
||||
header.QuantWBits |= wordsize << 4;
|
||||
|
||||
int k = 0;
|
||||
for (int j = 0; j < Constants.TerrainPatchSize; j++)
|
||||
{
|
||||
for (int i = 0; i < Constants.TerrainPatchSize; i++)
|
||||
block[k++] = patchData[j, i]*premult - sub;
|
||||
}
|
||||
|
||||
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
int maxWbits = prequant + 5;
|
||||
wbits = (prequant >> 1);
|
||||
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
DCTLine16(block, ftemp, o);
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
|
||||
|
||||
return itemp;
|
||||
}
|
||||
|
||||
private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
|
||||
int prequant, out int wbits)
|
||||
{
|
||||
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
int wordsize = prequant;
|
||||
float oozrange = 1.0f/header.Range;
|
||||
float range = (1 << prequant);
|
||||
float premult = oozrange*range;
|
||||
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
|
||||
|
||||
header.QuantWBits = wordsize - 2;
|
||||
header.QuantWBits |= (prequant - 2) << 4;
|
||||
|
||||
int k = 0;
|
||||
|
||||
int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ?
|
||||
(terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY;
|
||||
yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
|
||||
|
||||
int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ?
|
||||
(terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX;
|
||||
xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize;
|
||||
|
||||
for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++)
|
||||
{
|
||||
for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
|
||||
{
|
||||
block[k++] = terrData[xx, yy] * premult - sub;
|
||||
}
|
||||
}
|
||||
|
||||
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
|
||||
|
||||
int maxWbits = prequant + 5;
|
||||
wbits = (prequant >> 1);
|
||||
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
DCTLine16(block, ftemp, o);
|
||||
for (int o = 0; o < Constants.TerrainPatchSize; o++)
|
||||
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
|
||||
|
||||
return itemp;
|
||||
}
|
||||
|
||||
#region Initialization
|
||||
|
||||
private static void BuildDequantizeTable16()
|
||||
{
|
||||
for (int j = 0; j < Constants.TerrainPatchSize; j++)
|
||||
{
|
||||
for (int i = 0; i < Constants.TerrainPatchSize; i++)
|
||||
{
|
||||
DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildQuantizeTable16()
|
||||
{
|
||||
const float oosob = 2.0f/Constants.TerrainPatchSize;
|
||||
for (int j = 0; j < Constants.TerrainPatchSize; j++)
|
||||
{
|
||||
for (int i = 0; i < Constants.TerrainPatchSize; i++)
|
||||
{
|
||||
// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j));
|
||||
QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupCosines16()
|
||||
{
|
||||
const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize;
|
||||
|
||||
for (int u = 0; u < Constants.TerrainPatchSize; u++)
|
||||
{
|
||||
for (int n = 0; n < Constants.TerrainPatchSize; n++)
|
||||
{
|
||||
CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildCopyMatrix16()
|
||||
{
|
||||
bool diag = false;
|
||||
bool right = true;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int count = 0;
|
||||
|
||||
while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
|
||||
{
|
||||
CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
|
||||
|
||||
if (!diag)
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
if (i < Constants.TerrainPatchSize - 1) i++;
|
||||
else j++;
|
||||
|
||||
right = false;
|
||||
diag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (j < Constants.TerrainPatchSize - 1) j++;
|
||||
else i++;
|
||||
|
||||
right = true;
|
||||
diag = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
i++;
|
||||
j--;
|
||||
if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
i--;
|
||||
j++;
|
||||
if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Initialization
|
||||
}
|
||||
}
|
|
@ -520,7 +520,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
|||
|
||||
public Vector3 StartPos
|
||||
{
|
||||
get { return new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 50); }
|
||||
get { return new Vector3(m_scene.RegionInfo.RegionSizeX * 0.5f, m_scene.RegionInfo.RegionSizeY * 0.5f, 50f); }
|
||||
set { }
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
|
|||
|
||||
// Local constants
|
||||
|
||||
// This computation is not the real region center if the region is larger than 256.
|
||||
// This computation isn't fixed because there is not a handle back to the region.
|
||||
private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
|
||||
private static readonly char[] CS_SPACE = { ' ' };
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
|
|||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// This computation is not the real region center if the region is larger than 256.
|
||||
// This computation isn't fixed because there is not a handle back to the region.
|
||||
private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
|
||||
private const int DEBUG_CHANNEL = 2147483647;
|
||||
|
||||
|
|
|
@ -122,8 +122,8 @@ namespace OpenSim.Region.OptionalModules
|
|||
|
||||
private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
|
||||
{
|
||||
if (newPoint.X < -1f || newPoint.X > (float)(Constants.RegionSize + 1) ||
|
||||
newPoint.Y < -1f || newPoint.Y > (float)(Constants.RegionSize + 1))
|
||||
if (newPoint.X < -1f || newPoint.X > (scene.RegionInfo.RegionSizeX + 1) ||
|
||||
newPoint.Y < -1f || newPoint.Y > (scene.RegionInfo.RegionSizeY) )
|
||||
return true;
|
||||
|
||||
SceneObjectPart obj = scene.GetSceneObjectPart(objectID);
|
||||
|
|
|
@ -170,7 +170,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
|
|||
c.Channel = m_channelNotify;
|
||||
c.Message += numScriptsFailed.ToString() + "," + message;
|
||||
c.Type = ChatTypeEnum.Region;
|
||||
c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
|
||||
if (m_scene != null)
|
||||
c.Position = new Vector3((m_scene.RegionInfo.RegionSizeX * 0.5f), (m_scene.RegionInfo.RegionSizeY * 0.5f), 30);
|
||||
else
|
||||
c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
|
||||
c.Sender = null;
|
||||
c.SenderUUID = UUID.Zero;
|
||||
c.Scene = m_scene;
|
||||
|
|
|
@ -116,37 +116,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
|||
+ "If teleport is true then some extra teleport debug information is logged.\n"
|
||||
+ "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
|
||||
HandleDebugSceneSetCommand);
|
||||
|
||||
scene.AddCommand(
|
||||
"Regions",
|
||||
this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
|
||||
}
|
||||
|
||||
private void HandleShowBordersCommand(string module, string[] args)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
|
||||
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Cross Direction", 15);
|
||||
cdt.AddColumn("Line", 34);
|
||||
cdt.AddColumn("Trigger Region", 14);
|
||||
|
||||
foreach (Border b in m_scene.NorthBorders)
|
||||
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||
|
||||
foreach (Border b in m_scene.EastBorders)
|
||||
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||
|
||||
foreach (Border b in m_scene.SouthBorders)
|
||||
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||
|
||||
foreach (Border b in m_scene.WestBorders)
|
||||
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||
|
||||
cdt.AddToStringBuilder(sb);
|
||||
|
||||
MainConsole.Instance.Output(sb.ToString());
|
||||
}
|
||||
|
||||
private void HandleDebugSceneGetCommand(string module, string[] args)
|
||||
|
@ -263,4 +232,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -748,8 +748,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
|
|||
position.X = s_tree.AbsolutePosition.X + (float)randX;
|
||||
position.Y = s_tree.AbsolutePosition.Y + (float)randY;
|
||||
|
||||
if (position.X <= ((int)Constants.RegionSize - 1) && position.X >= 0 &&
|
||||
position.Y <= ((int)Constants.RegionSize - 1) && position.Y >= 0 &&
|
||||
if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
|
||||
position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
|
||||
Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
|
||||
{
|
||||
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
|||
private List<BasicActor> _actors = new List<BasicActor>();
|
||||
private List<BasicPhysicsPrim> _prims = new List<BasicPhysicsPrim>();
|
||||
private float[] _heightMap;
|
||||
private Vector3 m_regionExtent;
|
||||
|
||||
//protected internal string sceneIdentifier;
|
||||
|
||||
|
@ -58,6 +59,12 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
|||
|
||||
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
||||
{
|
||||
throw new Exception("Should not be called.");
|
||||
}
|
||||
|
||||
public override void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
|
||||
{
|
||||
m_regionExtent = regionExtent;
|
||||
}
|
||||
|
||||
public override void Dispose() {}
|
||||
|
@ -121,23 +128,23 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
|||
{
|
||||
actorPosition.Y = 0.1F;
|
||||
}
|
||||
else if (actor.Position.Y >= Constants.RegionSize)
|
||||
else if (actor.Position.Y >= m_regionExtent.Y)
|
||||
{
|
||||
actorPosition.Y = ((int)Constants.RegionSize - 0.1f);
|
||||
actorPosition.Y = (m_regionExtent.Y - 0.1f);
|
||||
}
|
||||
|
||||
if (actor.Position.X < 0)
|
||||
{
|
||||
actorPosition.X = 0.1F;
|
||||
}
|
||||
else if (actor.Position.X >= Constants.RegionSize)
|
||||
else if (actor.Position.X >= m_regionExtent.X)
|
||||
{
|
||||
actorPosition.X = ((int)Constants.RegionSize - 0.1f);
|
||||
actorPosition.X = (m_regionExtent.X - 0.1f);
|
||||
}
|
||||
|
||||
float terrainHeight = 0;
|
||||
if (_heightMap != null)
|
||||
terrainHeight = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X];
|
||||
terrainHeight = _heightMap[(int)actor.Position.Y * (int)m_regionExtent.Y + (int)actor.Position.X];
|
||||
|
||||
float height = terrainHeight + actor.Size.Z;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ using System.Reflection;
|
|||
using Nini.Config;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.Manager
|
||||
{
|
||||
|
@ -59,6 +60,14 @@ namespace OpenSim.Region.Physics.Manager
|
|||
m_log.Info("[PHYSICS]: Added meshing engine: " + plugHard.GetName());
|
||||
}
|
||||
|
||||
// Legacy method for simulators before extent was passed
|
||||
public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
|
||||
IConfigSource config, string regionName)
|
||||
{
|
||||
Vector3 extent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||
return GetPhysicsScene(physEngineName, meshEngineName, config, regionName, extent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a physics scene for the given physics engine and mesher.
|
||||
/// </summary>
|
||||
|
@ -66,7 +75,8 @@ namespace OpenSim.Region.Physics.Manager
|
|||
/// <param name="meshEngineName"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName, IConfigSource config, string regionName)
|
||||
public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
|
||||
IConfigSource config, string regionName, Vector3 regionExtent)
|
||||
{
|
||||
if (String.IsNullOrEmpty(physEngineName))
|
||||
{
|
||||
|
@ -94,7 +104,7 @@ namespace OpenSim.Region.Physics.Manager
|
|||
{
|
||||
m_log.Info("[PHYSICS]: creating " + physEngineName);
|
||||
PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName);
|
||||
result.Initialise(meshEngine, config);
|
||||
result.Initialise(meshEngine, config, regionExtent);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -132,8 +132,17 @@ namespace OpenSim.Region.Physics.Manager
|
|||
}
|
||||
}
|
||||
|
||||
// Deprecated. Do not use this for new physics engines.
|
||||
public abstract void Initialise(IMesher meshmerizer, IConfigSource config);
|
||||
|
||||
// For older physics engines that do not implement non-legacy region sizes.
|
||||
// If the physics engine handles the region extent feature, it overrides this function.
|
||||
public virtual void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
|
||||
{
|
||||
// If not overridden, call the old initialization entry.
|
||||
Initialise(meshmerizer, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an avatar
|
||||
/// </summary>
|
||||
|
|
|
@ -134,6 +134,49 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
throw new Exception(string.Format("Region with id {0} not found", regionId));
|
||||
}
|
||||
|
||||
// Test to see if this postiion (relative to the region) is within the area covered
|
||||
// by this megaregion.
|
||||
public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
|
||||
{
|
||||
bool ret = false;
|
||||
if (xx < 0 || yy < 0)
|
||||
return ret;
|
||||
|
||||
foreach (RegionConnections rootRegion in m_regions.Values)
|
||||
{
|
||||
if (currentRegion == rootRegion.RegionId)
|
||||
{
|
||||
// The caller is in the root region so this is an easy test
|
||||
if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maybe the caller is in one of the sub-regions
|
||||
foreach (RegionData childRegion in rootRegion.ConnectedRegions)
|
||||
{
|
||||
if (currentRegion == childRegion.RegionId)
|
||||
{
|
||||
// This is a child. Diddle the offsets and check if in
|
||||
Vector3 positionInMegaregion = childRegion.Offset;
|
||||
positionInMegaregion.X += xx;
|
||||
positionInMegaregion.Y += yy;
|
||||
if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void NewPresence(ScenePresence presence)
|
||||
{
|
||||
if (presence.IsChildAgent)
|
||||
|
@ -220,27 +263,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
//
|
||||
*/
|
||||
|
||||
// Give each region a standard set of non-infinite borders
|
||||
Border northBorder = new Border();
|
||||
northBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
|
||||
northBorder.CrossDirection = Cardinals.N;
|
||||
scene.NorthBorders[0] = northBorder;
|
||||
|
||||
Border southBorder = new Border();
|
||||
southBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
|
||||
southBorder.CrossDirection = Cardinals.S;
|
||||
scene.SouthBorders[0] = southBorder;
|
||||
|
||||
Border eastBorder = new Border();
|
||||
eastBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
|
||||
eastBorder.CrossDirection = Cardinals.E;
|
||||
scene.EastBorders[0] = eastBorder;
|
||||
|
||||
Border westBorder = new Border();
|
||||
westBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
|
||||
westBorder.CrossDirection = Cardinals.W;
|
||||
scene.WestBorders[0] = westBorder;
|
||||
|
||||
RegionConnections newConn = new RegionConnections();
|
||||
newConn.ConnectedRegions = new List<RegionData>();
|
||||
newConn.RegionScene = scene;
|
||||
|
@ -248,8 +270,8 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
newConn.RegionId = scene.RegionInfo.originRegionID;
|
||||
newConn.X = scene.RegionInfo.RegionLocX;
|
||||
newConn.Y = scene.RegionInfo.RegionLocY;
|
||||
newConn.XEnd = (int)Constants.RegionSize;
|
||||
newConn.YEnd = (int)Constants.RegionSize;
|
||||
newConn.XEnd = scene.RegionInfo.RegionSizeX;
|
||||
newConn.YEnd = scene.RegionInfo.RegionSizeX;
|
||||
|
||||
lock (m_regions)
|
||||
{
|
||||
|
@ -415,6 +437,11 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
*/
|
||||
#endregion
|
||||
|
||||
|
||||
// Check to see if this new region is adjacent to the root region.
|
||||
// Note that we expect the regions to be combined from the root region outward
|
||||
// thus the requirement for the ordering in the configuration files.
|
||||
|
||||
// If we're one region over +x y (i.e. root region is to the west)
|
||||
//xxx
|
||||
//xxy
|
||||
|
@ -431,7 +458,7 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
//xxx
|
||||
if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
|
||||
{
|
||||
connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene);
|
||||
connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -441,9 +468,8 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
//xxx
|
||||
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
|
||||
{
|
||||
connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene);
|
||||
connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,20 +479,20 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
DoWorkForRootRegion(newConn, scene);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up infinite borders around the entire AABB of the combined ConnectedRegions
|
||||
AdjustLargeRegionBounds();
|
||||
}
|
||||
|
||||
private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
|
||||
{
|
||||
// Offset (in meters) from the base of this region to the base of the root region.
|
||||
Vector3 offset = Vector3.Zero;
|
||||
offset.X = newConn.PosX - rootConn.PosX;
|
||||
offset.Y = newConn.PosY - rootConn.PosY;
|
||||
|
||||
// The new total size of the region (in meters)
|
||||
// We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
|
||||
Vector3 extents = Vector3.Zero;
|
||||
extents.Y = rootConn.YEnd;
|
||||
extents.X = rootConn.XEnd + newConn.XEnd;
|
||||
extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
|
||||
extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
|
||||
|
||||
rootConn.UpdateExtents(extents);
|
||||
|
||||
|
@ -475,9 +501,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
rootConn.RegionScene.RegionInfo.RegionName,
|
||||
newConn.RegionScene.RegionInfo.RegionName, offset, extents);
|
||||
|
||||
scene.BordersLocked = true;
|
||||
rootConn.RegionScene.BordersLocked = true;
|
||||
|
||||
RegionData ConnectedRegion = new RegionData();
|
||||
ConnectedRegion.Offset = offset;
|
||||
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
|
||||
|
@ -490,34 +513,10 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
// Inform Child region that it needs to forward it's terrain to the root region
|
||||
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
|
||||
|
||||
// Extend the borders as appropriate
|
||||
lock (rootConn.RegionScene.EastBorders)
|
||||
rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.NorthBorders)
|
||||
rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.SouthBorders)
|
||||
rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (scene.WestBorders)
|
||||
{
|
||||
scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
|
||||
|
||||
// Trigger auto teleport to root region
|
||||
scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
|
||||
scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
|
||||
}
|
||||
|
||||
// Reset Terrain.. since terrain loads before we get here, we need to load
|
||||
// it again so it loads in the root region
|
||||
|
||||
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
|
||||
|
||||
// Unlock borders
|
||||
rootConn.RegionScene.BordersLocked = false;
|
||||
scene.BordersLocked = false;
|
||||
|
||||
// Create a client event forwarder and add this region's events to the root region.
|
||||
if (rootConn.ClientEventForwarder != null)
|
||||
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
|
||||
|
@ -525,6 +524,9 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
|
||||
* was generalized. These functions are not needed for the generalized solution but left for reference.
|
||||
private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
|
||||
{
|
||||
Vector3 offset = Vector3.Zero;
|
||||
|
@ -536,9 +538,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
extents.X = rootConn.XEnd;
|
||||
rootConn.UpdateExtents(extents);
|
||||
|
||||
scene.BordersLocked = true;
|
||||
rootConn.RegionScene.BordersLocked = true;
|
||||
|
||||
RegionData ConnectedRegion = new RegionData();
|
||||
ConnectedRegion.Offset = offset;
|
||||
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
|
||||
|
@ -553,30 +552,11 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
|
||||
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
|
||||
|
||||
lock (rootConn.RegionScene.NorthBorders)
|
||||
rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.EastBorders)
|
||||
rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.WestBorders)
|
||||
rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (scene.SouthBorders)
|
||||
{
|
||||
scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
|
||||
scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
|
||||
scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
|
||||
}
|
||||
|
||||
// Reset Terrain.. since terrain normally loads first.
|
||||
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
|
||||
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
|
||||
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
|
||||
|
||||
scene.BordersLocked = false;
|
||||
rootConn.RegionScene.BordersLocked = false;
|
||||
|
||||
if (rootConn.ClientEventForwarder != null)
|
||||
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
|
||||
|
||||
|
@ -600,9 +580,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
extents.Y = rootConn.YEnd;
|
||||
extents.X = rootConn.XEnd;
|
||||
|
||||
scene.BordersLocked = true;
|
||||
rootConn.RegionScene.BordersLocked = true;
|
||||
|
||||
RegionData ConnectedRegion = new RegionData();
|
||||
ConnectedRegion.Offset = offset;
|
||||
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
|
||||
|
@ -618,67 +595,10 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
|
||||
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
|
||||
|
||||
lock (rootConn.RegionScene.NorthBorders)
|
||||
{
|
||||
if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
|
||||
{
|
||||
//compound border
|
||||
// already locked above
|
||||
rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.EastBorders)
|
||||
rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.WestBorders)
|
||||
rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
}
|
||||
}
|
||||
|
||||
lock (scene.SouthBorders)
|
||||
{
|
||||
scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
|
||||
scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
|
||||
scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
|
||||
}
|
||||
|
||||
lock (rootConn.RegionScene.EastBorders)
|
||||
{
|
||||
if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
|
||||
{
|
||||
rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.NorthBorders)
|
||||
rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
|
||||
lock (rootConn.RegionScene.SouthBorders)
|
||||
rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
}
|
||||
}
|
||||
|
||||
lock (scene.WestBorders)
|
||||
{
|
||||
scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
|
||||
scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
|
||||
scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
|
||||
}
|
||||
|
||||
/*
|
||||
else
|
||||
{
|
||||
conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
|
||||
scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Reset Terrain.. since terrain normally loads first.
|
||||
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
|
||||
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
|
||||
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
|
||||
scene.BordersLocked = false;
|
||||
rootConn.RegionScene.BordersLocked = false;
|
||||
|
||||
if (rootConn.ClientEventForwarder != null)
|
||||
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
|
||||
|
@ -687,6 +607,7 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
|
||||
//scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
|
||||
}
|
||||
*/
|
||||
|
||||
private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
|
||||
{
|
||||
|
@ -885,125 +806,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
// }
|
||||
// }
|
||||
|
||||
// Create a set of infinite borders around the whole aabb of the combined island.
|
||||
private void AdjustLargeRegionBounds()
|
||||
{
|
||||
lock (m_regions)
|
||||
{
|
||||
foreach (RegionConnections rconn in m_regions.Values)
|
||||
{
|
||||
Vector3 offset = Vector3.Zero;
|
||||
rconn.RegionScene.BordersLocked = true;
|
||||
foreach (RegionData rdata in rconn.ConnectedRegions)
|
||||
{
|
||||
if (rdata.Offset.X > offset.X) offset.X = rdata.Offset.X;
|
||||
if (rdata.Offset.Y > offset.Y) offset.Y = rdata.Offset.Y;
|
||||
}
|
||||
|
||||
lock (rconn.RegionScene.NorthBorders)
|
||||
{
|
||||
Border northBorder = null;
|
||||
// If we don't already have an infinite border, create one.
|
||||
if (!TryGetInfiniteBorder(rconn.RegionScene.NorthBorders, out northBorder))
|
||||
{
|
||||
northBorder = new Border();
|
||||
rconn.RegionScene.NorthBorders.Add(northBorder);
|
||||
}
|
||||
|
||||
northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,
|
||||
offset.Y + (int) Constants.RegionSize); //<---
|
||||
northBorder.CrossDirection = Cardinals.N;
|
||||
}
|
||||
|
||||
lock (rconn.RegionScene.SouthBorders)
|
||||
{
|
||||
Border southBorder = null;
|
||||
// If we don't already have an infinite border, create one.
|
||||
if (!TryGetInfiniteBorder(rconn.RegionScene.SouthBorders, out southBorder))
|
||||
{
|
||||
southBorder = new Border();
|
||||
rconn.RegionScene.SouthBorders.Add(southBorder);
|
||||
}
|
||||
southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
|
||||
southBorder.CrossDirection = Cardinals.S;
|
||||
}
|
||||
|
||||
lock (rconn.RegionScene.EastBorders)
|
||||
{
|
||||
Border eastBorder = null;
|
||||
// If we don't already have an infinite border, create one.
|
||||
if (!TryGetInfiniteBorder(rconn.RegionScene.EastBorders, out eastBorder))
|
||||
{
|
||||
eastBorder = new Border();
|
||||
rconn.RegionScene.EastBorders.Add(eastBorder);
|
||||
}
|
||||
eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, offset.X + (int)Constants.RegionSize);
|
||||
//<---
|
||||
eastBorder.CrossDirection = Cardinals.E;
|
||||
}
|
||||
|
||||
lock (rconn.RegionScene.WestBorders)
|
||||
{
|
||||
Border westBorder = null;
|
||||
// If we don't already have an infinite border, create one.
|
||||
if (!TryGetInfiniteBorder(rconn.RegionScene.WestBorders, out westBorder))
|
||||
{
|
||||
westBorder = new Border();
|
||||
rconn.RegionScene.WestBorders.Add(westBorder);
|
||||
|
||||
}
|
||||
westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
|
||||
westBorder.CrossDirection = Cardinals.W;
|
||||
}
|
||||
|
||||
rconn.RegionScene.BordersLocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try and get an Infinite border out of a listT of borders
|
||||
/// </summary>
|
||||
/// <param name="borders"></param>
|
||||
/// <param name="oborder"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryGetInfiniteBorder(List<Border> borders, out Border oborder)
|
||||
{
|
||||
// Warning! Should be locked before getting here!
|
||||
foreach (Border b in borders)
|
||||
{
|
||||
if (b.BorderLine.X == float.MinValue && b.BorderLine.Y == float.MaxValue)
|
||||
{
|
||||
oborder = b;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
oborder = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public RegionData GetRegionFromPosition(Vector3 pPosition)
|
||||
{
|
||||
pPosition = pPosition/(int) Constants.RegionSize;
|
||||
int OffsetX = (int) pPosition.X;
|
||||
int OffsetY = (int) pPosition.Y;
|
||||
|
||||
lock (m_regions)
|
||||
{
|
||||
foreach (RegionConnections regConn in m_regions.Values)
|
||||
{
|
||||
foreach (RegionData reg in regConn.ConnectedRegions)
|
||||
{
|
||||
if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new RegionData();
|
||||
}
|
||||
|
||||
public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
|
||||
{
|
||||
if (BigRegion.PermissionModule == null)
|
||||
|
|
|
@ -64,12 +64,12 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
/// <summary>
|
||||
/// The X meters position of this connection.
|
||||
/// </summary>
|
||||
public uint PosX { get { return X * Constants.RegionSize; } }
|
||||
public uint PosX { get { return Util.RegionToWorldLoc(X); } }
|
||||
|
||||
/// <summary>
|
||||
/// The Y meters co-ordinate of this connection.
|
||||
/// </summary>
|
||||
public uint PosY { get { return Y * Constants.RegionSize; } }
|
||||
public uint PosY { get { return Util.RegionToWorldLoc(Y); } }
|
||||
|
||||
/// <summary>
|
||||
/// The size of the megaregion in meters.
|
||||
|
@ -91,4 +91,4 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
YEnd = (uint)extents.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2352,7 +2352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
//
|
||||
// This workaround is to prevent silent failure of this function.
|
||||
// According to the specification on the SL Wiki, providing a position outside of the
|
||||
if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
|
||||
if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2362,9 +2362,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
m_host.ParentGroup.IsAttachment || // return FALSE if attachment
|
||||
(
|
||||
pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
|
||||
pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
|
||||
pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
|
||||
pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
|
||||
pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
|
||||
pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
|
||||
pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
|
||||
)
|
||||
)
|
||||
|
@ -4655,10 +4655,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
DataserverPlugin.RegisterRequest(m_host.LocalId,
|
||||
m_item.ItemID, item.AssetID.ToString());
|
||||
|
||||
Vector3 region = new Vector3(
|
||||
World.RegionInfo.RegionLocX * Constants.RegionSize,
|
||||
World.RegionInfo.RegionLocY * Constants.RegionSize,
|
||||
0);
|
||||
Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
|
||||
|
||||
World.AssetService.Get(item.AssetID.ToString(), this,
|
||||
delegate(string i, object sender, AssetBase a)
|
||||
|
@ -5949,7 +5946,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
public LSL_Vector llGetRegionCorner()
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -6104,7 +6101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
LSL_Float mag;
|
||||
if (dir.x > 0)
|
||||
{
|
||||
mag = (Constants.RegionSize - pos.x) / dir.x;
|
||||
mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6115,7 +6112,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
|
||||
edge.y = pos.y + (dir.y * mag);
|
||||
|
||||
if (edge.y > Constants.RegionSize || edge.y < 0)
|
||||
if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
|
||||
{
|
||||
// Y goes out of bounds first
|
||||
edge.y = dir.y / Math.Abs(dir.y);
|
||||
|
|
|
@ -459,7 +459,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
|
||||
if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
|
||||
OSSLError("osSetTerrainHeight: Coordinate out of bounds");
|
||||
|
||||
if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
|
||||
|
@ -489,7 +489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
private LSL_Float GetTerrainHeight(int x, int y)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
|
||||
if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
|
||||
OSSLError("osGetTerrainHeight: Coordinate out of bounds");
|
||||
|
||||
return World.Heightmap[x, y];
|
||||
|
@ -823,7 +823,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
private void TeleportAgent(string agent, int regionX, int regionY,
|
||||
LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
|
||||
{
|
||||
ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
|
||||
ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
UUID agentId = new UUID();
|
||||
|
@ -3024,7 +3024,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
}
|
||||
else
|
||||
{
|
||||
return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight);
|
||||
return new LSL_Vector((float)World.RegionInfo.RegionSizeX,
|
||||
(float)World.RegionInfo.RegionSizeY,
|
||||
(float)World.RegionInfo.RegionSizeZ );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -708,18 +708,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
|||
}
|
||||
private void Save()
|
||||
{
|
||||
/* Remove temporarily until we have a handle to the region size
|
||||
if (Position.x > ((int)Constants.RegionSize - 1))
|
||||
Position.x = ((int)Constants.RegionSize - 1);
|
||||
if (Position.x < 0)
|
||||
Position.x = 0;
|
||||
if (Position.y > ((int)Constants.RegionSize - 1))
|
||||
Position.y = ((int)Constants.RegionSize - 1);
|
||||
*/
|
||||
if (Position.x < 0)
|
||||
Position.x = 0;
|
||||
if (Position.y < 0)
|
||||
Position.y = 0;
|
||||
if (Position.z > 768)
|
||||
Position.z = 768;
|
||||
if (Position.z < 0)
|
||||
Position.z = 0;
|
||||
if (Position.z > Constants.RegionHeight)
|
||||
Position.z = Constants.RegionHeight;
|
||||
prim.OSSL.llSetPos(Position);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace OpenSim.Server.Handlers.MapImage
|
|||
if (m_GridService != null)
|
||||
{
|
||||
System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
|
||||
GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, x * (int)Constants.RegionSize, y * (int)Constants.RegionSize);
|
||||
GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
|
||||
if (r != null)
|
||||
{
|
||||
if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace OpenSim.Server.Handlers.MapImage
|
|||
if (m_GridService != null)
|
||||
{
|
||||
System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
|
||||
GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, x * (int)Constants.RegionSize, y * (int)Constants.RegionSize);
|
||||
GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
|
||||
if (r != null)
|
||||
{
|
||||
if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
|
||||
|
||||
Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight);
|
||||
|
||||
OSDMap extraData = new OSDMap
|
||||
{
|
||||
|
@ -174,8 +174,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
if (region != null)
|
||||
{
|
||||
List<GridRegion> regions = GetRegionRange(scopeID,
|
||||
region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + (int)Constants.RegionSize + NEIGHBOR_RADIUS,
|
||||
region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + (int)Constants.RegionSize + NEIGHBOR_RADIUS);
|
||||
region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + region.RegionSizeX + NEIGHBOR_RADIUS,
|
||||
region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + region.RegionSizeY + NEIGHBOR_RADIUS);
|
||||
|
||||
for (int i = 0; i < regions.Count; i++)
|
||||
{
|
||||
|
@ -240,7 +240,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
else
|
||||
{
|
||||
// m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}",
|
||||
// x / Constants.RegionSize, y / Constants.RegionSize);
|
||||
// Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -655,7 +655,7 @@ namespace OpenSim.Services.GridService
|
|||
return;
|
||||
}
|
||||
|
||||
RegionData region = m_Database.Get(x * (int)Constants.RegionSize, y * (int)Constants.RegionSize, UUID.Zero);
|
||||
RegionData region = m_Database.Get((int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y), UUID.Zero);
|
||||
if (region == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y);
|
||||
|
@ -673,6 +673,7 @@ namespace OpenSim.Services.GridService
|
|||
dispList.AddRow("Region Name", r.RegionName);
|
||||
dispList.AddRow("Region ID", r.RegionID);
|
||||
dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY));
|
||||
dispList.AddRow("Size", string.Format("{0}x{1}", r.sizeX, r.sizeY));
|
||||
dispList.AddRow("URI", r.Data["serverURI"]);
|
||||
dispList.AddRow("Owner ID", r.Data["owner_uuid"]);
|
||||
dispList.AddRow("Flags", flags);
|
||||
|
|
|
@ -183,8 +183,8 @@ namespace OpenSim.Services.GridService
|
|||
public GridRegion LinkRegion(UUID scopeID, string regionDescriptor)
|
||||
{
|
||||
string reason = string.Empty;
|
||||
int xloc = random.Next(0, Int16.MaxValue) * (int)Constants.RegionSize;
|
||||
return TryLinkRegionToCoords(scopeID, regionDescriptor, xloc, 0, out reason);
|
||||
uint xloc = Util.RegionToWorldLoc((uint)random.Next(0, Int16.MaxValue));
|
||||
return TryLinkRegionToCoords(scopeID, regionDescriptor, (int)xloc, 0, out reason);
|
||||
}
|
||||
|
||||
private static Random random = new Random();
|
||||
|
@ -260,7 +260,7 @@ namespace OpenSim.Services.GridService
|
|||
{
|
||||
m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0} {1}, in {2}-{3}",
|
||||
((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI),
|
||||
remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize);
|
||||
remoteRegionName, Util.WorldToRegionLoc((uint)xloc), Util.WorldToRegionLoc((uint)yloc));
|
||||
|
||||
reason = string.Empty;
|
||||
Uri uri = null;
|
||||
|
@ -311,7 +311,7 @@ namespace OpenSim.Services.GridService
|
|||
if (region != null)
|
||||
{
|
||||
m_log.WarnFormat("[HYPERGRID LINKER]: Coordinates {0}-{1} are already occupied by region {2} with uuid {3}",
|
||||
regInfo.RegionLocX / Constants.RegionSize, regInfo.RegionLocY / Constants.RegionSize,
|
||||
Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY),
|
||||
region.RegionName, region.RegionID);
|
||||
reason = "Coordinates are already in use";
|
||||
return false;
|
||||
|
@ -347,7 +347,7 @@ namespace OpenSim.Services.GridService
|
|||
if (region != null)
|
||||
{
|
||||
m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates {0} {1}",
|
||||
region.RegionLocX / Constants.RegionSize, region.RegionLocY / Constants.RegionSize);
|
||||
Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY));
|
||||
regInfo = region;
|
||||
return true;
|
||||
}
|
||||
|
@ -424,10 +424,10 @@ namespace OpenSim.Services.GridService
|
|||
// {
|
||||
// uint ux = 0, uy = 0;
|
||||
// Utils.LongToUInts(realHandle, out ux, out uy);
|
||||
// x = ux / Constants.RegionSize;
|
||||
// y = uy / Constants.RegionSize;
|
||||
// x = Util.WorldToRegionLoc(ux);
|
||||
// y = Util.WorldToRegionLoc(uy);
|
||||
//
|
||||
// const uint limit = (4096 - 1) * Constants.RegionSize;
|
||||
// const uint limit = Util.RegionToWorldLoc(4096 - 1);
|
||||
// uint xmin = ux - limit;
|
||||
// uint xmax = ux + limit;
|
||||
// uint ymin = uy - limit;
|
||||
|
@ -503,8 +503,9 @@ namespace OpenSim.Services.GridService
|
|||
foreach (RegionData r in regions)
|
||||
{
|
||||
MainConsole.Instance.Output(String.Format("{0}\n{2,-32} {1}\n",
|
||||
r.RegionName, r.RegionID, String.Format("{0},{1} ({2},{3})", r.posX, r.posY,
|
||||
r.posX / Constants.RegionSize, r.posY / Constants.RegionSize)));
|
||||
r.RegionName, r.RegionID,
|
||||
String.Format("{0},{1} ({2},{3})", r.posX, r.posY,
|
||||
Util.WorldToRegionLoc((uint)r.posX), Util.WorldToRegionLoc((uint)r.posY))) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -529,8 +530,8 @@ namespace OpenSim.Services.GridService
|
|||
int xloc, yloc;
|
||||
string serverURI;
|
||||
string remoteName = null;
|
||||
xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize;
|
||||
yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize;
|
||||
xloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[0]));
|
||||
yloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[1]));
|
||||
serverURI = cmdparams[2];
|
||||
if (cmdparams.Length > 3)
|
||||
remoteName = string.Join(" ", cmdparams, 3, cmdparams.Length - 3);
|
||||
|
@ -601,13 +602,13 @@ namespace OpenSim.Services.GridService
|
|||
{
|
||||
// old format
|
||||
GridRegion regInfo;
|
||||
int xloc, yloc;
|
||||
uint xloc, yloc;
|
||||
uint externalPort;
|
||||
string externalHostName;
|
||||
try
|
||||
{
|
||||
xloc = Convert.ToInt32(cmdparams[0]);
|
||||
yloc = Convert.ToInt32(cmdparams[1]);
|
||||
xloc = (uint)Convert.ToInt32(cmdparams[0]);
|
||||
yloc = (uint)Convert.ToInt32(cmdparams[1]);
|
||||
externalPort = Convert.ToUInt32(cmdparams[3]);
|
||||
externalHostName = cmdparams[2];
|
||||
//internalPort = Convert.ToUInt32(cmdparams[4]);
|
||||
|
@ -621,10 +622,11 @@ namespace OpenSim.Services.GridService
|
|||
}
|
||||
|
||||
// Convert cell coordinates given by the user to meters
|
||||
xloc = xloc * (int)Constants.RegionSize;
|
||||
yloc = yloc * (int)Constants.RegionSize;
|
||||
xloc = Util.RegionToWorldLoc(xloc);
|
||||
yloc = Util.RegionToWorldLoc(yloc);
|
||||
string reason = string.Empty;
|
||||
if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
|
||||
if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc,
|
||||
string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
|
||||
{
|
||||
// What is this? The GridRegion instance will be discarded anyway,
|
||||
// which effectively ignores any local name given with the command.
|
||||
|
@ -704,13 +706,13 @@ namespace OpenSim.Services.GridService
|
|||
private void ReadLinkFromConfig(IConfig config)
|
||||
{
|
||||
GridRegion regInfo;
|
||||
int xloc, yloc;
|
||||
uint xloc, yloc;
|
||||
uint externalPort;
|
||||
string externalHostName;
|
||||
uint realXLoc, realYLoc;
|
||||
|
||||
xloc = Convert.ToInt32(config.GetString("xloc", "0"));
|
||||
yloc = Convert.ToInt32(config.GetString("yloc", "0"));
|
||||
xloc = (uint)Convert.ToInt32(config.GetString("xloc", "0"));
|
||||
yloc = (uint)Convert.ToInt32(config.GetString("yloc", "0"));
|
||||
externalPort = Convert.ToUInt32(config.GetString("externalPort", "0"));
|
||||
externalHostName = config.GetString("externalHostName", "");
|
||||
realXLoc = Convert.ToUInt32(config.GetString("real-xloc", "0"));
|
||||
|
@ -718,18 +720,19 @@ namespace OpenSim.Services.GridService
|
|||
|
||||
if (m_enableAutoMapping)
|
||||
{
|
||||
xloc = (int)((xloc % 100) + m_autoMappingX);
|
||||
yloc = (int)((yloc % 100) + m_autoMappingY);
|
||||
xloc = (uint)((xloc % 100) + m_autoMappingX);
|
||||
yloc = (uint)((yloc % 100) + m_autoMappingY);
|
||||
}
|
||||
|
||||
if (((realXLoc == 0) && (realYLoc == 0)) ||
|
||||
(((realXLoc - xloc < 3896) || (xloc - realXLoc < 3896)) &&
|
||||
((realYLoc - yloc < 3896) || (yloc - realYLoc < 3896))))
|
||||
{
|
||||
xloc = xloc * (int)Constants.RegionSize;
|
||||
yloc = yloc * (int)Constants.RegionSize;
|
||||
xloc = Util.RegionToWorldLoc(xloc);
|
||||
yloc = Util.RegionToWorldLoc(yloc);
|
||||
string reason = string.Empty;
|
||||
if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
|
||||
if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc,
|
||||
string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
|
||||
{
|
||||
regInfo.RegionName = config.GetString("localName", "");
|
||||
}
|
||||
|
|
|
@ -179,14 +179,14 @@ namespace OpenSim.Services.Interfaces
|
|||
protected IPEndPoint m_internalEndPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The co-ordinate of this region.
|
||||
/// The co-ordinate of this region in region units.
|
||||
/// </summary>
|
||||
public int RegionCoordX { get { return RegionLocX / (int)Constants.RegionSize; } }
|
||||
public int RegionCoordX { get { return (int)Util.WorldToRegionLoc((uint)RegionLocX); } }
|
||||
|
||||
/// <summary>
|
||||
/// The co-ordinate of this region
|
||||
/// The co-ordinate of this region in region units
|
||||
/// </summary>
|
||||
public int RegionCoordY { get { return RegionLocY / (int)Constants.RegionSize; } }
|
||||
public int RegionCoordY { get { return (int)Util.WorldToRegionLoc((uint)RegionLocY); } }
|
||||
|
||||
/// <summary>
|
||||
/// The location of this region in meters.
|
||||
|
@ -265,8 +265,8 @@ namespace OpenSim.Services.Interfaces
|
|||
|
||||
public GridRegion(uint xcell, uint ycell)
|
||||
{
|
||||
m_regionLocX = (int)(xcell * Constants.RegionSize);
|
||||
m_regionLocY = (int)(ycell * Constants.RegionSize);
|
||||
m_regionLocX = (int)Util.RegionToWorldLoc(xcell);
|
||||
m_regionLocY = (int)Util.RegionToWorldLoc(ycell);
|
||||
RegionSizeX = (int)Constants.RegionSize;
|
||||
RegionSizeY = (int)Constants.RegionSize;
|
||||
}
|
||||
|
@ -274,8 +274,8 @@ namespace OpenSim.Services.Interfaces
|
|||
public GridRegion(RegionInfo ConvertFrom)
|
||||
{
|
||||
m_regionName = ConvertFrom.RegionName;
|
||||
m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize);
|
||||
m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize);
|
||||
m_regionLocX = (int)(ConvertFrom.WorldLocX);
|
||||
m_regionLocY = (int)(ConvertFrom.WorldLocY);
|
||||
RegionSizeX = (int)ConvertFrom.RegionSizeX;
|
||||
RegionSizeY = (int)ConvertFrom.RegionSizeY;
|
||||
m_internalEndPoint = ConvertFrom.InternalEndPoint;
|
||||
|
|
|
@ -368,7 +368,8 @@ namespace OpenSim.Services.LLLoginService
|
|||
|
||||
private void FillOutHomeData(GridUserInfo pinfo, GridRegion home)
|
||||
{
|
||||
int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize;
|
||||
int x = (int)Util.RegionToWorldLoc(1000);
|
||||
int y = (int)Util.RegionToWorldLoc(1000);
|
||||
if (home != null)
|
||||
{
|
||||
x = home.RegionLocX;
|
||||
|
@ -443,10 +444,23 @@ namespace OpenSim.Services.LLLoginService
|
|||
ErrorReason = "key";
|
||||
welcomeMessage = "Welcome to OpenSim!";
|
||||
seedCapability = String.Empty;
|
||||
home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" +
|
||||
userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" +
|
||||
userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" +
|
||||
userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}";
|
||||
home = "{'region_handle':["
|
||||
+ "r" + Util.RegionToWorldLoc(1000).ToString()
|
||||
+ ","
|
||||
+ "r" + Util.RegionToWorldLoc(1000).ToString()
|
||||
+ "], 'position':["
|
||||
+ "r" + userProfile.homepos.X.ToString()
|
||||
+ ","
|
||||
+ "r" + userProfile.homepos.Y.ToString()
|
||||
+ ","
|
||||
+ "r" + userProfile.homepos.Z.ToString()
|
||||
+ "], 'look_at':["
|
||||
+ "r" + userProfile.homelookat.X.ToString()
|
||||
+ ","
|
||||
+ "r" + userProfile.homelookat.Y.ToString()
|
||||
+ ","
|
||||
+ "r" + userProfile.homelookat.Z.ToString()
|
||||
+ "]}";
|
||||
lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]";
|
||||
RegionX = (uint) 255232;
|
||||
RegionY = (uint) 254976;
|
||||
|
|
|
@ -695,7 +695,7 @@ namespace OpenSim.Services.LLLoginService
|
|||
private GridRegion FindAlternativeRegion(UUID scopeID)
|
||||
{
|
||||
List<GridRegion> hyperlinks = null;
|
||||
List<GridRegion> regions = m_GridService.GetFallbackRegions(scopeID, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
|
||||
List<GridRegion> regions = m_GridService.GetFallbackRegions(scopeID, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
|
||||
if (regions != null && regions.Count > 0)
|
||||
{
|
||||
hyperlinks = m_GridService.GetHyperlinks(scopeID);
|
||||
|
|
|
@ -150,16 +150,16 @@ namespace OpenSim.Tests.Clients.GridClient
|
|||
|
||||
Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)");
|
||||
regions = m_Connector.GetRegionRange(UUID.Zero,
|
||||
900 * (int)Constants.RegionSize, 1002 * (int) Constants.RegionSize,
|
||||
900 * (int)Constants.RegionSize, 1002 * (int) Constants.RegionSize);
|
||||
(int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002),
|
||||
(int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) );
|
||||
if (regions == null)
|
||||
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
|
||||
else
|
||||
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
|
||||
Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)");
|
||||
regions = m_Connector.GetRegionRange(UUID.Zero,
|
||||
900 * (int)Constants.RegionSize, 950 * (int)Constants.RegionSize,
|
||||
900 * (int)Constants.RegionSize, 950 * (int)Constants.RegionSize);
|
||||
(int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950),
|
||||
(int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) );
|
||||
if (regions == null)
|
||||
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
|
||||
else
|
||||
|
|
|
@ -69,9 +69,7 @@ namespace OpenSim.Tests.Common
|
|||
tc.OnTestClientInformClientOfNeighbour += (neighbourHandle, neighbourExternalEndPoint) =>
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(neighbourHandle, out x, out y);
|
||||
x /= Constants.RegionSize;
|
||||
y /= Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(neighbourHandle, out x, out y);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}",
|
||||
|
@ -104,9 +102,7 @@ namespace OpenSim.Tests.Common
|
|||
+= (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) =>
|
||||
{
|
||||
uint x, y;
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
x /= Constants.RegionSize;
|
||||
y /= Constants.RegionSize;
|
||||
Util.RegionHandleToRegionLoc(regionHandle, out x, out y);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[TEST CLIENT]: Processing send region teleport for destination at {0},{1} at {2}",
|
||||
|
@ -125,4 +121,4 @@ namespace OpenSim.Tests.Common
|
|||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -159,7 +169,7 @@ namespace OpenSim.Data.Null
|
|||
protected Dictionary<UUID, SceneObjectPart> m_sceneObjectParts = new Dictionary<UUID, SceneObjectPart>();
|
||||
protected Dictionary<UUID, ICollection<TaskInventoryItem>> m_primItems
|
||||
= new Dictionary<UUID, ICollection<TaskInventoryItem>>();
|
||||
protected Dictionary<UUID, double[,]> m_terrains = new Dictionary<UUID, double[,]>();
|
||||
protected Dictionary<UUID, TerrainData> m_terrains = new Dictionary<UUID, TerrainData>();
|
||||
protected Dictionary<UUID, LandData> m_landData = new Dictionary<UUID, LandData>();
|
||||
|
||||
public void Initialise(string dbfile)
|
||||
|
@ -304,15 +314,28 @@ namespace OpenSim.Data.Null
|
|||
return new List<SceneObjectGroup>(objects.Values);
|
||||
}
|
||||
|
||||
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||
public void StoreTerrain(TerrainData ter, UUID regionID)
|
||||
{
|
||||
m_terrains[regionID] = ter;
|
||||
}
|
||||
|
||||
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];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public double[,] LoadTerrain(UUID regionID)
|
||||
{
|
||||
if (m_terrains.ContainsKey(regionID))
|
||||
return m_terrains[regionID];
|
||||
return m_terrains[regionID].GetDoubles();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue