aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorRobert Adams2013-09-25 17:21:20 -0700
committerRobert Adams2013-09-28 07:33:56 -0700
commit8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1 (patch)
tree0423a4cd16f354f21d12162eaa351d9e13ba52fd /OpenSim
parentRemove time based terrain storage in SQLite so revision number can be used (diff)
downloadopensim-SC-8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1.zip
opensim-SC-8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1.tar.gz
opensim-SC-8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1.tar.bz2
opensim-SC-8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1.tar.xz
varregion: serious rework of TerrainChannel:
-- addition of varaible region size in X and Y -- internal storage of heightmap changed from double[] to short[] -- helper routines for handling internal structure while keeping existing API -- to and from XML that adds region size information (for downward compatibility, output in the legacy XML format if X and Y are 256) Updated and commented Constants.RegionSize but didn't change the name for compatibility.
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Constants.cs9
-rw-r--r--OpenSim/Framework/RegionInfo.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs40
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs280
9 files changed, 247 insertions, 135 deletions
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..7979132 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -30,9 +30,18 @@ namespace OpenSim.Framework
30{ 30{
31 public class Constants 31 public class Constants
32 { 32 {
33 // 'RegionSize' captures the legacy region size.
34 // DO NOT USE THIS FOR ANY NEW CODE. Use Scene.RegionSize[XYZ] as a region might not
35 // be the legacy region size.
33 public const uint RegionSize = 256; 36 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096; 37 public const uint RegionHeight = 4096;
38
39 // Terrain heightmap is kept as shorts that are the float value times this compression factor
40 public const float TerrainCompression = 100.0f;
41 // Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
42 public const int MinRegionSize = 16;
35 public const byte TerrainPatchSize = 16; 43 public const byte TerrainPatchSize = 16;
44
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 45 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 46
38 public enum EstateAccessCodex : uint 47 public enum EstateAccessCodex : uint
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 2d3c9ea..882fe33 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -472,7 +472,7 @@ namespace OpenSim.Framework
472 /// The x co-ordinate of this region in map tiles (e.g. 1000). 472 /// The x co-ordinate of this region in map tiles (e.g. 1000).
473 /// Coordinate is scaled as world coordinates divided by the legacy region size 473 /// Coordinate is scaled as world coordinates divided by the legacy region size
474 /// and is thus is the number of legacy regions. 474 /// and is thus is the number of legacy regions.
475 /// This entrypoint exists for downward compatability for external modules. 475 /// DO NOT USE FOR NEW CODE! This entrypoint exists for downward compatability with external modules.
476 /// </summary> 476 /// </summary>
477 public uint RegionLocX 477 public uint RegionLocX
478 { 478 {
@@ -480,22 +480,11 @@ namespace OpenSim.Framework
480 set { LegacyRegionLocX = value; } 480 set { LegacyRegionLocX = value; }
481 } 481 }
482 482
483 public void SetDefaultRegionSize()
484 {
485 RegionWorldLocX = 0;
486 RegionWorldLocY = 0;
487 RegionWorldLocZ = 0;
488 RegionSizeX = Constants.RegionSize;
489 RegionSizeY = Constants.RegionSize;
490 RegionSizeZ = Constants.RegionHeight;
491 }
492
493
494 /// <summary> 483 /// <summary>
495 /// The y co-ordinate of this region in map tiles (e.g. 1000). 484 /// The y co-ordinate of this region in map tiles (e.g. 1000).
496 /// Coordinate is scaled as world coordinates divided by the legacy region size 485 /// Coordinate is scaled as world coordinates divided by the legacy region size
497 /// and is thus is the number of legacy regions. 486 /// and is thus is the number of legacy regions.
498 /// This entrypoint exists for downward compatability for external modules. 487 /// DO NOT USE FOR NEW CODE! This entrypoint exists for downward compatability with external modules.
499 /// </summary> 488 /// </summary>
500 public uint RegionLocY 489 public uint RegionLocY
501 { 490 {
@@ -503,6 +492,16 @@ namespace OpenSim.Framework
503 set { LegacyRegionLocY = value; } 492 set { LegacyRegionLocY = value; }
504 } 493 }
505 494
495 public void SetDefaultRegionSize()
496 {
497 RegionWorldLocX = 0;
498 RegionWorldLocY = 0;
499 RegionWorldLocZ = 0;
500 RegionSizeX = Constants.RegionSize;
501 RegionSizeY = Constants.RegionSize;
502 RegionSizeZ = Constants.RegionHeight;
503 }
504
506 // A unique region handle is created from the region's world coordinates. 505 // A unique region handle is created from the region's world coordinates.
507 // This cannot be changed because some code expects to receive the region handle and then 506 // This cannot be changed because some code expects to receive the region handle and then
508 // compute the region coordinates from it. 507 // compute the region coordinates from it.
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 22bff9f..fea9ddf 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -1240,9 +1240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1240 try 1240 try
1241 { 1241 {
1242 int[] patches = new int[] { py * 16 + px }; 1242 int[] patches = new int[] { py * 16 + px };
1243 float[] heightmap = (map.Length == 65536) ? 1243 float[] heightmap = (map.Length == 65536) ? map : LLHeightFieldMoronize(map);
1244 map :
1245 LLHeightFieldMoronize(map);
1246 1244
1247 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1245 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1248 1246
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d78ade5..d5c77ec 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
67 { 67 {
68 using (Bitmap bitmap = new Bitmap(filename)) 68 using (Bitmap bitmap = new Bitmap(filename))
69 { 69 {
70 ITerrainChannel retval = new TerrainChannel(true); 70 ITerrainChannel retval = new TerrainChannel(w, h);
71 71
72 for (int x = 0; x < retval.Width; x++) 72 for (int x = 0; x < retval.Width; x++)
73 { 73 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index c1ffd22..2fff4c1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -130,15 +130,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
130 { 130 {
131 if (m_scene.Heightmap == null) 131 if (m_scene.Heightmap == null)
132 { 132 {
133 m_channel = new TerrainChannel(m_InitialTerrain); 133 m_channel = new TerrainChannel(m_InitialTerrain,
134 m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY, m_scene.RegionInfo.RegionSizeZ);
134 m_scene.Heightmap = m_channel; 135 m_scene.Heightmap = m_channel;
135 m_revert = new TerrainChannel();
136 UpdateRevertMap(); 136 UpdateRevertMap();
137 } 137 }
138 else 138 else
139 { 139 {
140 m_channel = m_scene.Heightmap; 140 m_channel = m_scene.Heightmap;
141 m_revert = new TerrainChannel();
142 UpdateRevertMap(); 141 UpdateRevertMap();
143 } 142 }
144 143
@@ -532,6 +531,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
532 /// </summary> 531 /// </summary>
533 public void UpdateRevertMap() 532 public void UpdateRevertMap()
534 { 533 {
534 /*
535 int x; 535 int x;
536 for (x = 0; x < m_channel.Width; x++) 536 for (x = 0; x < m_channel.Width; x++)
537 { 537 {
@@ -541,6 +541,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
541 m_revert[x, y] = m_channel[x, y]; 541 m_revert[x, y] = m_channel[x, y];
542 } 542 }
543 } 543 }
544 */
545 m_revert = m_channel.MakeCopy();
544 } 546 }
545 547
546 /// <summary> 548 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index c936a84..847d245 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -134,26 +134,26 @@ namespace OpenSim.Region.Framework.Interfaces
134 Dictionary<string, string> GetExtra(UUID regionID); 134 Dictionary<string, string> GetExtra(UUID regionID);
135 135
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. 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 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 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 142 // feature removed, that left some old entries with the time in the revision
143 // field. 143 // field.
144 // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is 144 // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
145 // left over and it is presumed to be 'Legacy256'. 145 // left over and it is presumed to be 'Legacy256'.
146 // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation. 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. 147 // If a revision does not match any of these, it is assumed to be Legacy256.
148 public enum DBTerrainRevision 148 public enum DBTerrainRevision
149 { 149 {
150 // Terrain is 'double[256,256]' 150 // Terrain is 'double[256,256]'
151 Legacy256 = 11, 151 Legacy256 = 11,
152 // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions 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. 153 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
154 Variable2D = 22, 154 Variable2D = 22,
155 // A revision that is not listed above or any revision greater than this value is 'Legacy256'. 155 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
156 RevisionHigh = 1234 156 RevisionHigh = 1234
157 } 157 }
158 158
159} 159}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index e467701..3c060a4 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -29,15 +29,21 @@ namespace OpenSim.Region.Framework.Interfaces
29{ 29{
30 public interface ITerrainChannel 30 public interface ITerrainChannel
31 { 31 {
32 int Height { get; } 32 int Width { get;} // X dimension
33 int Height { get;} // Y dimension
34 int Altitude { get;} // Z dimension
35
33 double this[int x, int y] { get; set; } 36 double this[int x, int y] { get; set; }
34 int Width { get; }
35 37
36 /// <summary> 38 /// <summary>
37 /// Squash the entire heightmap into a single dimensioned array 39 /// Squash the entire heightmap into a single dimensioned array
38 /// </summary> 40 /// </summary>
39 /// <returns></returns> 41 /// <returns></returns>
40 float[] GetFloatsSerialised(); 42 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();
41 47
42 double[,] GetDoubles(); 48 double[,] GetDoubles();
43 bool Tainted(int x, int y); 49 bool Tainted(int x, int y);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 26e7d7d..49e32c6 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1905,13 +1905,13 @@ 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); 1908 Heightmap = new TerrainChannel(m_InitialTerrain, RegionInfo.RegionSizeX, RegionInfo.RegionSizeY, RegionInfo.RegionSizeZ);
1909 1909
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1911 }
1912 else 1912 else
1913 { 1913 {
1914 Heightmap = new TerrainChannel(map); 1914 Heightmap = new TerrainChannel(map, RegionInfo.RegionSizeZ);
1915 } 1915 }
1916 } 1916 }
1917 catch (IOException e) 1917 catch (IOException e)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index c0ca48e..fef93bf 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -40,132 +40,125 @@ namespace OpenSim.Region.Framework.Scenes
40 /// </summary> 40 /// </summary>
41 public class TerrainChannel : ITerrainChannel 41 public class TerrainChannel : ITerrainChannel
42 { 42 {
43 private readonly bool[,] taint; 43 protected bool[,] m_taint;
44 private double[,] map; 44 protected short[] m_map;
45 45
46 public int Width { get; private set; } // X dimension
47 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
48 public int Height { get; private set; } // Y dimension
49 public int Altitude { get; private set; } // Y dimension
50
51 // Default, not-often-used builder
46 public TerrainChannel() 52 public TerrainChannel()
47 { 53 {
48 map = new double[Constants.RegionSize, Constants.RegionSize]; 54 InitializeStructures(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight, false);
49 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 55 FlatLand();
50 56 // PinHeadIsland();
51 PinHeadIsland();
52 } 57 }
53 58
54 public TerrainChannel(String type) 59 // Create terrain of given size
60 public TerrainChannel(int pX, int pY)
55 { 61 {
56 map = new double[Constants.RegionSize, Constants.RegionSize]; 62 InitializeStructures((uint)pX, (uint)pY, Constants.RegionHeight, true);
57 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 63 }
58 64
65 // Create terrain of specified size and initialize with specified terrain.
66 // TODO: join this with the terrain initializers.
67 public TerrainChannel(String type, uint pX, uint pY, uint pZ)
68 {
69 InitializeStructures(pX, pY, pZ, false);
59 if (type.Equals("flat")) 70 if (type.Equals("flat"))
60 FlatLand(); 71 FlatLand();
61 else 72 else
62 PinHeadIsland(); 73 PinHeadIsland();
63 } 74 }
64 75
65 public TerrainChannel(double[,] import) 76 public TerrainChannel(double[,] pM, uint pH)
66 {
67 map = import;
68 taint = new bool[import.GetLength(0),import.GetLength(1)];
69 }
70
71 public TerrainChannel(bool createMap)
72 {
73 if (createMap)
74 {
75 map = new double[Constants.RegionSize,Constants.RegionSize];
76 taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16];
77 }
78 }
79
80 public TerrainChannel(int w, int h)
81 { 77 {
82 map = new double[w,h]; 78 InitializeStructures((uint)pM.GetLength(0), (uint)pM.GetLength(1), pH, false);
83 taint = new bool[w / 16,h / 16]; 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]);
84 } 83 }
85 84
86 #region ITerrainChannel Members 85 #region ITerrainChannel Members
87 86
88 public int Width 87 // ITerrainChannel.MakeCopy()
88 public ITerrainChannel MakeCopy()
89 { 89 {
90 get { return map.GetLength(0); } 90 return this.Copy();
91 } 91 }
92 92
93 public int Height 93 // ITerrainChannel.GetCompressedMap()
94 public short[] GetCompressedMap()
94 { 95 {
95 get { return map.GetLength(1); } 96 return m_map;
96 } 97 }
97 98
98 public ITerrainChannel MakeCopy() 99 // ITerrainChannel.GetFloatsSerialized()
100 public float[] GetFloatsSerialised()
99 { 101 {
100 TerrainChannel copy = new TerrainChannel(false); 102 int points = Width * Height;
101 copy.map = (double[,]) map.Clone(); 103 float[] heights = new float[points];
102 104
103 return copy; 105 for (int ii = 0; ii < points; ii++)
106 heights[ii] = FromCompressedHeight(m_map[ii]);
107
108 return heights;
104 } 109 }
105 110
106 public float[] GetFloatsSerialised() 111 // ITerrainChannel.GetDoubles()
112 public double[,] GetDoubles()
107 { 113 {
108 // Move the member variables into local variables, calling
109 // member variables 256*256 times gets expensive
110 int w = Width; 114 int w = Width;
111 int h = Height; 115 int l = Height;
112 float[] heights = new float[w * h]; 116 double[,] heights = new double[w, l];
113 117
114 int i, j; // map coordinates
115 int idx = 0; // index into serialized array 118 int idx = 0; // index into serialized array
116 for (i = 0; i < h; i++) 119 for (int ii = 0; ii < l; ii++)
117 { 120 {
118 for (j = 0; j < w; j++) 121 for (int jj = 0; jj < w; jj++)
119 { 122 {
120 heights[idx++] = (float)map[j, i]; 123 heights[ii, jj] = (double)FromCompressedHeight(m_map[idx]);
124 idx++;
121 } 125 }
122 } 126 }
123 127
124 return heights; 128 return heights;
125 } 129 }
126 130
127 public double[,] GetDoubles() 131 // ITerrainChannel.this[x,y]
128 {
129 return map;
130 }
131
132 public double this[int x, int y] 132 public double this[int x, int y]
133 { 133 {
134 get { return map[x, y]; } 134 get { return m_map[x * Width + y]; }
135 set 135 set
136 { 136 {
137 // Will "fix" terrain hole problems. Although not fantastically. 137 // Will "fix" terrain hole problems. Although not fantastically.
138 if (Double.IsNaN(value) || Double.IsInfinity(value)) 138 if (Double.IsNaN(value) || Double.IsInfinity(value))
139 return; 139 return;
140 140
141 if (map[x, y] != value) 141 int idx = x * Width + y;
142 if (m_map[idx] != value)
142 { 143 {
143 taint[x / 16, y / 16] = true; 144 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
144 map[x, y] = value; 145 m_map[idx] = ToCompressedHeight(value);
145 } 146 }
146 } 147 }
147 } 148 }
148 149
150 // ITerrainChannel.Tainted()
149 public bool Tainted(int x, int y) 151 public bool Tainted(int x, int y)
150 { 152 {
151 if (taint[x / 16, y / 16]) 153 if (m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize])
152 { 154 {
153 taint[x / 16, y / 16] = false; 155 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = false;
154 return true; 156 return true;
155 } 157 }
156 return false; 158 return false;
157 } 159 }
158 160
159 #endregion 161 // ITerrainChannel.SaveToXmlString()
160
161 public TerrainChannel Copy()
162 {
163 TerrainChannel copy = new TerrainChannel(false);
164 copy.map = (double[,]) map.Clone();
165
166 return copy;
167 }
168
169 public string SaveToXmlString() 162 public string SaveToXmlString()
170 { 163 {
171 XmlWriterSettings settings = new XmlWriterSettings(); 164 XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +174,7 @@ namespace OpenSim.Region.Framework.Scenes
181 } 174 }
182 } 175 }
183 176
184 private void WriteXml(XmlWriter writer) 177 // ITerrainChannel.LoadFromXmlString()
185 {
186 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
187 ToXml(writer);
188 writer.WriteEndElement();
189 }
190
191 public void LoadFromXmlString(string data) 178 public void LoadFromXmlString(string data)
192 { 179 {
193 StringReader sr = new StringReader(data); 180 StringReader sr = new StringReader(data);
@@ -199,12 +186,89 @@ namespace OpenSim.Region.Framework.Scenes
199 sr.Close(); 186 sr.Close();
200 } 187 }
201 188
189 #endregion
190
191 private void InitializeStructures(uint pX, uint pY, uint pZ, bool shouldInitializeHeightmap)
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
213 // that is coded as the float height times the compression factor (usually '100'
214 // to make for two decimal points).
215 public short ToCompressedHeight(double pHeight)
216 {
217 return (short)(pHeight * Constants.TerrainCompression);
218 }
219
220 public float FromCompressedHeight(short pHeight)
221 {
222 return ((float)pHeight) / Constants.TerrainCompression;
223 }
224
225 public TerrainChannel Copy()
226 {
227 TerrainChannel copy = new TerrainChannel();
228 copy.m_map = (short[])m_map.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;
235 }
236
237 private void WriteXml(XmlWriter writer)
238 {
239 if (Width == Constants.RegionSize && Height == Constants.RegionSize)
240 {
241 // Downward compatibility for legacy region terrain maps.
242 // If region is exactly legacy size, return the old format XML.
243 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
244 ToXml(writer);
245 writer.WriteEndElement();
246 }
247 else
248 {
249 // New format XML that includes width and length.
250 writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
251 ToXml2(writer);
252 writer.WriteEndElement();
253 }
254 }
255
202 private void ReadXml(XmlReader reader) 256 private void ReadXml(XmlReader reader)
203 { 257 {
204 reader.ReadStartElement("TerrainMap"); 258 // Check the first element. If legacy element, use the legacy reader.
205 FromXml(reader); 259 if (reader.IsStartElement("TerrainMap"))
260 {
261 reader.ReadStartElement("TerrainMap");
262 FromXml(reader);
263 }
264 else
265 {
266 reader.ReadStartElement("TerrainMap2");
267 FromXml2(reader);
268 }
206 } 269 }
207 270
271 // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
208 private void ToXml(XmlWriter xmlWriter) 272 private void ToXml(XmlWriter xmlWriter)
209 { 273 {
210 float[] mapData = GetFloatsSerialised(); 274 float[] mapData = GetFloatsSerialised();
@@ -218,6 +282,7 @@ namespace OpenSim.Region.Framework.Scenes
218 serializer.Serialize(xmlWriter, buffer); 282 serializer.Serialize(xmlWriter, buffer);
219 } 283 }
220 284
285 // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
221 private void FromXml(XmlReader xmlReader) 286 private void FromXml(XmlReader xmlReader)
222 { 287 {
223 XmlSerializer serializer = new XmlSerializer(typeof(byte[])); 288 XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
@@ -236,35 +301,68 @@ namespace OpenSim.Region.Framework.Scenes
236 } 301 }
237 } 302 }
238 303
304 private class TerrainChannelXMLPackage
305 {
306 public int Version;
307 public int SizeX;
308 public int SizeY;
309 public int SizeZ;
310 public short[] Map;
311 public TerrainChannelXMLPackage(int pX, int pY, int pZ, short[] pMap)
312 {
313 Version = 1;
314 SizeX = pX;
315 SizeY = pY;
316 SizeZ = pZ;
317 Map = pMap;
318 }
319 }
320
321 // New terrain serialization format that includes the width and length.
322 private void ToXml2(XmlWriter xmlWriter)
323 {
324 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_map);
325 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
326 serializer.Serialize(xmlWriter, package);
327 }
328
329 // New terrain serialization format that includes the width and length.
330 private void FromXml2(XmlReader xmlReader)
331 {
332 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
333 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
334 Width = package.SizeX;
335 Height = package.SizeY;
336 Altitude = package.SizeZ;
337 m_map = package.Map;
338 }
339
340 // Fill the heightmap with the center bump terrain
239 private void PinHeadIsland() 341 private void PinHeadIsland()
240 { 342 {
241 int x; 343 int x;
242 for (x = 0; x < Constants.RegionSize; x++) 344 for (x = 0; x < Width; x++)
243 { 345 {
244 int y; 346 int y;
245 for (y = 0; y < Constants.RegionSize; y++) 347 for (y = 0; y < Height; y++)
246 { 348 {
247 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 349 int idx = x * (int)Width + y;
248 double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01; 350 m_map[idx] = ToCompressedHeight(TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10);
249 double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001; 351 short spherFacA = ToCompressedHeight(TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01);
250 if (map[x, y] < spherFacA) 352 short spherFacB = ToCompressedHeight(TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001);
251 map[x, y] = spherFacA; 353 if (m_map[idx] < spherFacA)
252 if (map[x, y] < spherFacB) 354 m_map[idx] = spherFacA;
253 map[x, y] = spherFacB; 355 if (m_map[idx] < spherFacB)
356 m_map[idx] = spherFacB;
254 } 357 }
255 } 358 }
256 } 359 }
257 360
258 private void FlatLand() 361 private void FlatLand()
259 { 362 {
260 int x; 363 short flatHeight = ToCompressedHeight(21);
261 for (x = 0; x < Constants.RegionSize; x++) 364 for (int ii = 0; ii < m_map.Length; ii++)
262 { 365 m_map[ii] = flatHeight;
263 int y;
264 for (y = 0; y < Constants.RegionSize; y++)
265 map[x, y] = 21;
266 }
267 } 366 }
268
269 } 367 }
270} 368}