aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorRobert Adams2013-10-02 16:59:37 -0700
committerRobert Adams2013-10-07 13:57:40 -0700
commit7416809077227f35ab70ed44060e51f2bcf66937 (patch)
tree7578cbfed07777d5c60af986791dc7d8b09b2cd5 /OpenSim/Region
parentvarregion: remove scattered use of Constants.RegionSize by having routines re... (diff)
downloadopensim-SC_OLD-7416809077227f35ab70ed44060e51f2bcf66937.zip
opensim-SC_OLD-7416809077227f35ab70ed44060e51f2bcf66937.tar.gz
opensim-SC_OLD-7416809077227f35ab70ed44060e51f2bcf66937.tar.bz2
opensim-SC_OLD-7416809077227f35ab70ed44060e51f2bcf66937.tar.xz
varregion: plug in TerrainData class and modify TerrainModule and LLClientView to use same. This passes a terrain info class around rather than passing a one dimensional array thus allowing variable regions. Update the database storage for variable region sizes. This should be downward compatible (same format for 256x256 regions).
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs69
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs29
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs145
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs59
7 files changed, 126 insertions, 210 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index fea9ddf..7984acc 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -34,11 +34,13 @@ using System.Text;
34using System.Threading; 34using System.Threading;
35using System.Timers; 35using System.Timers;
36using System.Xml; 36using System.Xml;
37
37using log4net; 38using log4net;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
40using OpenMetaverse.Messages.Linden; 41using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43
42using OpenSim.Framework; 44using OpenSim.Framework;
43using OpenSim.Framework.Client; 45using OpenSim.Framework.Client;
44using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 50using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 51using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags; 52using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config;
52 53
53using System.IO; 54using System.IO;
54using PermissionMask = OpenSim.Framework.PermissionMask; 55using PermissionMask = OpenSim.Framework.PermissionMask;
@@ -307,6 +308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
307 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; 308 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
308 309
309 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 310 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
311 private static string LogHeader = "[LLCLIENTVIEW]";
310 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients 312 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
311 313
312 /// <summary> 314 /// <summary>
@@ -447,7 +449,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 449
448// ~LLClientView() 450// ~LLClientView()
449// { 451// {
450// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); 452// m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode);
451// } 453// }
452 454
453 /// <summary> 455 /// <summary>
@@ -513,9 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 // there is some unidentified connection problem, not where we have issues due to deadlock 515 // there is some unidentified connection problem, not where we have issues due to deadlock
514 if (!IsActive && !force) 516 if (!IsActive && !force)
515 { 517 {
516 m_log.DebugFormat( 518 m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set",
517 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", 519 LogHeader, Name, m_scene.Name);
518 Name, m_scene.Name);
519 520
520 return; 521 return;
521 } 522 }
@@ -1162,10 +1163,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1162 /// <param name="o"></param> 1163 /// <param name="o"></param>
1163 private void DoSendLayerData(object o) 1164 private void DoSendLayerData(object o)
1164 { 1165 {
1165 float[] map = LLHeightFieldMoronize((float[])o); 1166 float[] map = (float[])o;
1166 1167
1167 try 1168 try
1168 { 1169 {
1170 // Send LayerData in typerwriter pattern
1169 //for (int y = 0; y < 16; y++) 1171 //for (int y = 0; y < 16; y++)
1170 //{ 1172 //{
1171 // for (int x = 0; x < 16; x++) 1173 // for (int x = 0; x < 16; x++)
@@ -1230,7 +1232,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1230 // } 1232 // }
1231 1233
1232 /// <summary> 1234 /// <summary>
1233 /// Sends a specified patch to a client 1235 /// Sends a terrain packet for the point specified.
1236 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1237 /// We just use the terrain from the region we know about.
1234 /// </summary> 1238 /// </summary>
1235 /// <param name="px">Patch coordinate (x) 0..15</param> 1239 /// <param name="px">Patch coordinate (x) 0..15</param>
1236 /// <param name="py">Patch coordinate (y) 0..15</param> 1240 /// <param name="py">Patch coordinate (y) 0..15</param>
@@ -1239,10 +1243,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1239 { 1243 {
1240 try 1244 try
1241 { 1245 {
1242 int[] patches = new int[] { py * 16 + px }; 1246 // For unknown reasons, after this point, patch numbers are swapped X for y.
1243 float[] heightmap = (map.Length == 65536) ? map : LLHeightFieldMoronize(map); 1247 // That means, that for <patchNumX, patchNumY, the array location is computed as map[patchNumY * 16 + patchNumX].
1244 1248 // TODO: someday straighten the below implementation to keep the X row order for patch numbers.
1245 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1249 // Since this is passing only one patch, we just swap the patch numbers.
1250 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(m_scene.Heightmap.GetTerrainData(), px, py);
1246 1251
1247 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. 1252 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1248 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. 1253 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
@@ -1260,14 +1265,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1260 if (m_justEditedTerrain) 1265 if (m_justEditedTerrain)
1261 { 1266 {
1262 layerpack.Header.Reliable = false; 1267 layerpack.Header.Reliable = false;
1263 OutPacket(layerpack, 1268 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1264 ThrottleOutPacketType.Unknown );
1265 } 1269 }
1266 else 1270 else
1267 { 1271 {
1268 layerpack.Header.Reliable = true; 1272 layerpack.Header.Reliable = true;
1269 OutPacket(layerpack, 1273 OutPacket(layerpack, ThrottleOutPacketType.Land);
1270 ThrottleOutPacketType.Land);
1271 } 1274 }
1272 } 1275 }
1273 catch (Exception e) 1276 catch (Exception e)
@@ -1277,38 +1280,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1277 } 1280 }
1278 1281
1279 /// <summary> 1282 /// <summary>
1280 /// Munges heightfield into the LLUDP backed in restricted heightfield.
1281 /// </summary>
1282 /// <param name="map">float array in the base; Constants.RegionSize</param>
1283 /// <returns>float array in the base 256</returns>
1284 internal float[] LLHeightFieldMoronize(float[] map)
1285 {
1286 if (map.Length == 65536)
1287 return map;
1288 else
1289 {
1290 float[] returnmap = new float[65536];
1291
1292 if (map.Length < 65535)
1293 {
1294 // rebase the vector stride to 256
1295 for (int i = 0; i < Constants.RegionSize; i++)
1296 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
1297 }
1298 else
1299 {
1300 for (int i = 0; i < 256; i++)
1301 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
1302 }
1303
1304 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
1305
1306 return returnmap;
1307 }
1308
1309 }
1310
1311 /// <summary>
1312 /// Send the wind matrix to the client 1283 /// Send the wind matrix to the client
1313 /// </summary> 1284 /// </summary>
1314 /// <param name="windSpeeds">16x16 array of wind speeds</param> 1285 /// <param name="windSpeeds">16x16 array of wind speeds</param>
@@ -2780,8 +2751,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2780 { 2751 {
2781 if (req.AssetInf.Data == null) 2752 if (req.AssetInf.Data == null)
2782 { 2753 {
2783 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", 2754 m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null",
2784 req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2755 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2785 return; 2756 return;
2786 } 2757 }
2787 2758
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 2fff4c1..eb6187b 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;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Net; 32using System.Net;
33
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
36
35using OpenMetaverse; 37using OpenMetaverse;
36using Mono.Addins; 38using Mono.Addins;
39
40using OpenSim.Data;
37using OpenSim.Framework; 41using OpenSim.Framework;
38using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
39using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; 43using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
@@ -130,8 +134,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
130 { 134 {
131 if (m_scene.Heightmap == null) 135 if (m_scene.Heightmap == null)
132 { 136 {
133 m_channel = new TerrainChannel(m_InitialTerrain, 137 m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
134 m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY, m_scene.RegionInfo.RegionSizeZ); 138 (int)m_scene.RegionInfo.RegionSizeY,
139 (int)m_scene.RegionInfo.RegionSizeZ);
135 m_scene.Heightmap = m_channel; 140 m_scene.Heightmap = m_channel;
136 UpdateRevertMap(); 141 UpdateRevertMap();
137 } 142 }
@@ -707,7 +712,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
707 private void CheckForTerrainUpdates(bool respectEstateSettings) 712 private void CheckForTerrainUpdates(bool respectEstateSettings)
708 { 713 {
709 bool shouldTaint = false; 714 bool shouldTaint = false;
710 float[] serialised = m_channel.GetFloatsSerialised(); 715 float[] terrData = m_channel.GetFloatsSerialised();
711 int x; 716 int x;
712 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) 717 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
713 { 718 {
@@ -716,16 +721,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
716 { 721 {
717 if (m_channel.Tainted(x, y)) 722 if (m_channel.Tainted(x, y))
718 { 723 {
719 // if we should respect the estate settings then 724 // If we should respect the estate settings then
720 // fixup and height deltas that don't respect them 725 // fixup and height deltas that don't respect them.
726 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
721 if (respectEstateSettings && LimitChannelChanges(x, y)) 727 if (respectEstateSettings && LimitChannelChanges(x, y))
722 { 728 {
723 // this has been vetoed, so update 729 // Terrain heights were modified. Refetch the terrain info.
724 // what we are going to send to the client 730 terrData = m_channel.GetFloatsSerialised();
725 serialised = m_channel.GetFloatsSerialised();
726 } 731 }
727 732
728 SendToClients(serialised, x, y); 733 SendToClients(terrData, x, y);
729 shouldTaint = true; 734 shouldTaint = true;
730 } 735 }
731 } 736 }
@@ -794,13 +799,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
794 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> 799 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
795 /// <param name="x">The patch corner to send</param> 800 /// <param name="x">The patch corner to send</param>
796 /// <param name="y">The patch corner to send</param> 801 /// <param name="y">The patch corner to send</param>
797 private void SendToClients(float[] serialised, int x, int y) 802 private void SendToClients(float[] heightMap, int x, int y)
798 { 803 {
799 m_scene.ForEachClient( 804 m_scene.ForEachClient(
800 delegate(IClientAPI controller) 805 delegate(IClientAPI controller)
801 { controller.SendLayerData( 806 { controller.SendLayerData( x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); }
802 x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
803 }
804 ); 807 );
805 } 808 }
806 809
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 847d245..5ba5b31 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -136,24 +136,4 @@ namespace OpenSim.Region.Framework.Interfaces
136 void Shutdown(); 136 void Shutdown();
137 } 137 }
138 138
139 // The terrain is stored as a blob in the database with a 'revision' field.
140 // Some implementations of terrain storage would fill the revision field with
141 // the time the terrain was stored. When real revisions were added and this
142 // feature removed, that left some old entries with the time in the revision
143 // field.
144 // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
145 // left over and it is presumed to be 'Legacy256'.
146 // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
147 // If a revision does not match any of these, it is assumed to be Legacy256.
148 public enum DBTerrainRevision
149 {
150 // Terrain is 'double[256,256]'
151 Legacy256 = 11,
152 // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions
153 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
154 Variable2D = 22,
155 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
156 RevisionHigh = 1234
157 }
158
159} 139}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index 3c060a4..cc8a236 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,6 +25,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenSim.Framework;
29
28namespace OpenSim.Region.Framework.Interfaces 30namespace OpenSim.Region.Framework.Interfaces
29{ 31{
30 public interface ITerrainChannel 32 public interface ITerrainChannel
@@ -35,18 +37,20 @@ namespace OpenSim.Region.Framework.Interfaces
35 37
36 double this[int x, int y] { get; set; } 38 double this[int x, int y] { get; set; }
37 39
40 // Return the packaged terrain data for passing into lower levels of communication
41 TerrainData GetTerrainData();
42
38 /// <summary> 43 /// <summary>
39 /// Squash the entire heightmap into a single dimensioned array 44 /// Squash the entire heightmap into a single dimensioned array
40 /// </summary> 45 /// </summary>
41 /// <returns></returns> 46 /// <returns></returns>
42 float[] GetFloatsSerialised(); 47 float[] GetFloatsSerialised();
43 // Get version of map as a single dimensioned array and each value compressed
44 // into an int (compressedHeight = (int)(floatHeight * Constants.TerrainCompression);)
45 // This is done to make the map smaller as it can get pretty larger for variable sized regions.
46 short[] GetCompressedMap();
47 48
48 double[,] GetDoubles(); 49 double[,] GetDoubles();
50
51 // Check if a location has been updated. Clears the taint flag as a side effect.
49 bool Tainted(int x, int y); 52 bool Tainted(int x, int y);
53
50 ITerrainChannel MakeCopy(); 54 ITerrainChannel MakeCopy();
51 string SaveToXmlString(); 55 string SaveToXmlString();
52 void LoadFromXmlString(string data); 56 void LoadFromXmlString(string data);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 49e32c6..e2880e3 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1905,7 +1905,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1906 1906
1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1908 Heightmap = new TerrainChannel(m_InitialTerrain, RegionInfo.RegionSizeX, RegionInfo.RegionSizeY, RegionInfo.RegionSizeZ); 1908 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1909 1909
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1911 }
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index fef93bf..65e890f 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -25,14 +25,19 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenSim.Framework;
29using OpenSim.Region.Framework.Interfaces;
30using System; 28using System;
29using System.IO;
31using System.Text; 30using System.Text;
31using System.Reflection;
32using System.Xml; 32using System.Xml;
33using System.IO;
34using System.Xml.Serialization; 33using System.Xml.Serialization;
35 34
35using OpenSim.Data;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38
39using log4net;
40
36namespace OpenSim.Region.Framework.Scenes 41namespace OpenSim.Region.Framework.Scenes
37{ 42{
38 /// <summary> 43 /// <summary>
@@ -40,18 +45,20 @@ namespace OpenSim.Region.Framework.Scenes
40 /// </summary> 45 /// </summary>
41 public class TerrainChannel : ITerrainChannel 46 public class TerrainChannel : ITerrainChannel
42 { 47 {
43 protected bool[,] m_taint; 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 protected short[] m_map; 49 private static string LogHeader = "[TERRAIN CHANNEL]";
45 50
46 public int Width { get; private set; } // X dimension 51 protected TerrainData m_terrainData;
52
53 public int Width { get { return m_terrainData.SizeX; } } // X dimension
47 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y 54 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
48 public int Height { get; private set; } // Y dimension 55 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
49 public int Altitude { get; private set; } // Y dimension 56 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
50 57
51 // Default, not-often-used builder 58 // Default, not-often-used builder
52 public TerrainChannel() 59 public TerrainChannel()
53 { 60 {
54 InitializeStructures(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight, false); 61 m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
55 FlatLand(); 62 FlatLand();
56 // PinHeadIsland(); 63 // PinHeadIsland();
57 } 64 }
@@ -59,27 +66,23 @@ namespace OpenSim.Region.Framework.Scenes
59 // Create terrain of given size 66 // Create terrain of given size
60 public TerrainChannel(int pX, int pY) 67 public TerrainChannel(int pX, int pY)
61 { 68 {
62 InitializeStructures((uint)pX, (uint)pY, Constants.RegionHeight, true); 69 m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
63 } 70 }
64 71
65 // Create terrain of specified size and initialize with specified terrain. 72 // Create terrain of specified size and initialize with specified terrain.
66 // TODO: join this with the terrain initializers. 73 // TODO: join this with the terrain initializers.
67 public TerrainChannel(String type, uint pX, uint pY, uint pZ) 74 public TerrainChannel(String type, int pX, int pY, int pZ)
68 { 75 {
69 InitializeStructures(pX, pY, pZ, false); 76 m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
70 if (type.Equals("flat")) 77 if (type.Equals("flat"))
71 FlatLand(); 78 FlatLand();
72 else 79 else
73 PinHeadIsland(); 80 PinHeadIsland();
74 } 81 }
75 82
76 public TerrainChannel(double[,] pM, uint pH) 83 public TerrainChannel(double[,] pM, uint pAltitude)
77 { 84 {
78 InitializeStructures((uint)pM.GetLength(0), (uint)pM.GetLength(1), pH, false); 85 m_terrainData = new HeightmapTerrainData(pM);
79 int idx = 0;
80 for (int ii = 0; ii < Height; ii++)
81 for (int jj = 0; jj < Width; jj++)
82 m_map[idx++] = ToCompressedHeight(pM[ii, jj]);
83 } 86 }
84 87
85 #region ITerrainChannel Members 88 #region ITerrainChannel Members
@@ -90,20 +93,23 @@ namespace OpenSim.Region.Framework.Scenes
90 return this.Copy(); 93 return this.Copy();
91 } 94 }
92 95
93 // ITerrainChannel.GetCompressedMap() 96 // ITerrainChannel.GetTerrainData()
94 public short[] GetCompressedMap() 97 public TerrainData GetTerrainData()
95 { 98 {
96 return m_map; 99 return m_terrainData;
97 } 100 }
98 101
99 // ITerrainChannel.GetFloatsSerialized() 102 // ITerrainChannel.GetFloatsSerialized()
103 // NOTICE that the one dimensional form is ordered by Y!!
100 public float[] GetFloatsSerialised() 104 public float[] GetFloatsSerialised()
101 { 105 {
102 int points = Width * Height; 106 int points = Width * Height;
103 float[] heights = new float[points]; 107 float[] heights = new float[points];
104 108
105 for (int ii = 0; ii < points; ii++) 109 int idx = 0;
106 heights[ii] = FromCompressedHeight(m_map[ii]); 110 for (int ii = 0; ii < Height; ii++)
111 for (int jj = 0; jj < Width; jj++)
112 heights[idx++] = m_terrainData[jj, ii];
107 113
108 return heights; 114 return heights;
109 } 115 }
@@ -116,11 +122,11 @@ namespace OpenSim.Region.Framework.Scenes
116 double[,] heights = new double[w, l]; 122 double[,] heights = new double[w, l];
117 123
118 int idx = 0; // index into serialized array 124 int idx = 0; // index into serialized array
119 for (int ii = 0; ii < l; ii++) 125 for (int ii = 0; ii < w; ii++)
120 { 126 {
121 for (int jj = 0; jj < w; jj++) 127 for (int jj = 0; jj < l; jj++)
122 { 128 {
123 heights[ii, jj] = (double)FromCompressedHeight(m_map[idx]); 129 heights[ii, jj] = (double)m_terrainData[ii, jj];
124 idx++; 130 idx++;
125 } 131 }
126 } 132 }
@@ -131,31 +137,20 @@ namespace OpenSim.Region.Framework.Scenes
131 // ITerrainChannel.this[x,y] 137 // ITerrainChannel.this[x,y]
132 public double this[int x, int y] 138 public double this[int x, int y]
133 { 139 {
134 get { return m_map[x * Width + y]; } 140 get { return (double)m_terrainData[x, y]; }
135 set 141 set
136 { 142 {
137 // Will "fix" terrain hole problems. Although not fantastically.
138 if (Double.IsNaN(value) || Double.IsInfinity(value)) 143 if (Double.IsNaN(value) || Double.IsInfinity(value))
139 return; 144 return;
140 145
141 int idx = x * Width + y; 146 m_terrainData[x, y] = (float)value;
142 if (m_map[idx] != value)
143 {
144 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
145 m_map[idx] = ToCompressedHeight(value);
146 }
147 } 147 }
148 } 148 }
149 149
150 // ITerrainChannel.Tainted() 150 // ITerrainChannel.Tainted()
151 public bool Tainted(int x, int y) 151 public bool Tainted(int x, int y)
152 { 152 {
153 if (m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize]) 153 return m_terrainData.IsTaintedAt(x, y);
154 {
155 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = false;
156 return true;
157 }
158 return false;
159 } 154 }
160 155
161 // ITerrainChannel.SaveToXmlString() 156 // ITerrainChannel.SaveToXmlString()
@@ -188,49 +183,25 @@ namespace OpenSim.Region.Framework.Scenes
188 183
189 #endregion 184 #endregion
190 185
191 private void InitializeStructures(uint pX, uint pY, uint pZ, bool shouldInitializeHeightmap) 186 /*
192 {
193 Width = (int)pX;
194 Height = (int)pY;
195 Altitude = (int)pZ;
196 m_map = new short[Width * Height];
197 m_taint = new bool[Width / Constants.TerrainPatchSize, Height / Constants.TerrainPatchSize];
198 ClearTaint();
199 if (shouldInitializeHeightmap)
200 {
201 FlatLand();
202 }
203 }
204
205 public void ClearTaint()
206 {
207 for (int ii = 0; ii < Width / Constants.TerrainPatchSize; ii++)
208 for (int jj = 0; jj < Height / Constants.TerrainPatchSize; jj++)
209 m_taint[ii, jj] = false;
210 }
211
212 // To save space (especially for large regions), keep the height as a short integer 187 // To save space (especially for large regions), keep the height as a short integer
213 // that is coded as the float height times the compression factor (usually '100' 188 // that is coded as the float height times the compression factor (usually '100'
214 // to make for two decimal points). 189 // to make for two decimal points).
215 public short ToCompressedHeight(double pHeight) 190 public static short ToCompressedHeight(double pHeight)
216 { 191 {
217 return (short)(pHeight * Constants.TerrainCompression); 192 return (short)(pHeight * Constants.TerrainCompression);
218 } 193 }
219 194
220 public float FromCompressedHeight(short pHeight) 195 public static float FromCompressedHeight(short pHeight)
221 { 196 {
222 return ((float)pHeight) / Constants.TerrainCompression; 197 return ((float)pHeight) / Constants.TerrainCompression;
223 } 198 }
199 */
224 200
225 public TerrainChannel Copy() 201 public TerrainChannel Copy()
226 { 202 {
227 TerrainChannel copy = new TerrainChannel(); 203 TerrainChannel copy = new TerrainChannel();
228 copy.m_map = (short[])m_map.Clone(); 204 copy.m_terrainData = m_terrainData.Clone();
229 copy.m_taint = (bool[,])m_taint.Clone();
230 copy.Width = Width;
231 copy.Height = Height;
232 copy.Altitude = Altitude;
233
234 return copy; 205 return copy;
235 } 206 }
236 207
@@ -289,6 +260,8 @@ namespace OpenSim.Region.Framework.Scenes
289 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader); 260 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
290 int index = 0; 261 int index = 0;
291 262
263 m_terrainData = new HeightmapTerrainData(Width, Height, Altitude);
264
292 for (int y = 0; y < Height; y++) 265 for (int y = 0; y < Height; y++)
293 { 266 {
294 for (int x = 0; x < Width; x++) 267 for (int x = 0; x < Width; x++)
@@ -321,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
321 // New terrain serialization format that includes the width and length. 294 // New terrain serialization format that includes the width and length.
322 private void ToXml2(XmlWriter xmlWriter) 295 private void ToXml2(XmlWriter xmlWriter)
323 { 296 {
324 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_map); 297 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.GetCompressedMap());
325 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage)); 298 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
326 serializer.Serialize(xmlWriter, package); 299 serializer.Serialize(xmlWriter, package);
327 } 300 }
@@ -331,38 +304,32 @@ namespace OpenSim.Region.Framework.Scenes
331 { 304 {
332 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage)); 305 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
333 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader); 306 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
334 Width = package.SizeX; 307 m_terrainData = new HeightmapTerrainData(package.Map, package.SizeX, package.SizeY, package.SizeZ);
335 Height = package.SizeY;
336 Altitude = package.SizeZ;
337 m_map = package.Map;
338 } 308 }
339 309
340 // Fill the heightmap with the center bump terrain 310 // Fill the heightmap with the center bump terrain
341 private void PinHeadIsland() 311 private void PinHeadIsland()
342 { 312 {
343 int x; 313 for (int x = 0; x < Width; x++)
344 for (x = 0; x < Width; x++)
345 { 314 {
346 int y; 315 for (int y = 0; y < Height; y++)
347 for (y = 0; y < Height; y++)
348 { 316 {
349 int idx = x * (int)Width + y; 317 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
350 m_map[idx] = ToCompressedHeight(TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10); 318 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
351 short spherFacA = ToCompressedHeight(TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01); 319 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
352 short spherFacB = ToCompressedHeight(TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001); 320 if (m_terrainData[x, y]< spherFacA)
353 if (m_map[idx] < spherFacA) 321 m_terrainData[x, y]= spherFacA;
354 m_map[idx] = spherFacA; 322 if (m_terrainData[x, y]< spherFacB)
355 if (m_map[idx] < spherFacB) 323 m_terrainData[x, y] = spherFacB;
356 m_map[idx] = spherFacB;
357 } 324 }
358 } 325 }
359 } 326 }
360 327
361 private void FlatLand() 328 private void FlatLand()
362 { 329 {
363 short flatHeight = ToCompressedHeight(21); 330 for (int xx = 0; xx < Width; xx++)
364 for (int ii = 0; ii < m_map.Length; ii++) 331 for (int yy = 0; yy < Height; yy++)
365 m_map[ii] = flatHeight; 332 m_terrainData[xx, yy] = 21;
366 } 333 }
367 } 334 }
368} 335}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index 2e856bc..511745d 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -113,22 +113,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
113 // routines (like IClientAPI) only pass the float array of heights around. This entry 113 // routines (like IClientAPI) only pass the float array of heights around. This entry
114 // converts that legacy representation into the more compact represenation used in 114 // converts that legacy representation into the more compact represenation used in
115 // TerrainChannel. Someday fix the plumbing between here and the scene. 115 // TerrainChannel. Someday fix the plumbing between here and the scene.
116 public static LayerDataPacket CreateLandPacket(float[] heightmap, int patchX, int patchY, uint sizeX, uint sizeY) 116 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
117 { 117 {
118 int[] xPieces = new int[1]; 118 int[] xPieces = new int[1];
119 int[] yPieces = new int[1]; 119 int[] yPieces = new int[1];
120
121 short[] newmap = new short[heightmap.Length];
122 for (int ii = 0; ii < heightmap.Length; ii++)
123 newmap[ii] = TerrainChannel.ToCompressedHeight(heightmap[ii]);
124
125 xPieces[0] = patchX; // patch X dimension 120 xPieces[0] = patchX; // patch X dimension
126 yPieces[0] = patchY; 121 yPieces[0] = patchY;
127 122
128 m_log.DebugFormat("{0} CreateLandPacket. patchX={1}, patchY={2}, sizeX={3}, sizeY={4}", 123 m_log.DebugFormat("{0} CreateLandPacket. patchX={1}, patchY={2}, sizeX={3}, sizeY={4}",
129 LogHeader, patchX, patchY, sizeX, sizeY); 124 LogHeader, patchX, patchY, terrData.SizeX, terrData.SizeY);
130 125
131 return CreateLandPacket(newmap, xPieces, yPieces, (int)TerrainPatch.LayerType.Land, sizeX, sizeY); 126 return CreateLandPacket(terrData, xPieces, yPieces, (int)TerrainPatch.LayerType.Land);
132 } 127 }
133 128
134 /// <summary> 129 /// <summary>
@@ -153,8 +148,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
153 /// <param name="pRegionSizeX"></param> 148 /// <param name="pRegionSizeX"></param>
154 /// <param name="pRegionSizeY"></param> 149 /// <param name="pRegionSizeY"></param>
155 /// <returns></returns> 150 /// <returns></returns>
156 public static LayerDataPacket CreateLandPacket(short[] heightmap, int[] x, int[] y, byte type, 151 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
157 uint pRegionSizeX, uint pRegionSizeY)
158 { 152 {
159 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 153 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
160 154
@@ -168,7 +162,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 bitpack.PackBits(type, 8); 162 bitpack.PackBits(type, 8);
169 163
170 for (int i = 0; i < x.Length; i++) 164 for (int i = 0; i < x.Length; i++)
171 CreatePatchFromHeightmap(bitpack, heightmap, x[i], y[i], pRegionSizeX, pRegionSizeY); 165 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
172 166
173 bitpack.PackBits(END_OF_PATCHES, 8); 167 bitpack.PackBits(END_OF_PATCHES, 8);
174 168
@@ -217,14 +211,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
217 /// </param> 211 /// </param>
218 /// <param name="pRegionSizeX"></param> 212 /// <param name="pRegionSizeX"></param>
219 /// <param name="pRegionSizeY"></param> 213 /// <param name="pRegionSizeY"></param>
220 public static void CreatePatchFromHeightmap(BitPack output, short[] heightmap, int patchX, int patchY, 214 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
221 uint pRegionSizeX, uint pRegionSizeY)
222 { 215 {
223 TerrainPatch.Header header = PrescanPatch(heightmap, patchX, patchY, pRegionSizeX, pRegionSizeY); 216 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
224 header.QuantWBits = 136; 217 header.QuantWBits = 136;
225 218
226 // If larger than legacy region size, pack patch X and Y info differently. 219 // If larger than legacy region size, pack patch X and Y info differently.
227 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 220 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
228 { 221 {
229 header.PatchIDs = (patchY & 0xFFFF); 222 header.PatchIDs = (patchY & 0xFFFF);
230 header.PatchIDs += (patchX << 16); 223 header.PatchIDs += (patchX << 16);
@@ -237,8 +230,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
237 230
238 // NOTE: No idea what prequant and postquant should be or what they do 231 // NOTE: No idea what prequant and postquant should be or what they do
239 int wbits; 232 int wbits;
240 int[] patch = CompressPatch(heightmap, patchX, patchY, header, 10, pRegionSizeX, pRegionSizeY, out wbits); 233 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
241 wbits = EncodePatchHeader(output, header, patch, pRegionSizeX, pRegionSizeY, wbits); 234 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
242 EncodePatch(output, patch, 0, wbits); 235 EncodePatch(output, patch, 0, wbits);
243 } 236 }
244 237
@@ -262,19 +255,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
262 } 255 }
263 256
264 // Scan the height info we're returning and return a patch packet header for this patch. 257 // Scan the height info we're returning and return a patch packet header for this patch.
265 // TODO. Why are patches ordered Y,X rather than X,Y? 258 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
266 private static TerrainPatch.Header PrescanPatch(short[] heightmap, int patchX, int patchY,
267 uint pRegionSizeX, uint pRegionSizeY)
268 { 259 {
269 TerrainPatch.Header header = new TerrainPatch.Header(); 260 TerrainPatch.Header header = new TerrainPatch.Header();
270 short zmax = -32767; 261 float zmax = -99999999.0f;
271 short zmin = 32767; 262 float zmin = 99999999.0f;
272 263
273 for (int j = patchY*16; j < (patchY + 1)*16; j++) 264 for (int j = patchY*16; j < (patchY + 1)*16; j++)
274 { 265 {
275 for (int i = patchX*16; i < (patchX + 1)*16; i++) 266 for (int i = patchX*16; i < (patchX + 1)*16; i++)
276 { 267 {
277 short val = heightmap[j*pRegionSizeX + i]; 268 // short val = heightmap[j*pRegionSizeX + i];
269 float val = terrData[j, i];
278 if (val > zmax) zmax = val; 270 if (val > zmax) zmax = val;
279 if (val < zmin) zmin = val; 271 if (val < zmin) zmin = val;
280 } 272 }
@@ -282,8 +274,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 274
283 // Since the the min and max values are the shorts, rescale to be real values. 275 // Since the the min and max values are the shorts, rescale to be real values.
284 // TODO: all this logic should go into the class wrapping the short values. 276 // TODO: all this logic should go into the class wrapping the short values.
285 header.DCOffset = TerrainChannel.FromCompressedHeight(zmin); 277 header.DCOffset = zmin;
286 header.Range = (int)(TerrainChannel.FromCompressedHeight(zmax) - TerrainChannel.FromCompressedHeight(zmin) + 1.0f); 278 header.Range = (int)(zmax - zmin + 1.0f);
287 279
288 return header; 280 return header;
289 } 281 }
@@ -812,8 +804,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
812 return itemp; 804 return itemp;
813 } 805 }
814 806
815 private static int[] CompressPatch(short[] heightmap, int patchX, int patchY, TerrainPatch.Header header, 807 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
816 int prequant, uint pRegionSizeX, uint pRegionSizeY, out int wbits) 808 int prequant, out int wbits)
817 { 809 {
818 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 810 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
819 int wordsize = prequant; 811 int wordsize = prequant;
@@ -827,19 +819,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
827 819
828 int k = 0; 820 int k = 0;
829 821
830 premult /= Constants.TerrainCompression; // put here short to float factor
831
832 int jPatchLimit = patchY; 822 int jPatchLimit = patchY;
833 if (patchY >= (pRegionSizeY / Constants.TerrainPatchSize)) 823 if (patchY >= (terrData.SizeY / Constants.TerrainPatchSize))
834 { 824 {
835 jPatchLimit = (int)(pRegionSizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize; 825 jPatchLimit = (int)(terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize;
836 } 826 }
837 jPatchLimit = (jPatchLimit + 1) * Constants.TerrainPatchSize; 827 jPatchLimit = (jPatchLimit + 1) * Constants.TerrainPatchSize;
838 828
839 int iPatchLimit = patchX; 829 int iPatchLimit = patchX;
840 if (patchX >= (pRegionSizeX / Constants.TerrainPatchSize)) 830 if (patchX >= (terrData.SizeX / Constants.TerrainPatchSize))
841 { 831 {
842 iPatchLimit = (int)(pRegionSizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize; 832 iPatchLimit = (int)(terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize;
843 } 833 }
844 iPatchLimit = (iPatchLimit + 1) * Constants.TerrainPatchSize; 834 iPatchLimit = (iPatchLimit + 1) * Constants.TerrainPatchSize;
845 835
@@ -847,7 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
847 { 837 {
848 for (int i = patchX * Constants.TerrainPatchSize; i < iPatchLimit; i++) 838 for (int i = patchX * Constants.TerrainPatchSize; i < iPatchLimit; i++)
849 { 839 {
850 block[k++] = (heightmap[j*pRegionSizeX + i])*premult - sub; 840 // block[k++] = (heightmap[j*pRegionSizeX + i])*premult - sub;
841 block[k++] = terrData[j, i] - sub;
851 } 842 }
852 } 843 }
853 844