Changes to Load Oar options and new code to support importing OARs with different Region sizes to the destination region.

Signed-off-by: UbitUmarov <ajlduarte@sapo.pt>
This commit is contained in:
Jak Daniels
2015-11-19 13:28:17 +00:00
committed by UbitUmarov
parent cc992bf156
commit 0b216c37df
4 changed files with 282 additions and 58 deletions

View File

@@ -40,6 +40,7 @@ using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Serialization;
using OpenSim.Framework.Serialization.External;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.CoreModules.World.Land;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
@@ -131,7 +132,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// </value>
protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f);
/// <value>
/// Corner 1 of a bounding cuboid which specifies which objects we load from the oar
/// </value>
protected Vector3 m_boundingOrigin = Vector3.Zero;
/// <value>
/// Size of a bounding cuboid which specifies which objects we load from the oar
/// </value>
protected Vector3 m_boundingSize = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
protected bool m_noObjects = false;
protected bool m_boundingBox = false;
protected bool m_debug = false;
protected Vector3 m_incomingRegionSize = new Vector3(256f, 256f, 4096f);
/// <summary>
/// Used to cache lookups for valid uuids.
@@ -202,6 +217,55 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
: new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
m_boundingOrigin = Vector3.Zero;
m_boundingSize = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, Constants.RegionHeight);
if (options.ContainsKey("bounding-origin"))
{
Vector3 boOption = (Vector3)options["bounding-origin"];
if (boOption.X >= 0 && boOption.X < m_boundingSize.X
&& boOption.Y >= 0 && boOption.Y < m_boundingSize.Y
&& boOption.Z >= 0 && boOption.Z < m_boundingSize.Z)
{
if (m_boundingOrigin != boOption)
{
m_boundingOrigin = boOption;
m_boundingBox = true;
}
}
else m_log.InfoFormat("[ARCHIVER]: The bounding cube origin must be within the destination region! Setting to {0}.", m_boundingOrigin.ToString());
}
if (options.ContainsKey("bounding-size"))
{
Vector3 bsOption = (Vector3)options["bounding-size"];
bool clip = false;
if (bsOption.X <= 0 && bsOption.X > (m_boundingSize.X - m_boundingOrigin.X))
{
bsOption.X = m_boundingSize.X - m_boundingOrigin.X;
clip = true;
}
if (bsOption.Y <= 0 && bsOption.Y > (m_boundingSize.Y - m_boundingOrigin.Y))
{
bsOption.Y = m_boundingSize.Y - m_boundingOrigin.Y;
clip = true;
}
if (bsOption.Z <= 0 && bsOption.Z > (m_boundingSize.Z - m_boundingOrigin.Z))
{
bsOption.Z = m_boundingSize.Y - m_boundingOrigin.Z;
clip = true;
}
if (m_boundingSize != bsOption)
{
m_boundingSize = bsOption;
m_boundingBox = true;
if (clip) m_log.InfoFormat("[ARCHIVER]: The bounding cube specified is larger than the destination region! Clipping to {0}.", m_boundingSize.ToString());
}
}
m_debug = options.ContainsKey("debug");
// Zero can never be a valid user id (or group)
m_validUserUuids[UUID.Zero] = false;
m_validGroupUuids[UUID.Zero] = false;
@@ -435,7 +499,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// If the control file wasn't the first file then reset the read pointer
if (!firstFile)
{
m_log.Warn("Control file wasn't the first file in the archive");
m_log.Warn("[ARCHIVER]: Control file wasn't the first file in the archive");
if (m_loadStream.CanSeek)
{
m_loadStream.Seek(0, SeekOrigin.Begin);
@@ -452,7 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
else
{
// There isn't currently a scenario where this happens, but it's best to add a check just in case
throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
throw new Exception("[ARCHIVER]: Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
}
}
@@ -462,7 +526,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
firstFile = false;
}
throw new Exception("Control file not found");
throw new Exception("[ARCHIVER]: Control file not found");
}
/// <summary>
@@ -473,12 +537,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Reload serialized prims
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation);
// Convert rotation to radians
double rotation = Math.PI * m_rotation / 180f;
OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, (float)rotation);
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
int sceneObjectsLoadedCount = 0;
Vector3 boundingExtent = new Vector3(m_boundingOrigin.X + m_boundingSize.X, m_boundingOrigin.Y + m_boundingSize.Y, m_boundingOrigin.Z + m_boundingSize.Z);
foreach (string serialisedSceneObject in serialisedSceneObjects)
{
@@ -498,30 +566,50 @@ namespace OpenSim.Region.CoreModules.World.Archiver
SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
Vector3 pos = sceneObject.AbsolutePosition;
//fix the rotation center to the middle of the incoming region now as it's otherwise hopelessly confusing on varRegions
//as it only works with objects and terrain (using old Merge method) and not parcels
m_rotationCenter.X = m_incomingRegionSize.X / 2;
m_rotationCenter.Y = m_incomingRegionSize.Y / 2;
if (m_debug) m_log.DebugFormat("[ARCHIVER]: Loading object from OAR with original scene position {0}.", pos.ToString());
// Happily this does not do much to the object since it hasn't been added to the scene yet
if (!sceneObject.IsAttachment)
{
if (m_displacement != Vector3.Zero || m_rotation != 0f)
if (m_rotation != 0f)
{
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;
// 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_debug) m_log.DebugFormat("[ARCHIVER]: After rotation, object from OAR is at scene position {0}.", pos.ToString());
}
if (m_boundingBox)
{
if (pos.X < m_boundingOrigin.X || pos.X >= boundingExtent.X
|| pos.Y < m_boundingOrigin.Y || pos.Y >= boundingExtent.Y
|| pos.Z < m_boundingOrigin.Z || pos.Z >= boundingExtent.Z)
{
if (m_debug) m_log.DebugFormat("[ARCHIVER]: Skipping object from OAR in scene because it's position {0} is outside of bounding cube.", pos.ToString());
continue;
}
//adjust object position to be relative to <0,0> so we can apply the displacement
pos.X -= m_boundingOrigin.X;
pos.Y -= m_boundingOrigin.Y;
}
if (m_displacement != Vector3.Zero)
{
pos += m_displacement;
if (m_debug) m_log.DebugFormat("[ARCHIVER]: After displacement, object from OAR is at scene position {0}.", pos.ToString());
}
sceneObject.AbsolutePosition = pos;
}
if (m_debug) m_log.DebugFormat("[ARCHIVER]: Placing object from OAR in scene at position {0}. ", pos.ToString());
bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
@@ -553,11 +641,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
if (ignoredObjects > 0)
m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);
m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene or were out of bounds", ignoredObjects);
if (oldTelehubUUID != UUID.Zero)
{
m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
m_log.WarnFormat("[ARCHIVER]: Telehub object not found: {0}", oldTelehubUUID);
scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
scene.RegionInfo.RegionSettings.ClearSpawnPoints();
}
@@ -645,15 +733,86 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Reload serialized parcels
m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
List<LandData> landData = new List<LandData>();
ILandObject landObject = scene.RequestModuleInterface<ILandObject>();
List<ILandObject> parcels;
Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
Vector2 displacement = new Vector2(m_displacement.X, m_displacement.Y);
Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
Vector2 regionSize = new Vector2(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY);
// Gather any existing parcels before we add any more. Later as we add parcels we can check if the new parcel
// data overlays any of the old data, and we can modify and remove (if empty) the old parcel so that there's no conflict
parcels = scene.LandChannel.AllParcels();
foreach (string serialisedParcel in serialisedParcels)
{
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
bool overrideRegionSize = true; //use the src land parcel data size not the dst region size
bool isEmptyNow;
Vector3 AABBMin;
Vector3 AABBMax;
if (m_displacement != Vector3.Zero)
// create a new LandObject that we can use to manipulate the incoming source parcel data
// this is ok, but just beware that some of the LandObject functions (that we haven't used here) still
// assume we're always using the destination region size
LandData ld = new LandData();
landObject = new LandObject(ld, scene);
landObject.LandData = parcel;
bool[,] srcLandBitmap = landObject.ConvertBytesToLandBitmap(overrideRegionSize);
if (landObject.IsLandBitmapEmpty(srcLandBitmap))
{
Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
parcel.AABBMin += parcelDisp;
parcel.AABBMax += parcelDisp;
m_log.InfoFormat("[ARCHIVER]: Skipping source parcel {0} with GlobalID: {1} LocalID: {2} that has no claimed land.",
parcel.Name, parcel.GlobalID, parcel.LocalID);
continue;
}
//m_log.DebugFormat("[ARCHIVER]: Showing claimed land for source parcel: {0} with GlobalID: {1} LocalID: {2}.",
// parcel.Name, parcel.GlobalID, parcel.LocalID);
//landObject.DebugLandBitmap(srcLandBitmap);
bool[,] dstLandBitmap = landObject.RemapLandBitmap(srcLandBitmap, displacement, m_rotation, boundingOrigin, boundingSize, regionSize, out isEmptyNow, out AABBMin, out AABBMax);
if (isEmptyNow)
{
m_log.WarnFormat("[ARCHIVER]: Not adding destination parcel {0} with GlobalID: {1} LocalID: {2} because, after applying rotation, bounding and displacement, it has no claimed land.",
parcel.Name, parcel.GlobalID, parcel.LocalID);
continue;
}
//m_log.DebugFormat("[ARCHIVER]: Showing claimed land for destination parcel: {0} with GlobalID: {1} LocalID: {2} after applying rotation, bounding and displacement.",
// parcel.Name, parcel.GlobalID, parcel.LocalID);
//landObject.DebugLandBitmap(dstLandBitmap);
landObject.LandBitmap = dstLandBitmap;
parcel.Bitmap = landObject.ConvertLandBitmapToBytes();
parcel.AABBMin = AABBMin;
parcel.AABBMax = AABBMax;
if (m_merge)
{
// give the remapped parcel a new GlobalID, in case we're using the same OAR twice and a bounding cube, displacement and --merge
parcel.GlobalID = UUID.Random();
//now check if the area of this new incoming parcel overlays an area in any existing parcels
//and if so modify or lose the existing parcels
for (int i = 0; i < parcels.Count; i++)
{
if (parcels[i] != null)
{
bool[,] modLandBitmap = parcels[i].ConvertBytesToLandBitmap(overrideRegionSize);
modLandBitmap = parcels[i].RemoveFromLandBitmap(modLandBitmap, dstLandBitmap, out isEmptyNow, out AABBMin, out AABBMax);
if (isEmptyNow)
{
parcels[i] = null;
}
else
{
parcels[i].LandBitmap = modLandBitmap;
parcels[i].LandData.Bitmap = parcels[i].ConvertLandBitmapToBytes();
parcels[i].LandData.AABBMin = AABBMin;
parcels[i].LandData.AABBMax = AABBMax;
}
}
}
}
// Validate User and Group UUID's
@@ -670,18 +829,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
else
{
parcel.OwnerID = m_defaultUser;
parcel.GroupID = UUID.Zero;
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
parcel.IsGroupOwned = false;
}
}
else
{
if (!ResolveUserUuid(scene, parcel.OwnerID))
parcel.OwnerID = m_defaultUser;
if (!ResolveGroupUuid(parcel.GroupID))
parcel.GroupID = UUID.Zero;
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
}
List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -693,19 +848,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
parcel.ParcelAccessList = accessList;
// m_log.DebugFormat(
// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
if (m_debug) m_log.DebugFormat("[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
landData.Add(parcel);
}
if (!m_merge)
if (m_merge)
{
bool setupDefaultParcel = (landData.Count == 0);
scene.LandChannel.Clear(setupDefaultParcel);
for (int i = 0; i < parcels.Count; i++) //if merging then we need to also add back in any existing parcels
{
if (parcels[i] != null) landData.Add(parcels[i].LandData);
}
}
m_log.InfoFormat("[ARCHIVER]: Clearing {0} parcels.", parcels.Count);
bool setupDefaultParcel = (landData.Count == 0);
scene.LandChannel.Clear(setupDefaultParcel);
scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
}
@@ -934,10 +1093,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
using (MemoryStream ms = new MemoryStream(data))
{
if (m_displacement != Vector3.Zero || m_rotation != 0f)
if (m_displacement != Vector3.Zero || m_rotation != 0f || m_boundingBox)
{
Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y);
terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms);
Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, boundingOrigin, boundingSize, ms); ;
}
else
{
@@ -1014,6 +1174,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
}
else if (xtr.Name.ToString() == "size_in_meters")
{
Vector3 value;
string size = "<" + xtr.ReadElementContentAsString() + ",0>";
if (Vector3.TryParse(size, out value))
{
m_incomingRegionSize = value;
dearchivedScenes.SetRegionSize(m_incomingRegionSize);
m_log.DebugFormat("[ARCHIVER]: Found region_size info {0}", m_incomingRegionSize.ToString());
}
}
}
}

