aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs239
2 files changed, 224 insertions, 50 deletions
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index b0563c5..01f04d9 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -555,37 +555,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
555 555
556 try 556 try
557 { 557 {
558 MemoryStream terrainStream = new MemoryStream(terrainData);
559 terr.LoadFromStream(filename, terrainStream);
560 terrainStream.Close();
558 561
559 string localfilename = "terrain.raw"; 562 FileInfo x = new FileInfo(filename);
560 563 remoteClient.SendAlertMessage("Your terrain was loaded as a " + x.Extension + " file. It may take a few moments to appear.");
561 if (terrainData.Length == 851968)
562 {
563 localfilename = Path.Combine(Util.dataDir(),"terrain.raw"); // It's a .LLRAW
564 }
565
566 if (terrainData.Length == 196662) // 24-bit 256x256 Bitmap
567 localfilename = Path.Combine(Util.dataDir(), "terrain.bmp");
568
569 if (terrainData.Length == 256 * 256 * 4) // It's a .R32
570 localfilename = Path.Combine(Util.dataDir(), "terrain.r32");
571
572 if (terrainData.Length == 256 * 256 * 8) // It's a .R64
573 localfilename = Path.Combine(Util.dataDir(), "terrain.r64");
574
575 if (File.Exists(localfilename))
576 {
577 File.Delete(localfilename);
578 }
579
580 FileStream input = new FileStream(localfilename, FileMode.CreateNew);
581 input.Write(terrainData, 0, terrainData.Length);
582 input.Close();
583
584 FileInfo x = new FileInfo(localfilename);
585
586 terr.LoadFromFile(localfilename);
587 remoteClient.SendAlertMessage("Your terrain was loaded as a ." + x.Extension + " file. It may take a few moments to appear.");
588
589 } 564 }
590 catch (IOException e) 565 catch (IOException e)
591 { 566 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index 3ee20ae..2919897 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
@@ -30,6 +30,7 @@ using System.IO;
30using System.Text; 30using System.Text;
31using OpenSim.Region.Framework.Interfaces; 31using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Framework;
33 34
34namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders 35namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
35{ 36{
@@ -53,17 +54,120 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
53 return retval; 54 return retval;
54 } 55 }
55 56
57 public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
58 {
59 TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight);
60
61 FileInfo file = new FileInfo(filename);
62 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
63 BinaryReader bs = new BinaryReader(s);
64
65 bool eof = false;
66
67 int fileXPoints = 0;
68 int fileYPoints = 0;
69
70 // Terragen file
71 while (eof == false)
72 {
73 string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
74 switch (tmp)
75 {
76 case "SIZE":
77 fileXPoints = bs.ReadInt16() + 1;
78 fileYPoints = fileXPoints;
79 bs.ReadInt16();
80 break;
81 case "XPTS":
82 fileXPoints = bs.ReadInt16();
83 bs.ReadInt16();
84 break;
85 case "YPTS":
86 fileYPoints = bs.ReadInt16();
87 bs.ReadInt16();
88 break;
89 case "ALTW":
90 eof = true;
91 Int16 heightScale = bs.ReadInt16();
92 Int16 baseHeight = bs.ReadInt16();
93
94 int currFileYOffset = 0;
95
96 // if our region isn't on the first X section of the areas to be landscaped, then
97 // advance to our section of the file
98 while (currFileYOffset < offsetY)
99 {
100 // read a whole strip of regions
101 int heightsToRead = sectionHeight * fileXPoints;
102 bs.ReadBytes(heightsToRead * 2); // because the shorts are 2 bytes in the file
103 currFileYOffset++;
104 }
105
106 for (int y = 0; y < sectionHeight; y++)
107 {
108 int currFileXOffset = 0;
109
110 // if our region isn't the first X section of the areas to be landscaped, then
111 // advance the stream to the X start pos of our section in the file
112 // i.e. eat X upto where we start
113 while (currFileXOffset < offsetX)
114 {
115 bs.ReadBytes(sectionWidth * 2); // 2 bytes = short
116 currFileXOffset++;
117 }
118
119 // got to our X offset, so write our regions X line
120 for (int x = 0; x < sectionWidth; x++)
121 {
122 // Read a strip and continue
123 retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0;
124 }
125 // record that we wrote it
126 currFileXOffset++;
127
128 // if our region isn't the last X section of the areas to be landscaped, then
129 // advance the stream to the end of this Y column
130 while (currFileXOffset < fileWidth)
131 {
132 // eat the next regions x line
133 bs.ReadBytes(sectionWidth * 2); // 2 bytes = short
134 currFileXOffset++;
135 }
136 //eat the last additional point
137 bs.ReadInt16();
138 }
139
140
141 break;
142 default:
143 bs.ReadInt32();
144 break;
145 }
146 }
147
148 bs.Close();
149 s.Close();
150
151 return retval;
152 }
153
56 public ITerrainChannel LoadStream(Stream s) 154 public ITerrainChannel LoadStream(Stream s)
57 { 155 {
58 TerrainChannel retval = new TerrainChannel(); 156
157 int w = (int)Constants.RegionSize;
158 int h = (int)Constants.RegionSize;
159
160 TerrainChannel retval = new TerrainChannel(w, h);
59 161
60 BinaryReader bs = new BinaryReader(s); 162 BinaryReader bs = new BinaryReader(s);
61 163
62 bool eof = false; 164 bool eof = false;
63 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") 165 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
64 { 166 {
65 int w = 256; 167
66 int h = 256; 168 int fileWidth = w;
169 int fileHeight = h;
170
67 171
68 // Terragen file 172 // Terragen file
69 while (eof == false) 173 while (eof == false)
@@ -73,30 +177,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
73 { 177 {
74 case "SIZE": 178 case "SIZE":
75 int sztmp = bs.ReadInt16() + 1; 179 int sztmp = bs.ReadInt16() + 1;
76 w = sztmp; 180 fileWidth = sztmp;
77 h = sztmp; 181 fileHeight = sztmp;
78 bs.ReadInt16(); 182 bs.ReadInt16();
79 break; 183 break;
80 case "XPTS": 184 case "XPTS":
81 w = bs.ReadInt16(); 185 fileWidth = bs.ReadInt16();
82 bs.ReadInt16(); 186 bs.ReadInt16();
83 break; 187 break;
84 case "YPTS": 188 case "YPTS":
85 h = bs.ReadInt16(); 189 fileHeight = bs.ReadInt16();
86 bs.ReadInt16(); 190 bs.ReadInt16();
87 break; 191 break;
88 case "ALTW": 192 case "ALTW":
89 eof = true; 193 eof = true;
90 Int16 heightScale = bs.ReadInt16(); 194 Int16 heightScale = bs.ReadInt16();
91 Int16 baseHeight = bs.ReadInt16(); 195 Int16 baseHeight = bs.ReadInt16();
92 retval = new TerrainChannel(w, h); 196 for (int y = 0; y < h; y++)
93 int x;
94 for (x = 0; x < w; x++)
95 { 197 {
96 int y; 198 for (int x = 0; x < w; x++)
97 for (y = 0; y < h; y++)
98 { 199 {
99 retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0; 200 retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0;
100 } 201 }
101 } 202 }
102 break; 203 break;
@@ -114,12 +215,92 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
114 215
115 public void SaveFile(string filename, ITerrainChannel map) 216 public void SaveFile(string filename, ITerrainChannel map)
116 { 217 {
117 throw new NotImplementedException(); 218 FileInfo file = new FileInfo(filename);
219 FileStream s = file.Open(FileMode.Create, FileAccess.Write);
220 SaveStream(s, map);
221
222 s.Close();
118 } 223 }
119 224
120 public void SaveStream(Stream stream, ITerrainChannel map) 225 public void SaveStream(Stream stream, ITerrainChannel map)
121 { 226 {
122 throw new NotImplementedException(); 227 BinaryWriter bs = new BinaryWriter(stream);
228
229 //find the max and min heights on the map
230 double heightMax = map[0,0];
231 double heightMin = map[0,0];
232
233 for (int y = 0; y < map.Height; y++)
234 {
235 for (int x = 0; x < map.Width; x++)
236 {
237 double current = map[x,y];
238 if (heightMax < current)
239 heightMax = current;
240 if (heightMin > current)
241 heightMin = current;
242 }
243 }
244
245 double baseHeight = Math.Floor( (heightMax + heightMin) / 2d );
246
247 double horizontalScale = Math.Ceiling((heightMax - heightMin));
248
249 // if we are completely flat add 1cm range to avoid NaN divisions
250 if (horizontalScale < 0.01d)
251 horizontalScale = 0.01d;
252
253 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
254
255 bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
256
257 bs.Write(enc.GetBytes("SIZE"));
258 bs.Write(Convert.ToInt16(Constants.RegionSize));
259 bs.Write(Convert.ToInt16(0)); // necessary padding
260
261 //The XPTS and YPTS chunks are not needed for square regions
262 //but L3DT won't load the terrain file properly without them.
263 bs.Write(enc.GetBytes("XPTS"));
264 bs.Write(Convert.ToInt16(Constants.RegionSize));
265 bs.Write(Convert.ToInt16(0)); // necessary padding
266
267 bs.Write(enc.GetBytes("YPTS"));
268 bs.Write(Convert.ToInt16(Constants.RegionSize));
269 bs.Write(Convert.ToInt16(0)); // necessary padding
270
271 bs.Write(enc.GetBytes("SCAL"));
272 bs.Write(ToLittleEndian(1f)); //we're going to say that 1 terrain unit is 1 metre
273 bs.Write(ToLittleEndian(1f));
274 bs.Write(ToLittleEndian(1f));
275
276 // as we are square and not projected on a sphere then the other
277 // header blocks are not required
278
279 // now write the elevation data
280 bs.Write(enc.GetBytes("ALTW"));
281 bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min
282 bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point
283
284 for (int y = 0; y < map.Height; y++)
285 {
286 for (int x = 0; x < map.Width; x++)
287 {
288 float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse
289
290 // clamp rounding issues
291 if (elevation > Int16.MaxValue)
292 elevation = Int16.MaxValue;
293 else if (elevation < Int16.MinValue)
294 elevation = Int16.MinValue;
295
296 bs.Write(Convert.ToInt16(elevation));
297 }
298 }
299
300 //This is only necessary for older versions of Terragen.
301 bs.Write(enc.GetBytes("EOF "));
302
303 bs.Close();
123 } 304 }
124 305
125 public string FileExtension 306 public string FileExtension
@@ -127,16 +308,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
127 get { return ".ter"; } 308 get { return ".ter"; }
128 } 309 }
129 310
130 public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h)
131 {
132 throw new NotImplementedException();
133 }
134
135 #endregion 311 #endregion
136 312
137 public override string ToString() 313 public override string ToString()
138 { 314 {
139 return "Terragen"; 315 return "Terragen";
140 } 316 }
317
318 /// <summary>
319 /// terragen SCAL floats need to be written intel ordered regardless of
320 /// big or little endian system
321 /// </summary>
322 /// <param name="number"></param>
323 /// <returns></returns>
324 private byte[] ToLittleEndian( float number)
325 {
326 byte[] retVal = BitConverter.GetBytes(number);
327 if (BitConverter.IsLittleEndian == false)
328 {
329 byte[] tmp = new byte[4];
330 for (int i = 0; i < 4; i++)
331 {
332 tmp[i] = retVal[3 - i];
333 }
334 retVal = tmp;
335
336 }
337 return retVal ;
338 }
339
141 } 340 }
142} 341}