aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TerrainData.cs
diff options
context:
space:
mode:
authorRobert Adams2013-11-01 11:35:31 -0700
committerRobert Adams2013-11-01 11:35:31 -0700
commitff5885ab234bc9a7efda49eea0e2200711c4933c (patch)
tree21ef180072b30891700f139792d34ca9b2c7e0d6 /OpenSim/Framework/TerrainData.cs
parentvarregion: fix problem of X/Y dimensions swapped and incorrect terrain (diff)
downloadopensim-SC_OLD-ff5885ab234bc9a7efda49eea0e2200711c4933c.zip
opensim-SC_OLD-ff5885ab234bc9a7efda49eea0e2200711c4933c.tar.gz
opensim-SC_OLD-ff5885ab234bc9a7efda49eea0e2200711c4933c.tar.bz2
opensim-SC_OLD-ff5885ab234bc9a7efda49eea0e2200711c4933c.tar.xz
varregion: push TerrainData implementation up and down the database storage stack.
Implement both LoadTerrain and StoreTerrain for all DBs. Move all database blob serialization/deserialization into TerrainData.
Diffstat (limited to 'OpenSim/Framework/TerrainData.cs')
-rw-r--r--OpenSim/Framework/TerrainData.cs193
1 files changed, 169 insertions, 24 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index d7f1655..58b203f 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -43,6 +43,9 @@ namespace OpenSim.Framework
43 public int SizeY { get; protected set; } 43 public int SizeY { get; protected set; }
44 public int SizeZ { get; protected set; } 44 public int SizeZ { get; protected set; }
45 45
46 // A height used when the user doesn't specify anything
47 public const float DefaultTerrainHeight = 21f;
48
46 public abstract float this[int x, int y] { get; set; } 49 public abstract float this[int x, int y] { get; set; }
47 // Someday terrain will have caves 50 // Someday terrain will have caves
48 public abstract float this[int x, int y, int z] { get; set; } 51 public abstract float this[int x, int y, int z] { get; set; }
@@ -51,15 +54,28 @@ namespace OpenSim.Framework
51 public abstract bool IsTaintedAt(int xx, int yy); 54 public abstract bool IsTaintedAt(int xx, int yy);
52 public abstract void ClearTaint(); 55 public abstract void ClearTaint();
53 56
57 public abstract void ClearLand();
58 public abstract void ClearLand(float height);
59
54 // Return a representation of this terrain for storing as a blob in the database. 60 // Return a representation of this terrain for storing as a blob in the database.
55 // Returns 'true' to say blob was stored in the 'out' locations. 61 // Returns 'true' to say blob was stored in the 'out' locations.
56 public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob); 62 public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob);
57 63
64 // Given a revision code and a blob from the database, create and return the right type of TerrainData.
65 // The sizes passed are the expected size of the region. The database info will be used to
66 // initialize the heightmap of that sized region with as much data is in the blob.
67 // Return created TerrainData or 'null' if unsuccessful.
68 public static TerrainData CreateFromDatabaseBlobFactory(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
69 {
70 // For the moment, there is only one implementation class
71 return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
72 }
73
58 // return a special compressed representation of the heightmap in shorts 74 // return a special compressed representation of the heightmap in shorts
59 public abstract short[] GetCompressedMap(); 75 public abstract short[] GetCompressedMap();
60 public abstract float CompressionFactor { get; } 76 public abstract float CompressionFactor { get; }
61 public abstract void SetCompressedMap(short[] cmap, float pCompressionFactor);
62 77
78 public abstract double[,] GetDoubles();
63 public abstract TerrainData Clone(); 79 public abstract TerrainData Clone();
64 } 80 }
65 81
@@ -76,9 +92,14 @@ namespace OpenSim.Framework
76 { 92 {
77 // Terrain is 'double[256,256]' 93 // Terrain is 'double[256,256]'
78 Legacy256 = 11, 94 Legacy256 = 11,
79 // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions 95 // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions
80 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 96 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
81 Variable2D = 22, 97 Variable2D = 22,
98 // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
99 // and third int is the 'compression factor'. The heights are compressed as
100 // "short compressedHeight = (short)(height * compressionFactor);"
101 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
102 Compressed2D = 27,
82 // A revision that is not listed above or any revision greater than this value is 'Legacy256'. 103 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
83 RevisionHigh = 1234 104 RevisionHigh = 1234
84 } 105 }
@@ -124,6 +145,20 @@ namespace OpenSim.Framework
124 m_taint[ii, jj] = false; 145 m_taint[ii, jj] = false;
125 } 146 }
126 147
148 // TerrainData.ClearLand
149 public override void ClearLand()
150 {
151 ClearLand(DefaultTerrainHeight);
152 }
153 // TerrainData.ClearLand(float)
154 public override void ClearLand(float pHeight)
155 {
156 short flatHeight = ToCompressedHeight(pHeight);
157 for (int xx = 0; xx < SizeX; xx++)
158 for (int yy = 0; yy < SizeY; yy++)
159 m_heightmap[xx, yy] = flatHeight;
160 }
161
127 public override bool IsTaintedAt(int xx, int yy) 162 public override bool IsTaintedAt(int xx, int yy)
128 { 163 {
129 return m_taint[xx / Constants.TerrainPatchSize, yy / Constants.TerrainPatchSize]; 164 return m_taint[xx / Constants.TerrainPatchSize, yy / Constants.TerrainPatchSize];
@@ -134,7 +169,7 @@ namespace OpenSim.Framework
134 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob) 169 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
135 { 170 {
136 DBRevisionCode = (int)DBTerrainRevision.Legacy256; 171 DBRevisionCode = (int)DBTerrainRevision.Legacy256;
137 blob = LegacyTerrainSerialization(); 172 blob = ToLegacyTerrainSerialization();
138 return false; 173 return false;
139 } 174 }
140 175
@@ -155,17 +190,6 @@ namespace OpenSim.Framework
155 return newMap; 190 return newMap;
156 191
157 } 192 }
158 // TerrainData.SetCompressedMap
159 public override void SetCompressedMap(short[] cmap, float pCompressionFactor)
160 {
161 m_compressionFactor = pCompressionFactor;
162
163 int ind = 0;
164 for (int xx = 0; xx < SizeX; xx++)
165 for (int yy = 0; yy < SizeY; yy++)
166 m_heightmap[xx, yy] = cmap[ind++];
167 }
168
169 // TerrainData.Clone 193 // TerrainData.Clone
170 public override TerrainData Clone() 194 public override TerrainData Clone()
171 { 195 {
@@ -174,6 +198,18 @@ namespace OpenSim.Framework
174 return ret; 198 return ret;
175 } 199 }
176 200
201 // TerrainData.GetDoubles
202 public override double[,] GetDoubles()
203 {
204 double[,] ret = new double[SizeX, SizeY];
205 for (int xx = 0; xx < SizeX; xx++)
206 for (int yy = 0; yy < SizeY; yy++)
207 ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]);
208
209 return ret;
210 }
211
212
177 // ============================================================= 213 // =============================================================
178 214
179 private short[,] m_heightmap; 215 private short[,] m_heightmap;
@@ -230,31 +266,140 @@ namespace OpenSim.Framework
230 266
231 public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) 267 public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
232 { 268 {
233 SetCompressedMap(cmap, pCompressionFactor); 269 m_compressionFactor = pCompressionFactor;
270 int ind = 0;
271 for (int xx = 0; xx < SizeX; xx++)
272 for (int yy = 0; yy < SizeY; yy++)
273 m_heightmap[xx, yy] = cmap[ind++];
234 } 274 }
235 275
276 // Create a heighmap from a database blob
277 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ)
278 {
279 switch ((DBTerrainRevision)pFormatCode)
280 {
281 case DBTerrainRevision.Compressed2D:
282 FromCompressedTerrainSerialization(pBlob);
283 break;
284 default:
285 FromLegacyTerrainSerialization(pBlob);
286 break;
287 }
288 }
236 289
237 // Just create an array of doubles. Presumes the caller implicitly knows the size. 290 // Just create an array of doubles. Presumes the caller implicitly knows the size.
238 public Array LegacyTerrainSerialization() 291 public Array ToLegacyTerrainSerialization()
239 { 292 {
240 Array ret = null; 293 Array ret = null;
241 using (MemoryStream str = new MemoryStream(SizeX * SizeY * sizeof(double))) 294
295 using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double)))
242 { 296 {
243 using (BinaryWriter bw = new BinaryWriter(str)) 297 using (BinaryWriter bw = new BinaryWriter(str))
244 { 298 {
245 // TODO: COMPATIBILITY - Add byte-order conversions 299 for (int xx = 0; xx < Constants.RegionSize; xx++)
246 for (int ii = 0; ii < SizeX; ii++)
247 for (int jj = 0; jj < SizeY; jj++)
248 { 300 {
249 double height = this[ii, jj]; 301 for (int yy = 0; yy < Constants.RegionSize; yy++)
250 if (height == 0.0) 302 {
251 height = double.Epsilon; 303 double height = this[xx, yy];
252 bw.Write(height); 304 if (height == 0.0)
305 height = double.Epsilon;
306 bw.Write(height);
307 }
253 } 308 }
254 } 309 }
255 ret = str.ToArray(); 310 ret = str.ToArray();
256 } 311 }
257 return ret; 312 return ret;
258 } 313 }
314
315 // Just create an array of doubles. Presumes the caller implicitly knows the size.
316 public void FromLegacyTerrainSerialization(byte[] pBlob)
317 {
318 // In case database info doesn't match real terrain size, initialize the whole terrain.
319 ClearLand();
320
321 using (MemoryStream mstr = new MemoryStream(pBlob))
322 {
323 using (BinaryReader br = new BinaryReader(mstr))
324 {
325 for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
326 {
327 for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
328 {
329 float val = (float)br.ReadDouble();
330 if (xx < SizeX && yy < SizeY)
331 m_heightmap[xx, yy] = ToCompressedHeight(val);
332 }
333 }
334 }
335 ClearTaint();
336
337 m_log.InfoFormat("{0} Loaded legacy heightmap. SizeX={1}, SizeY={2}", LogHeader, SizeX, SizeY);
338 }
339 }
340
341 // See the reader below.
342 public Array ToCompressedTerrainSerialization()
343 {
344 Array ret = null;
345 using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16))))
346 {
347 using (BinaryWriter bw = new BinaryWriter(str))
348 {
349 bw.Write((Int32)DBTerrainRevision.Compressed2D);
350 bw.Write((Int32)SizeX);
351 bw.Write((Int32)SizeY);
352 bw.Write((Int32)CompressionFactor);
353 for (int yy = 0; yy < SizeY; yy++)
354 for (int xx = 0; xx < SizeX; xx++)
355 {
356 bw.Write((Int16)m_heightmap[xx, yy]);
357 }
358 }
359 ret = str.ToArray();
360 }
361 return ret;
362 }
363
364 // Initialize heightmap from blob consisting of:
365 // int32, int32, int32, int32, int16[]
366 // where the first int32 is format code, next two int32s are the X and y of heightmap data and
367 // the forth int is the compression factor for the following int16s
368 // This is just sets heightmap info. The actual size of the region was set on this instance's
369 // creation and any heights not initialized by theis blob are set to the default height.
370 public void FromCompressedTerrainSerialization(byte[] pBlob)
371 {
372 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
373
374 using (MemoryStream mstr = new MemoryStream(pBlob))
375 {
376 using (BinaryReader br = new BinaryReader(mstr))
377 {
378 hmFormatCode = br.ReadInt32();
379 hmSizeX = br.ReadInt32();
380 hmSizeY = br.ReadInt32();
381 hmCompressionFactor = br.ReadInt32();
382
383 m_compressionFactor = hmCompressionFactor;
384
385 // In case database info doesn't match real terrain size, initialize the whole terrain.
386 ClearLand();
387
388 for (int yy = 0; yy < hmSizeY; yy++)
389 {
390 for (int xx = 0; xx < hmSizeX; xx++)
391 {
392 Int16 val = br.ReadInt16();
393 if (xx < SizeX && yy < SizeY)
394 m_heightmap[xx, yy] = ToCompressedHeight(val);
395 }
396 }
397 }
398 ClearTaint();
399
400 m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size={<{3},{4}>. CompFact={5}", LogHeader,
401 hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
402 }
403 }
259 } 404 }
260} 405}