diff options
6 files changed, 129 insertions, 54 deletions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index f4807ad..6f68966 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 | |||
121 | protected Vector3 m_displacement = Vector3.Zero; | 121 | protected Vector3 m_displacement = Vector3.Zero; |
122 | 122 | ||
123 | /// <value> | 123 | /// <value> |
124 | /// Rotation to apply to the objects as they are loaded. | 124 | /// Rotation (in radians) to apply to the objects as they are loaded. |
125 | /// </value> | 125 | /// </value> |
126 | protected float m_rotation = 0f; | 126 | protected float m_rotation = 0f; |
127 | 127 | ||
@@ -184,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
184 | m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; | 184 | m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; |
185 | m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; | 185 | m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; |
186 | m_rotationCenter = options.ContainsKey("rotationCenter") ? (Vector3)options["rotationCenter"] | 186 | m_rotationCenter = options.ContainsKey("rotationCenter") ? (Vector3)options["rotationCenter"] |
187 | : new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f); | 187 | : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f); |
188 | 188 | ||
189 | // Zero can never be a valid user id | 189 | // Zero can never be a valid user id |
190 | m_validUserUuids[UUID.Zero] = false; | 190 | m_validUserUuids[UUID.Zero] = false; |
@@ -454,8 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
454 | // Reload serialized prims | 454 | // Reload serialized prims |
455 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); | 455 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); |
456 | 456 | ||
457 | float angle = (float)(m_rotation / 180.0 * Math.PI); | 457 | OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation); |
458 | OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, angle); | ||
459 | 458 | ||
460 | UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; | 459 | UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; |
461 | 460 | ||
@@ -483,16 +482,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
483 | // Happily this does not do much to the object since it hasn't been added to the scene yet | 482 | // Happily this does not do much to the object since it hasn't been added to the scene yet |
484 | if (sceneObject.AttachmentPoint == 0) | 483 | if (sceneObject.AttachmentPoint == 0) |
485 | { | 484 | { |
486 | if (angle != 0f) | 485 | if (m_displacement != Vector3.Zero || m_rotation != 0f) |
487 | { | 486 | { |
488 | sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation; | 487 | Vector3 pos = sceneObject.AbsolutePosition; |
489 | Vector3 offset = sceneObject.AbsolutePosition - m_rotationCenter; | 488 | if (m_rotation != 0f) |
490 | offset *= rot; | 489 | { |
491 | sceneObject.AbsolutePosition = m_rotationCenter + offset; | 490 | // Rotate the object |
492 | } | 491 | sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation; |
493 | if (m_displacement != Vector3.Zero) | 492 | // Get object position relative to rotation axis |
494 | { | 493 | Vector3 offset = pos - m_rotationCenter; |
495 | sceneObject.AbsolutePosition += m_displacement; | 494 | // Rotate the object position |
495 | offset *= rot; | ||
496 | // Restore the object position back to relative to the region | ||
497 | pos = m_rotationCenter + offset; | ||
498 | } | ||
499 | if (m_displacement != Vector3.Zero) | ||
500 | { | ||
501 | pos += m_displacement; | ||
502 | } | ||
503 | sceneObject.AbsolutePosition = pos; | ||
496 | } | 504 | } |
497 | } | 505 | } |
498 | 506 | ||
@@ -868,10 +876,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
868 | ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); | 876 | ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); |
869 | 877 | ||
870 | MemoryStream ms = new MemoryStream(data); | 878 | MemoryStream ms = new MemoryStream(data); |
871 | if (m_displacement != Vector3.Zero) | 879 | if (m_displacement != Vector3.Zero || m_rotation != 0f) |
872 | { | 880 | { |
873 | Vector2 terrainDisplacement = new Vector2(m_displacement.X, m_displacement.Y); | 881 | Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y); |
874 | terrainModule.LoadFromStream(terrainPath, terrainDisplacement, ms); | 882 | terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms); |
875 | } | 883 | } |
876 | else | 884 | else |
877 | { | 885 | { |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 2a6f1eb..6fbac4c 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 | |||
120 | { | 120 | { |
121 | displacement = v == null ? Vector3.Zero : Vector3.Parse(v); | 121 | displacement = v == null ? Vector3.Zero : Vector3.Parse(v); |
122 | } | 122 | } |
123 | catch (Exception e) | 123 | catch |
124 | { | 124 | { |
125 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement"); | 125 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement"); |
126 | displacement = new Vector3(0f, 0f, 0f); | 126 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\""); |
127 | return; | ||
127 | } | 128 | } |
128 | }); | 129 | }); |
129 | options.Add("rotation=", delegate (string v) { | 130 | options.Add("rotation=", delegate (string v) { |
130 | rotation = float.Parse(v); | 131 | try |
131 | rotation = Util.Clamp<float>(rotation, -359f, 359f); | 132 | { |
133 | rotation = v == null ? 0f : float.Parse(v); | ||
134 | } | ||
135 | catch | ||
136 | { | ||
137 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation"); | ||
138 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45"); | ||
139 | return; | ||
140 | } | ||
141 | // Convert to radians for internals | ||
142 | rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; | ||
132 | }); | 143 | }); |
133 | options.Add("rotationcenter=", delegate (string v) { | 144 | options.Add("rotationcenter=", delegate (string v) { |
134 | // RA 20130119: libomv's Vector2.Parse doesn't work. Need to use vector3 for the moment | 145 | try |
135 | rotationCenter = Vector3.Parse(v); | 146 | { |
147 | rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); | ||
148 | } | ||
149 | catch | ||
150 | { | ||
151 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement"); | ||
152 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotationcenter \"<128,128,0>\""); | ||
153 | return; | ||
154 | } | ||
136 | }); | 155 | }); |
137 | 156 | ||
138 | // Send a message to the region ready module | 157 | // 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 7bc5e88..08891d9 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 | |||
316 | 316 | ||
317 | public void LoadFromStream(string filename, Stream stream) | 317 | public void LoadFromStream(string filename, Stream stream) |
318 | { | 318 | { |
319 | Vector2 defaultDisplacement = new Vector2(0f, 0f); | 319 | LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream); |
320 | LoadFromStream(filename, defaultDisplacement, stream); | ||
321 | } | 320 | } |
322 | 321 | ||
323 | /// <summary> | 322 | /// <summary> |
@@ -325,7 +324,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
325 | /// </summary> | 324 | /// </summary> |
326 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> | 325 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> |
327 | /// <param name="stream"></param> | 326 | /// <param name="stream"></param> |
328 | public void LoadFromStream(string filename, Vector2 displacement, Stream stream) | 327 | public void LoadFromStream(string filename, Vector3 displacement, |
328 | float radianRotation, Vector2 rotationDisplacement, Stream stream) | ||
329 | { | 329 | { |
330 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 330 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
331 | { | 331 | { |
@@ -336,7 +336,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
336 | try | 336 | try |
337 | { | 337 | { |
338 | ITerrainChannel channel = loader.Value.LoadStream(stream); | 338 | ITerrainChannel channel = loader.Value.LoadStream(stream); |
339 | MergeTerrainIntoExisting(channel, displacement); | 339 | m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); |
340 | UpdateRevertMap(); | 340 | UpdateRevertMap(); |
341 | } | 341 | } |
342 | catch (NotImplementedException) | 342 | catch (NotImplementedException) |
@@ -356,33 +356,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
356 | throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); | 356 | throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); |
357 | } | 357 | } |
358 | 358 | ||
359 | private void MergeTerrainIntoExisting(ITerrainChannel channel, Vector2 displacement) | ||
360 | { | ||
361 | if (displacement == Vector2.Zero) | ||
362 | { | ||
363 | // If there is no displacement, just use this channel as the new heightmap | ||
364 | m_scene.Heightmap = channel; | ||
365 | m_channel = channel; | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | // If there is a displacement, we copy the loaded heightmap into the overall region | ||
370 | for (int xx = 0; xx < channel.Width; xx++) | ||
371 | { | ||
372 | for (int yy = 0; yy < channel.Height; yy++) | ||
373 | { | ||
374 | int dispX = xx + (int)displacement.X; | ||
375 | int dispY = yy + (int)displacement.Y; | ||
376 | if (dispX >= 0 && dispX < m_channel.Width | ||
377 | && dispY >= 0 && dispY < m_channel.Height) | ||
378 | { | ||
379 | m_channel[dispX, dispY] = channel[xx, yy]; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | |||
386 | private static Stream URIFetch(Uri uri) | 359 | private static Stream URIFetch(Uri uri) |
387 | { | 360 | { |
388 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); | 361 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); |
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs index 469bd31..f660b8d 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using OpenSim.Framework; | 28 | using OpenSim.Framework; |
29 | using OpenMetaverse; | ||
29 | 30 | ||
30 | namespace OpenSim.Region.Framework.Interfaces | 31 | namespace OpenSim.Region.Framework.Interfaces |
31 | { | 32 | { |
@@ -56,5 +57,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
56 | ITerrainChannel MakeCopy(); | 57 | ITerrainChannel MakeCopy(); |
57 | string SaveToXmlString(); | 58 | string SaveToXmlString(); |
58 | void LoadFromXmlString(string data); | 59 | void LoadFromXmlString(string data); |
60 | // Merge some terrain into this channel | ||
61 | void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement); | ||
59 | } | 62 | } |
60 | } | 63 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 189a30a..a6f5d98 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | |||
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
51 | /// </param> | 51 | /// </param> |
52 | /// <param name="stream"></param> | 52 | /// <param name="stream"></param> |
53 | void LoadFromStream(string filename, Stream stream); | 53 | void LoadFromStream(string filename, Stream stream); |
54 | void LoadFromStream(string filename, Vector2 displacement, Stream stream); | 54 | void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream); |
55 | void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); | 55 | void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); |
56 | /// <summary> | 56 | /// <summary> |
57 | /// Save a terrain to a stream. | 57 | /// Save a terrain to a stream. |
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs index b4b1823..24709dc 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs | |||
@@ -36,6 +36,8 @@ using OpenSim.Data; | |||
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
38 | 38 | ||
39 | using OpenMetaverse; | ||
40 | |||
39 | using log4net; | 41 | using log4net; |
40 | 42 | ||
41 | namespace OpenSim.Region.Framework.Scenes | 43 | namespace OpenSim.Region.Framework.Scenes |
@@ -212,6 +214,76 @@ namespace OpenSim.Region.Framework.Scenes | |||
212 | sr.Close(); | 214 | sr.Close(); |
213 | } | 215 | } |
214 | 216 | ||
217 | // ITerrainChannel.Merge | ||
218 | public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement) | ||
219 | { | ||
220 | for (int xx = 0; xx < newTerrain.Width; xx++) | ||
221 | { | ||
222 | for (int yy = 0; yy < newTerrain.Height; yy++) | ||
223 | { | ||
224 | int dispX = (int)displacement.X; | ||
225 | int dispY = (int)displacement.Y; | ||
226 | float newHeight = (float)newTerrain[xx, yy] + displacement.Z; | ||
227 | if (radianRotation == 0) | ||
228 | { | ||
229 | // If no rotation, place the new height in the specified location | ||
230 | dispX += xx; | ||
231 | dispY += yy; | ||
232 | if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY) | ||
233 | { | ||
234 | m_terrainData[dispX, dispY] = newHeight; | ||
235 | } | ||
236 | } | ||
237 | else | ||
238 | { | ||
239 | // If rotating, we have to smooth the result because the conversion | ||
240 | // to ints will mean heightmap entries will not get changed | ||
241 | // First compute the rotation location for the new height. | ||
242 | dispX += (int)(rotationDisplacement.X | ||
243 | + ((float)xx - rotationDisplacement.X) * Math.Cos(radianRotation) | ||
244 | - ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) ); | ||
245 | |||
246 | dispY += (int)(rotationDisplacement.Y | ||
247 | + ((float)xx - rotationDisplacement.X) * Math.Sin(radianRotation) | ||
248 | + ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) ); | ||
249 | |||
250 | if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY) | ||
251 | { | ||
252 | float oldHeight = m_terrainData[dispX, dispY]; | ||
253 | // Smooth the heights around this location if the old height is far from this one | ||
254 | for (int sxx = dispX - 2; sxx < dispX + 2; sxx++) | ||
255 | { | ||
256 | for (int syy = dispY - 2; syy < dispY + 2; syy++) | ||
257 | { | ||
258 | if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY) | ||
259 | { | ||
260 | if (sxx == dispX && syy == dispY) | ||
261 | { | ||
262 | // Set height for the exact rotated point | ||
263 | m_terrainData[dispX, dispY] = newHeight; | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f) | ||
268 | { | ||
269 | // If the adjacent height is far off, force it to this height | ||
270 | m_terrainData[sxx, syy] = newHeight; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY) | ||
279 | { | ||
280 | m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy]; | ||
281 | } | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
215 | #endregion | 287 | #endregion |
216 | 288 | ||
217 | public TerrainChannel Copy() | 289 | public TerrainChannel Copy() |