aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/TerrainChannel.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs259
1 files changed, 156 insertions, 103 deletions
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index c0ca48e..6d245cb 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,132 +45,115 @@ namespace OpenSim.Region.Framework.Scenes
40 /// </summary> 45 /// </summary>
41 public class TerrainChannel : ITerrainChannel 46 public class TerrainChannel : ITerrainChannel
42 { 47 {
43 private readonly bool[,] taint; 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private double[,] map; 49 private static string LogHeader = "[TERRAIN CHANNEL]";
50
51 protected TerrainData m_terrainData;
45 52
53 public int Width { get { return m_terrainData.SizeX; } } // X dimension
54 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
55 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
56 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
57
58 // Default, not-often-used builder
46 public TerrainChannel() 59 public TerrainChannel()
47 { 60 {
48 map = new double[Constants.RegionSize, Constants.RegionSize]; 61 m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
49 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 62 FlatLand();
50 63 // PinHeadIsland();
51 PinHeadIsland();
52 } 64 }
53 65
54 public TerrainChannel(String type) 66 // Create terrain of given size
67 public TerrainChannel(int pX, int pY)
55 { 68 {
56 map = new double[Constants.RegionSize, Constants.RegionSize]; 69 m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
57 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 70 }
58 71
72 // Create terrain of specified size and initialize with specified terrain.
73 // TODO: join this with the terrain initializers.
74 public TerrainChannel(String type, int pX, int pY, int pZ)
75 {
76 m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
59 if (type.Equals("flat")) 77 if (type.Equals("flat"))
60 FlatLand(); 78 FlatLand();
61 else 79 else
62 PinHeadIsland(); 80 PinHeadIsland();
63 } 81 }
64 82
65 public TerrainChannel(double[,] import) 83 public TerrainChannel(double[,] pM, uint pAltitude)
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 { 84 {
82 map = new double[w,h]; 85 m_terrainData = new HeightmapTerrainData(pM);
83 taint = new bool[w / 16,h / 16];
84 } 86 }
85 87
86 #region ITerrainChannel Members 88 #region ITerrainChannel Members
87 89
88 public int Width 90 // ITerrainChannel.MakeCopy()
91 public ITerrainChannel MakeCopy()
89 { 92 {
90 get { return map.GetLength(0); } 93 return this.Copy();
91 } 94 }
92 95
93 public int Height 96 // ITerrainChannel.GetTerrainData()
97 public TerrainData GetTerrainData()
94 { 98 {
95 get { return map.GetLength(1); } 99 return m_terrainData;
96 } 100 }
97 101
98 public ITerrainChannel MakeCopy() 102 // ITerrainChannel.GetFloatsSerialized()
103 // NOTICE that the one dimensional form is ordered by Y!!
104 public float[] GetFloatsSerialised()
99 { 105 {
100 TerrainChannel copy = new TerrainChannel(false); 106 int points = Width * Height;
101 copy.map = (double[,]) map.Clone(); 107 float[] heights = new float[points];
102 108
103 return copy; 109 int idx = 0;
110 for (int ii = 0; ii < Height; ii++)
111 for (int jj = 0; jj < Width; jj++)
112 heights[idx++] = m_terrainData[jj, ii];
113
114 return heights;
104 } 115 }
105 116
106 public float[] GetFloatsSerialised() 117 // ITerrainChannel.GetDoubles()
118 public double[,] GetDoubles()
107 { 119 {
108 // Move the member variables into local variables, calling
109 // member variables 256*256 times gets expensive
110 int w = Width; 120 int w = Width;
111 int h = Height; 121 int l = Height;
112 float[] heights = new float[w * h]; 122 double[,] heights = new double[w, l];
113 123
114 int i, j; // map coordinates
115 int idx = 0; // index into serialized array 124 int idx = 0; // index into serialized array
116 for (i = 0; i < h; i++) 125 for (int ii = 0; ii < w; ii++)
117 { 126 {
118 for (j = 0; j < w; j++) 127 for (int jj = 0; jj < l; jj++)
119 { 128 {
120 heights[idx++] = (float)map[j, i]; 129 heights[ii, jj] = (double)m_terrainData[ii, jj];
130 idx++;
121 } 131 }
122 } 132 }
123 133
124 return heights; 134 return heights;
125 } 135 }
126 136
127 public double[,] GetDoubles() 137 // ITerrainChannel.this[x,y]
128 {
129 return map;
130 }
131
132 public double this[int x, int y] 138 public double this[int x, int y]
133 { 139 {
134 get { return map[x, 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 if (map[x, y] != value) 146 m_terrainData[x, y] = (float)value;
142 {
143 taint[x / 16, y / 16] = true;
144 map[x, y] = value;
145 }
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 return m_terrainData.IsTaintedAt(x, y);
152 {
153 taint[x / 16, y / 16] = false;
154 return true;
155 }
156 return false;
157 }
158
159 #endregion
160
161 public TerrainChannel Copy()
162 {
163 TerrainChannel copy = new TerrainChannel(false);
164 copy.map = (double[,]) map.Clone();
165
166 return copy;
167 } 154 }
168 155
156 // ITerrainChannel.SaveToXmlString()
169 public string SaveToXmlString() 157 public string SaveToXmlString()
170 { 158 {
171 XmlWriterSettings settings = new XmlWriterSettings(); 159 XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
181 } 169 }
182 } 170 }
183 171
184 private void WriteXml(XmlWriter writer) 172 // 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) 173 public void LoadFromXmlString(string data)
192 { 174 {
193 StringReader sr = new StringReader(data); 175 StringReader sr = new StringReader(data);
@@ -199,12 +181,50 @@ namespace OpenSim.Region.Framework.Scenes
199 sr.Close(); 181 sr.Close();
200 } 182 }
201 183
184 #endregion
185
186 public TerrainChannel Copy()
187 {
188 TerrainChannel copy = new TerrainChannel();
189 copy.m_terrainData = m_terrainData.Clone();
190 return copy;
191 }
192
193 private void WriteXml(XmlWriter writer)
194 {
195 if (Width == Constants.RegionSize && Height == Constants.RegionSize)
196 {
197 // Downward compatibility for legacy region terrain maps.
198 // If region is exactly legacy size, return the old format XML.
199 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
200 ToXml(writer);
201 writer.WriteEndElement();
202 }
203 else
204 {
205 // New format XML that includes width and length.
206 writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
207 ToXml2(writer);
208 writer.WriteEndElement();
209 }
210 }
211
202 private void ReadXml(XmlReader reader) 212 private void ReadXml(XmlReader reader)
203 { 213 {
204 reader.ReadStartElement("TerrainMap"); 214 // Check the first element. If legacy element, use the legacy reader.
205 FromXml(reader); 215 if (reader.IsStartElement("TerrainMap"))
216 {
217 reader.ReadStartElement("TerrainMap");
218 FromXml(reader);
219 }
220 else
221 {
222 reader.ReadStartElement("TerrainMap2");
223 FromXml2(reader);
224 }
206 } 225 }
207 226
227 // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
208 private void ToXml(XmlWriter xmlWriter) 228 private void ToXml(XmlWriter xmlWriter)
209 { 229 {
210 float[] mapData = GetFloatsSerialised(); 230 float[] mapData = GetFloatsSerialised();
@@ -218,12 +238,15 @@ namespace OpenSim.Region.Framework.Scenes
218 serializer.Serialize(xmlWriter, buffer); 238 serializer.Serialize(xmlWriter, buffer);
219 } 239 }
220 240
241 // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
221 private void FromXml(XmlReader xmlReader) 242 private void FromXml(XmlReader xmlReader)
222 { 243 {
223 XmlSerializer serializer = new XmlSerializer(typeof(byte[])); 244 XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
224 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader); 245 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
225 int index = 0; 246 int index = 0;
226 247
248 m_terrainData = new HeightmapTerrainData(Width, Height, Altitude);
249
227 for (int y = 0; y < Height; y++) 250 for (int y = 0; y < Height; y++)
228 { 251 {
229 for (int x = 0; x < Width; x++) 252 for (int x = 0; x < Width; x++)
@@ -236,35 +259,65 @@ namespace OpenSim.Region.Framework.Scenes
236 } 259 }
237 } 260 }
238 261
262 private class TerrainChannelXMLPackage
263 {
264 public int Version;
265 public int SizeX;
266 public int SizeY;
267 public int SizeZ;
268 public float CompressionFactor;
269 public short[] Map;
270 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
271 {
272 Version = 1;
273 SizeX = pX;
274 SizeY = pY;
275 SizeZ = pZ;
276 CompressionFactor = pCompressionFactor;
277 Map = pMap;
278 }
279 }
280
281 // New terrain serialization format that includes the width and length.
282 private void ToXml2(XmlWriter xmlWriter)
283 {
284 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
285 m_terrainData.GetCompressedMap());
286 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
287 serializer.Serialize(xmlWriter, package);
288 }
289
290 // New terrain serialization format that includes the width and length.
291 private void FromXml2(XmlReader xmlReader)
292 {
293 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
294 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
295 m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
296 }
297
298 // Fill the heightmap with the center bump terrain
239 private void PinHeadIsland() 299 private void PinHeadIsland()
240 { 300 {
241 int x; 301 for (int x = 0; x < Width; x++)
242 for (x = 0; x < Constants.RegionSize; x++)
243 { 302 {
244 int y; 303 for (int y = 0; y < Height; y++)
245 for (y = 0; y < Constants.RegionSize; y++)
246 { 304 {
247 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 305 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
248 double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01; 306 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
249 double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001; 307 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
250 if (map[x, y] < spherFacA) 308 if (m_terrainData[x, y]< spherFacA)
251 map[x, y] = spherFacA; 309 m_terrainData[x, y]= spherFacA;
252 if (map[x, y] < spherFacB) 310 if (m_terrainData[x, y]< spherFacB)
253 map[x, y] = spherFacB; 311 m_terrainData[x, y] = spherFacB;
254 } 312 }
255 } 313 }
256 } 314 }
257 315
258 private void FlatLand() 316 private void FlatLand()
259 { 317 {
260 int x; 318 for (int xx = 0; xx < Width; xx++)
261 for (x = 0; x < Constants.RegionSize; x++) 319 for (int yy = 0; yy < Height; yy++)
262 { 320 m_terrainData[xx, yy] = 21;
263 int y;
264 for (y = 0; y < Constants.RegionSize; y++)
265 map[x, y] = 21;
266 }
267 } 321 }
268
269 } 322 }
270} 323}