View File

@@ -110,8 +110,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
Vector3 displacement = new Vector3(0f, 0f, 0f);
String defaultUser = "";
float rotation = 0f;
Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0);
Vector3 rotationCenter = new Vector3(Scene.RegionInfo.RegionSizeX / 2f, Scene.RegionInfo.RegionSizeY / 2f, 0);
Vector3 boundingOrigin = new Vector3(0f, 0f, 0f);
Vector3 boundingSize = new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, Constants.RegionHeight);
bool debug = false;
OptionSet options = new OptionSet();
options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
@@ -147,13 +149,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
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<float>(rotation, -359f, 359f) / 180f * (float)Math.PI;
//pass this in as degrees now, convert to radians later during actual work phase
rotation = Util.Clamp<float>(rotation, -359f, 359f);
});
options.Add("rotation-center=", delegate(string v)
{
try
{
m_log.Info("[ARCHIVER MODULE] Warning: --rotation-center no longer does anything and will be removed soon!");
rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
}
catch
@@ -163,6 +166,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver
return;
}
});
options.Add("bounding-origin=", delegate(string v)
{
try
{
boundingOrigin = v == null ? Vector3.Zero : Vector3.Parse(v);
}
catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube origin");
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --bounding-origin \"<128,128,0>\"");
return;
}
});
options.Add("bounding-size=", delegate(string v)
{
try
{
boundingSize = v == null ? new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, Constants.RegionHeight) : Vector3.Parse(v);
}
catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube size");
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as a positive vector3: --bounding-size \"<256,256,4096>\"");
return;
}
});
options.Add("d|debug", delegate(string v) { debug = (v != null); });
// Send a message to the region ready module
/* bluewall* Disable this for the time being
@@ -211,6 +241,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
archiveOptions.Add("displacement", displacement);
archiveOptions.Add("rotation", rotation);
archiveOptions.Add("rotation-center", rotationCenter);
archiveOptions.Add("bounding-origin", boundingOrigin);
archiveOptions.Add("bounding-size", boundingSize);
if (debug) archiveOptions.Add("debug", null);
if (mainParams.Count > 2)
{

View File

@@ -70,6 +70,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// If null then the region doesn't have a corresponding scene, and it won't be loaded.
/// </summary>
public Scene Scene { get; set; }
/// <summary>
/// The size of the region being loaded.
/// </summary>
public Vector3 RegionSize { get; set; }
}
/// <summary>
@@ -118,7 +123,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void SetRegionOriginalID(string id)
{
m_curRegion = new RegionInfo();
if (m_curRegion == null) m_curRegion = new RegionInfo();
m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
m_curRegion.OriginalID = id;
// 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
@@ -130,6 +135,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_directory2region[directory] = m_curRegion;
}
public void SetRegionSize(Vector3 size)
{
if (m_curRegion == null) m_curRegion = new RegionInfo();
m_curRegion.RegionSize = size;
}
/// <summary>
/// Sets all the scenes present in the simulator.