diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index fd30c46..7bc5e88 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | |||
@@ -30,10 +30,14 @@ using System.Collections.Generic; | |||
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Net; | 32 | using System.Net; |
33 | |||
33 | using log4net; | 34 | using log4net; |
34 | using Nini.Config; | 35 | using Nini.Config; |
36 | |||
35 | using OpenMetaverse; | 37 | using OpenMetaverse; |
36 | using Mono.Addins; | 38 | using Mono.Addins; |
39 | |||
40 | using OpenSim.Data; | ||
37 | using OpenSim.Framework; | 41 | using OpenSim.Framework; |
38 | using OpenSim.Region.CoreModules.Framework.InterfaceCommander; | 42 | using OpenSim.Region.CoreModules.Framework.InterfaceCommander; |
39 | using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; | 43 | using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; |
@@ -70,6 +74,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
70 | #endregion | 74 | #endregion |
71 | 75 | ||
72 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 76 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
77 | private static readonly string LogHeader = "[TERRAIN MODULE]"; | ||
73 | 78 | ||
74 | private readonly Commander m_commander = new Commander("terrain"); | 79 | private readonly Commander m_commander = new Commander("terrain"); |
75 | 80 | ||
@@ -130,15 +135,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
130 | { | 135 | { |
131 | if (m_scene.Heightmap == null) | 136 | if (m_scene.Heightmap == null) |
132 | { | 137 | { |
133 | m_channel = new TerrainChannel(m_InitialTerrain); | 138 | m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX, |
139 | (int)m_scene.RegionInfo.RegionSizeY, | ||
140 | (int)m_scene.RegionInfo.RegionSizeZ); | ||
134 | m_scene.Heightmap = m_channel; | 141 | m_scene.Heightmap = m_channel; |
135 | m_revert = new TerrainChannel(); | ||
136 | UpdateRevertMap(); | 142 | UpdateRevertMap(); |
137 | } | 143 | } |
138 | else | 144 | else |
139 | { | 145 | { |
140 | m_channel = m_scene.Heightmap; | 146 | m_channel = m_scene.Heightmap; |
141 | m_revert = new TerrainChannel(); | ||
142 | UpdateRevertMap(); | 147 | UpdateRevertMap(); |
143 | } | 148 | } |
144 | 149 | ||
@@ -230,11 +235,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
230 | try | 235 | try |
231 | { | 236 | { |
232 | ITerrainChannel channel = loader.Value.LoadFile(filename); | 237 | ITerrainChannel channel = loader.Value.LoadFile(filename); |
233 | if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize) | 238 | if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY) |
234 | { | 239 | { |
235 | // TerrainChannel expects a RegionSize x RegionSize map, currently | 240 | // TerrainChannel expects a RegionSize x RegionSize map, currently |
236 | throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", | 241 | throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", |
237 | Constants.RegionSize, Constants.RegionSize)); | 242 | m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY)); |
238 | } | 243 | } |
239 | m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); | 244 | m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); |
240 | m_scene.Heightmap = channel; | 245 | m_scene.Heightmap = channel; |
@@ -309,12 +314,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
309 | LoadFromStream(filename, URIFetch(pathToTerrainHeightmap)); | 314 | LoadFromStream(filename, URIFetch(pathToTerrainHeightmap)); |
310 | } | 315 | } |
311 | 316 | ||
317 | public void LoadFromStream(string filename, Stream stream) | ||
318 | { | ||
319 | Vector2 defaultDisplacement = new Vector2(0f, 0f); | ||
320 | LoadFromStream(filename, defaultDisplacement, stream); | ||
321 | } | ||
322 | |||
312 | /// <summary> | 323 | /// <summary> |
313 | /// Loads a terrain file from a stream and installs it in the scene. | 324 | /// Loads a terrain file from a stream and installs it in the scene. |
314 | /// </summary> | 325 | /// </summary> |
315 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> | 326 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> |
316 | /// <param name="stream"></param> | 327 | /// <param name="stream"></param> |
317 | public void LoadFromStream(string filename, Stream stream) | 328 | public void LoadFromStream(string filename, Vector2 displacement, Stream stream) |
318 | { | 329 | { |
319 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 330 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
320 | { | 331 | { |
@@ -325,8 +336,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
325 | try | 336 | try |
326 | { | 337 | { |
327 | ITerrainChannel channel = loader.Value.LoadStream(stream); | 338 | ITerrainChannel channel = loader.Value.LoadStream(stream); |
328 | m_scene.Heightmap = channel; | 339 | MergeTerrainIntoExisting(channel, displacement); |
329 | m_channel = channel; | ||
330 | UpdateRevertMap(); | 340 | UpdateRevertMap(); |
331 | } | 341 | } |
332 | catch (NotImplementedException) | 342 | catch (NotImplementedException) |
@@ -346,6 +356,33 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
346 | 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)); |
347 | } | 357 | } |
348 | 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 | |||
349 | private static Stream URIFetch(Uri uri) | 386 | private static Stream URIFetch(Uri uri) |
350 | { | 387 | { |
351 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); | 388 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); |
@@ -532,6 +569,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
532 | /// </summary> | 569 | /// </summary> |
533 | public void UpdateRevertMap() | 570 | public void UpdateRevertMap() |
534 | { | 571 | { |
572 | /* | ||
535 | int x; | 573 | int x; |
536 | for (x = 0; x < m_channel.Width; x++) | 574 | for (x = 0; x < m_channel.Width; x++) |
537 | { | 575 | { |
@@ -541,6 +579,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
541 | m_revert[x, y] = m_channel[x, y]; | 579 | m_revert[x, y] = m_channel[x, y]; |
542 | } | 580 | } |
543 | } | 581 | } |
582 | */ | ||
583 | m_revert = m_channel.MakeCopy(); | ||
544 | } | 584 | } |
545 | 585 | ||
546 | /// <summary> | 586 | /// <summary> |
@@ -567,8 +607,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
567 | { | 607 | { |
568 | ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, | 608 | ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, |
569 | fileWidth, fileHeight, | 609 | fileWidth, fileHeight, |
570 | (int) Constants.RegionSize, | 610 | (int) m_scene.RegionInfo.RegionSizeX, |
571 | (int) Constants.RegionSize); | 611 | (int) m_scene.RegionInfo.RegionSizeY); |
572 | m_scene.Heightmap = channel; | 612 | m_scene.Heightmap = channel; |
573 | m_channel = channel; | 613 | m_channel = channel; |
574 | UpdateRevertMap(); | 614 | UpdateRevertMap(); |
@@ -615,8 +655,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
615 | { | 655 | { |
616 | loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, | 656 | loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, |
617 | fileWidth, fileHeight, | 657 | fileWidth, fileHeight, |
618 | (int)Constants.RegionSize, | 658 | (int)m_scene.RegionInfo.RegionSizeX, |
619 | (int)Constants.RegionSize); | 659 | (int)m_scene.RegionInfo.RegionSizeY); |
620 | 660 | ||
621 | MainConsole.Instance.OutputFormat( | 661 | MainConsole.Instance.OutputFormat( |
622 | "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}", | 662 | "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}", |
@@ -705,7 +745,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
705 | private void CheckForTerrainUpdates(bool respectEstateSettings) | 745 | private void CheckForTerrainUpdates(bool respectEstateSettings) |
706 | { | 746 | { |
707 | bool shouldTaint = false; | 747 | bool shouldTaint = false; |
708 | float[] serialised = m_channel.GetFloatsSerialised(); | 748 | float[] terrHeights = m_channel.GetFloatsSerialised(); |
709 | int x; | 749 | int x; |
710 | for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) | 750 | for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) |
711 | { | 751 | { |
@@ -714,16 +754,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
714 | { | 754 | { |
715 | if (m_channel.Tainted(x, y)) | 755 | if (m_channel.Tainted(x, y)) |
716 | { | 756 | { |
717 | // if we should respect the estate settings then | 757 | // If we should respect the estate settings then |
718 | // fixup and height deltas that don't respect them | 758 | // fixup and height deltas that don't respect them. |
759 | // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. | ||
719 | if (respectEstateSettings && LimitChannelChanges(x, y)) | 760 | if (respectEstateSettings && LimitChannelChanges(x, y)) |
720 | { | 761 | { |
721 | // this has been vetoed, so update | 762 | // Terrain heights were modified. Refetch the terrain info. |
722 | // what we are going to send to the client | 763 | terrHeights = m_channel.GetFloatsSerialised(); |
723 | serialised = m_channel.GetFloatsSerialised(); | ||
724 | } | 764 | } |
725 | 765 | ||
726 | SendToClients(serialised, x, y); | 766 | // m_log.DebugFormat("{0} Patch modified. Sending (x,y) = ({1},{2})", LogHeader, x, y); |
767 | SendToClients(terrHeights, x, y); | ||
727 | shouldTaint = true; | 768 | shouldTaint = true; |
728 | } | 769 | } |
729 | } | 770 | } |
@@ -792,13 +833,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
792 | /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> | 833 | /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> |
793 | /// <param name="x">The patch corner to send</param> | 834 | /// <param name="x">The patch corner to send</param> |
794 | /// <param name="y">The patch corner to send</param> | 835 | /// <param name="y">The patch corner to send</param> |
795 | private void SendToClients(float[] serialised, int x, int y) | 836 | private void SendToClients(float[] heightMap, int x, int y) |
796 | { | 837 | { |
797 | m_scene.ForEachClient( | 838 | m_scene.ForEachClient( |
798 | delegate(IClientAPI controller) | 839 | delegate(IClientAPI controller) |
799 | { controller.SendLayerData( | 840 | { controller.SendLayerData( x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); } |
800 | x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised); | ||
801 | } | ||
802 | ); | 841 | ); |
803 | } | 842 | } |
804 | 843 | ||
@@ -984,28 +1023,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
984 | 1023 | ||
985 | if (direction.ToLower().StartsWith("y")) | 1024 | if (direction.ToLower().StartsWith("y")) |
986 | { | 1025 | { |
987 | for (int x = 0; x < Constants.RegionSize; x++) | 1026 | for (int x = 0; x < m_channel.Width; x++) |
988 | { | 1027 | { |
989 | for (int y = 0; y < Constants.RegionSize / 2; y++) | 1028 | for (int y = 0; y < m_channel.Height / 2; y++) |
990 | { | 1029 | { |
991 | double height = m_channel[x, y]; | 1030 | double height = m_channel[x, y]; |
992 | double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y]; | 1031 | double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; |
993 | m_channel[x, y] = flippedHeight; | 1032 | m_channel[x, y] = flippedHeight; |
994 | m_channel[x, (int)Constants.RegionSize - 1 - y] = height; | 1033 | m_channel[x, (int)m_channel.Height - 1 - y] = height; |
995 | 1034 | ||
996 | } | 1035 | } |
997 | } | 1036 | } |
998 | } | 1037 | } |
999 | else if (direction.ToLower().StartsWith("x")) | 1038 | else if (direction.ToLower().StartsWith("x")) |
1000 | { | 1039 | { |
1001 | for (int y = 0; y < Constants.RegionSize; y++) | 1040 | for (int y = 0; y < m_channel.Height; y++) |
1002 | { | 1041 | { |
1003 | for (int x = 0; x < Constants.RegionSize / 2; x++) | 1042 | for (int x = 0; x < m_channel.Width / 2; x++) |
1004 | { | 1043 | { |
1005 | double height = m_channel[x, y]; | 1044 | double height = m_channel[x, y]; |
1006 | double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y]; | 1045 | double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; |
1007 | m_channel[x, y] = flippedHeight; | 1046 | m_channel[x, y] = flippedHeight; |
1008 | m_channel[(int)Constants.RegionSize - 1 - x, y] = height; | 1047 | m_channel[(int)m_channel.Width - 1 - x, y] = height; |
1009 | 1048 | ||
1010 | } | 1049 | } |
1011 | } | 1050 | } |