aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-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
5 files changed, 90 insertions, 148 deletions
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