diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index f4807addbb..6f6896680b 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -121,7 +121,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected Vector3 m_displacement = Vector3.Zero;
///
- /// Rotation to apply to the objects as they are loaded.
+ /// Rotation (in radians) to apply to the objects as they are loaded.
///
protected float m_rotation = 0f;
@@ -184,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
m_rotationCenter = options.ContainsKey("rotationCenter") ? (Vector3)options["rotationCenter"]
- : new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f);
+ : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
// Zero can never be a valid user id
m_validUserUuids[UUID.Zero] = false;
@@ -454,8 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Reload serialized prims
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
- float angle = (float)(m_rotation / 180.0 * Math.PI);
- OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, angle);
+ OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation);
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
@@ -483,16 +482,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Happily this does not do much to the object since it hasn't been added to the scene yet
if (sceneObject.AttachmentPoint == 0)
{
- if (angle != 0f)
+ if (m_displacement != Vector3.Zero || m_rotation != 0f)
{
- sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
- Vector3 offset = sceneObject.AbsolutePosition - m_rotationCenter;
- offset *= rot;
- sceneObject.AbsolutePosition = m_rotationCenter + offset;
- }
- if (m_displacement != Vector3.Zero)
- {
- sceneObject.AbsolutePosition += m_displacement;
+ Vector3 pos = sceneObject.AbsolutePosition;
+ if (m_rotation != 0f)
+ {
+ // Rotate the object
+ sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
+ // Get object position relative to rotation axis
+ Vector3 offset = pos - m_rotationCenter;
+ // Rotate the object position
+ offset *= rot;
+ // Restore the object position back to relative to the region
+ pos = m_rotationCenter + offset;
+ }
+ if (m_displacement != Vector3.Zero)
+ {
+ pos += m_displacement;
+ }
+ sceneObject.AbsolutePosition = pos;
}
}
@@ -868,10 +876,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
ITerrainModule terrainModule = scene.RequestModuleInterface();
MemoryStream ms = new MemoryStream(data);
- if (m_displacement != Vector3.Zero)
+ if (m_displacement != Vector3.Zero || m_rotation != 0f)
{
- Vector2 terrainDisplacement = new Vector2(m_displacement.X, m_displacement.Y);
- terrainModule.LoadFromStream(terrainPath, terrainDisplacement, ms);
+ Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y);
+ terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms);
}
else
{
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 2a6f1eb23b..6fbac4c82a 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -120,19 +120,38 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
}
- catch (Exception e)
+ catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement");
- displacement = new Vector3(0f, 0f, 0f);
+ m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\"");
+ return;
}
});
options.Add("rotation=", delegate (string v) {
- rotation = float.Parse(v);
- rotation = Util.Clamp(rotation, -359f, 359f);
+ try
+ {
+ rotation = v == null ? 0f : float.Parse(v);
+ }
+ catch
+ {
+ m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation");
+ m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
+ return;
+ }
+ // Convert to radians for internals
+ rotation = Util.Clamp(rotation, -359f, 359f) / 180f * (float)Math.PI;
});
options.Add("rotationcenter=", delegate (string v) {
- // RA 20130119: libomv's Vector2.Parse doesn't work. Need to use vector3 for the moment
- rotationCenter = Vector3.Parse(v);
+ try
+ {
+ rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
+ }
+ catch
+ {
+ m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement");
+ m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotationcenter \"<128,128,0>\"");
+ return;
+ }
});
// Send a message to the region ready module
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 7bc5e8845a..08891d98a8 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -316,8 +316,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
public void LoadFromStream(string filename, Stream stream)
{
- Vector2 defaultDisplacement = new Vector2(0f, 0f);
- LoadFromStream(filename, defaultDisplacement, stream);
+ LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream);
}
///
@@ -325,7 +324,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
///
/// Filename to terrain file. Type is determined by extension.
///
- public void LoadFromStream(string filename, Vector2 displacement, Stream stream)
+ public void LoadFromStream(string filename, Vector3 displacement,
+ float radianRotation, Vector2 rotationDisplacement, Stream stream)
{
foreach (KeyValuePair loader in m_loaders)
{
@@ -336,7 +336,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
ITerrainChannel channel = loader.Value.LoadStream(stream);
- MergeTerrainIntoExisting(channel, displacement);
+ m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
UpdateRevertMap();
}
catch (NotImplementedException)
@@ -356,33 +356,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
}
- private void MergeTerrainIntoExisting(ITerrainChannel channel, Vector2 displacement)
- {
- if (displacement == Vector2.Zero)
- {
- // If there is no displacement, just use this channel as the new heightmap
- m_scene.Heightmap = channel;
- m_channel = channel;
- }
- else
- {
- // If there is a displacement, we copy the loaded heightmap into the overall region
- for (int xx = 0; xx < channel.Width; xx++)
- {
- for (int yy = 0; yy < channel.Height; yy++)
- {
- int dispX = xx + (int)displacement.X;
- int dispY = yy + (int)displacement.Y;
- if (dispX >= 0 && dispX < m_channel.Width
- && dispY >= 0 && dispY < m_channel.Height)
- {
- m_channel[dispX, dispY] = channel[xx, yy];
- }
- }
- }
- }
- }
-
private static Stream URIFetch(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index 469bd31506..f660b8dbe0 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -26,6 +26,7 @@
*/
using OpenSim.Framework;
+using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
@@ -56,5 +57,7 @@ namespace OpenSim.Region.Framework.Interfaces
ITerrainChannel MakeCopy();
string SaveToXmlString();
void LoadFromXmlString(string data);
+ // Merge some terrain into this channel
+ void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
}
}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 189a30accb..a6f5d9838e 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces
///
///
void LoadFromStream(string filename, Stream stream);
- void LoadFromStream(string filename, Vector2 displacement, Stream stream);
+ void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
///
/// Save a terrain to a stream.
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index b4b1823de3..24709dcf74 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -36,6 +36,8 @@ using OpenSim.Data;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
+using OpenMetaverse;
+
using log4net;
namespace OpenSim.Region.Framework.Scenes
@@ -212,6 +214,76 @@ namespace OpenSim.Region.Framework.Scenes
sr.Close();
}
+ // ITerrainChannel.Merge
+ public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
+ {
+ 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()