aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorUbitUmarov2018-05-06 17:32:03 +0100
committerUbitUmarov2018-05-06 17:32:03 +0100
commitdffa6289666382166dd038e250cad94d24b88c6c (patch)
tree52e9b0ec61fb4f4b8a5486c9df6988b805e99215 /OpenSim
parentfix warp3d textures UV (diff)
downloadopensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.zip
opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.gz
opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.bz2
opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.xz
break nap a bit more, add options ExportMapAddScale, ExportMapAddRegionName and (warp3d) AverageTextureColorOnMapTile
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs419
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs104
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs29
4 files changed, 318 insertions, 235 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 226b330..ba6ebfc 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -56,7 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
56 56
57 private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[] 57 private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[]
58 { 58 {
59 Color.FromArgb(255, 164, 136, 117), 59// Color.FromArgb(255, 164, 136, 117),
60 Color.FromArgb(255, 255, 136, 117),
61
60 Color.FromArgb(255, 65, 87, 47), 62 Color.FromArgb(255, 65, 87, 47),
61 Color.FromArgb(255, 157, 145, 131), 63 Color.FromArgb(255, 157, 145, 131),
62 Color.FromArgb(255, 125, 128, 130) 64 Color.FromArgb(255, 125, 128, 130)
@@ -82,7 +84,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
82 84
83 public static Bitmap Splat(ITerrainChannel terrain, 85 public static Bitmap Splat(ITerrainChannel terrain,
84 UUID[] textureIDs, float[] startHeights, float[] heightRanges, 86 UUID[] textureIDs, float[] startHeights, float[] heightRanges,
85 Vector3d regionPosition, IAssetService assetService, bool textureTerrain) 87 uint regionPositionX,uint regionPositionY,
88 IAssetService assetService, bool textureTerrain, bool averagetextureTerrain)
86 { 89 {
87 Debug.Assert(textureIDs.Length == 4); 90 Debug.Assert(textureIDs.Length == 4);
88 Debug.Assert(startHeights.Length == 4); 91 Debug.Assert(startHeights.Length == 4);
@@ -90,70 +93,81 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
90 93
91 Bitmap[] detailTexture = new Bitmap[4]; 94 Bitmap[] detailTexture = new Bitmap[4];
92 95
96 byte[] mapColorsRed = new byte[4];
97 byte[] mapColorsGreen = new byte[4];
98 byte[] mapColorsBlue = new byte[4];
99
100 bool usecolors = false;
101
93 if (textureTerrain) 102 if (textureTerrain)
94 { 103 {
95 // Swap empty terrain textureIDs with default IDs 104 // Swap empty terrain textureIDs with default IDs
96 for (int i = 0; i < textureIDs.Length; i++) 105 for(int i = 0; i < textureIDs.Length; i++)
97 { 106 {
98 if (textureIDs[i] == UUID.Zero) 107 if(textureIDs[i] == UUID.Zero)
99 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; 108 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
100 } 109 }
101 110
102 #region Texture Fetching 111 #region Texture Fetching
103 112
104 if (assetService != null) 113 if(assetService != null)
105 { 114 {
106 for (int i = 0; i < 4; i++) 115 for(int i = 0; i < 4; i++)
107 { 116 {
108 AssetBase asset; 117 AssetBase asset = null;
109 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); 118 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
110 119
111 // Try to fetch a cached copy of the decoded/resized version of this texture 120 // Try to fetch a cached copy of the decoded/resized version of this texture
112 asset = assetService.GetCached(cacheID.ToString()); 121 // asset = assetService.GetCached(cacheID.ToString());
113 if (asset != null) 122 if(asset != null)
114 { 123 {
115 try 124 try
116 { 125 {
117 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) 126 using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
118 detailTexture[i] = (Bitmap)Image.FromStream(stream); 127 detailTexture[i] = (Bitmap)Image.FromStream(stream);
119 } 128 }
120 catch (Exception ex) 129 catch(Exception ex)
121 { 130 {
122 m_log.Warn("Failed to decode cached terrain texture " + cacheID + 131 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
123 " (textureID: " + textureIDs[i] + "): " + ex.Message); 132 " (textureID: " + textureIDs[i] + "): " + ex.Message);
124 } 133 }
134 if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb ||
135 detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
136 {
137 detailTexture[i].Dispose();
138 detailTexture[i] = null;
139 }
125 } 140 }
126 141
127 if (detailTexture[i] == null) 142 if(detailTexture[i] == null)
128 { 143 {
129 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG 144 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
130 asset = assetService.Get(textureIDs[i].ToString()); 145 asset = assetService.Get(textureIDs[i].ToString());
131 if (asset != null) 146 if(asset != null)
132 { 147 {
133 // m_log.DebugFormat( 148 // m_log.DebugFormat(
134 // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); 149 // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
135 150
136 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 151 try
137 catch (Exception ex) 152 {
153 detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data);
154 }
155 catch(Exception ex)
138 { 156 {
139 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); 157 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
140 } 158 }
141 } 159 }
142 160
143 if (detailTexture[i] != null) 161 if(detailTexture[i] != null)
144 { 162 {
145 // Make sure this texture is the correct size, otherwise resize 163 if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb ||
146 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 164 detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
147 { 165 using(Bitmap origBitmap = detailTexture[i])
148 using (Bitmap origBitmap = detailTexture[i]) 166 detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16);
149 {
150 detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
151 }
152 }
153 167
154 // Save the decoded and resized texture to the cache 168 // Save the decoded and resized texture to the cache
155 byte[] data; 169 byte[] data;
156 using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) 170 using(System.IO.MemoryStream stream = new System.IO.MemoryStream())
157 { 171 {
158 detailTexture[i].Save(stream, ImageFormat.Png); 172 detailTexture[i].Save(stream, ImageFormat.Png);
159 data = stream.ToArray(); 173 data = stream.ToArray();
@@ -180,91 +194,97 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
180 } 194 }
181 195
182 #endregion Texture Fetching 196 #endregion Texture Fetching
183 } 197 if(averagetextureTerrain)
184
185 // Fill in any missing textures with a solid color
186 for (int i = 0; i < 4; i++)
187 {
188 if (detailTexture[i] == null)
189 { 198 {
190 m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", 199 for(int t = 0; t < 4; t++)
191 LogHeader, i);
192 // Create a solid color texture for this layer
193 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
194 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
195 { 200 {
196 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) 201 usecolors = true;
197 gfx.FillRectangle(brush, 0, 0, 256, 256); 202 if(detailTexture[t] == null)
203 {
204 mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R;
205 mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G;
206 mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B;
207 continue;
208 }
209
210 int npixeis = 0;
211 int cR = 0;
212 int cG = 0;
213 int cB = 0;
214
215 BitmapData bmdata = detailTexture[t].LockBits(new Rectangle(0, 0, 16, 16),
216 ImageLockMode.ReadOnly, detailTexture[t].PixelFormat);
217
218 npixeis = bmdata.Height * bmdata.Width;
219 int ylen = bmdata.Height * bmdata.Stride;
220
221 unsafe
222 {
223 for(int y = 0; y < ylen; y += bmdata.Stride)
224 {
225 byte* ptrc = (byte*)bmdata.Scan0 + y;
226 for(int x = 0 ; x < bmdata.Width; ++x)
227 {
228 cR += *(ptrc++);
229 cG += *(ptrc++);
230 cB += *(ptrc++);
231 }
232 }
233
234 }
235 detailTexture[t].UnlockBits(bmdata);
236 detailTexture[t].Dispose();
237
238 mapColorsRed[t] = (byte)Util.Clamp(cR / npixeis, 0 , 255);
239 mapColorsGreen[t] = (byte)Util.Clamp(cG / npixeis, 0 , 255);
240 mapColorsBlue[t] = (byte)Util.Clamp(cB / npixeis, 0 , 255);
198 } 241 }
199 } 242 }
200 else 243 else
201 { 244 {
202 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 245 // Fill in any missing textures with a solid color
246 for(int i = 0; i < 4; i++)
203 { 247 {
204 detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); 248 if(detailTexture[i] == null)
249 {
250 m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", LogHeader, i);
251
252 // Create a solid color texture for this layer
253 detailTexture[i] = new Bitmap(16, 16, PixelFormat.Format24bppRgb);
254 using(Graphics gfx = Graphics.FromImage(detailTexture[i]))
255 {
256 using(SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
257 gfx.FillRectangle(brush, 0, 0, 16, 16);
258 }
259 }
260 else
261 {
262 if(detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
263 {
264 using(Bitmap origBitmap = detailTexture[i])
265 detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16);
266 }
267 }
205 } 268 }
206 } 269 }
207 } 270 }
208 271 else
209 #region Layer Map
210
211 float[,] layermap = new float[256, 256];
212
213 // Scale difference between actual region size and the 256 texture being created
214 int xFactor = terrain.Width / 256;
215 int yFactor = terrain.Height / 256;
216
217 // Create 'layermap' where each value is the fractional layer number to place
218 // at that point. For instance, a value of 1.345 gives the blending of
219 // layer 1 and layer 2 for that point.
220 for (int y = 0; y < 256; y++)
221 { 272 {
222 for (int x = 0; x < 256; x++) 273 usecolors = true;
274 for(int t = 0; t < 4; t++)
223 { 275 {
224 float height = (float)terrain[x * xFactor, y * yFactor]; 276 mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R;
225 277 mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G;
226 float pctX = (float)x / 255f; 278 mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B;
227 float pctY = (float)y / 255f;
228
229 // Use bilinear interpolation between the four corners of start height and
230 // height range to select the current values at this position
231 float startHeight = ImageUtils.Bilinear(
232 startHeights[0],
233 startHeights[2],
234 startHeights[1],
235 startHeights[3],
236 pctX, pctY);
237 startHeight = Utils.Clamp(startHeight, 0f, 255f);
238
239 float heightRange = ImageUtils.Bilinear(
240 heightRanges[0],
241 heightRanges[2],
242 heightRanges[1],
243 heightRanges[3],
244 pctX, pctY);
245 heightRange = Utils.Clamp(heightRange, 0f, 255f);
246
247 // Generate two frequencies of perlin noise based on our global position
248 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
249 Vector3 vec = new Vector3
250 (
251 ((float)regionPosition.X + (x * xFactor)) * 0.20319f,
252 ((float)regionPosition.Y + (y * yFactor)) * 0.20319f,
253 height * 0.25f
254 );
255
256 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
257 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
258 float noise = (lowFreq + highFreq) * 2f;
259
260 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
261 float layer = ((height + noise - startHeight) / heightRange) * 4f;
262 if (Single.IsNaN(layer))
263 layer = 0f;
264 layermap[x, y] = Utils.Clamp(layer, 0f, 3f);
265 } 279 }
266 } 280 }
267 281
282 #region Layer Map
283
284 // Scale difference between actual region size and the 256 texture being created
285 float xFactor = terrain.Width / 256f;
286 float yFactor = terrain.Height / 256f;
287
268 #endregion Layer Map 288 #endregion Layer Map
269 289
270 #region Texture Compositing 290 #region Texture Compositing
@@ -274,115 +294,152 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
274 294
275 // Unsafe work as we lock down the source textures for quicker access and access the 295 // Unsafe work as we lock down the source textures for quicker access and access the
276 // pixel data directly 296 // pixel data directly
277 unsafe 297 if(usecolors)
278 { 298 {
279 // Get handles to all of the texture data arrays 299 unsafe
280 BitmapData[] datas = new BitmapData[]
281 {
282 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
283 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
284 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
285 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
286 };
287
288 // Compute size of each pixel data (used to address into the pixel data array)
289 int[] comps = new int[]
290 {
291 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
292 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
293 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
294 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
295 };
296
297 for (int y = 0; y < 256; y++)
298 { 300 {
299 for (int x = 0; x < 256; x++) 301 for(int y = 0; y < 256; ++y)
300 { 302 {
301 float layer = layermap[x, y]; 303 int ty = (int)((255 - y) * yFactor);
304 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride;
302 305
303 // Select two textures 306 for(int x = 0; x < 256; ++x)
304 int l0 = (int)Math.Floor(layer); 307 {
305 int l1 = Math.Min(l0 + 1, 3); 308 int tx = (int)(x * xFactor);
309 float height = (float)terrain[tx, ty];
310 float layer = getLayerTex(height, x, (255 - y),
311 (uint)tx + regionPositionX, (uint)ty + regionPositionY,
312 startHeights, heightRanges);
306 313
307 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; 314 // Select two textures
308 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; 315 int l0 = (int)layer;
309 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; 316 int l1 = Math.Min(l0 + 1, 3);
310 317
311 float aB = *(ptrA + 0); 318 float layerDiff = layer - l0;
312 float aG = *(ptrA + 1);
313 float aR = *(ptrA + 2);
314 319
315 float bB = *(ptrB + 0); 320 float a = mapColorsRed[l0];
316 float bG = *(ptrB + 1); 321 float b = mapColorsRed[l1];
317 float bR = *(ptrB + 2); 322 *(ptrO++) = (byte)(a + layerDiff * (b - a));
318 323
319 float layerDiff = layer - l0; 324 a = mapColorsGreen[l0];
325 b = mapColorsGreen[l1];
326 *(ptrO++) = (byte)(a + layerDiff * (b - a));
320 327
321 // Interpolate between the two selected textures 328 a = mapColorsBlue[l0];
322 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); 329 b = mapColorsBlue[l1];
323 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); 330 *(ptrO++) = (byte)(a + layerDiff * (b - a));
324 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); 331 }
325 } 332 }
326 } 333 }
327
328 for (int i = 0; i < detailTexture.Length; i++)
329 detailTexture[i].UnlockBits(datas[i]);
330 } 334 }
335 else
336 {
337 unsafe
338 {
339 // Get handles to all of the texture data arrays
340 BitmapData[] datas = new BitmapData[]
341 {
342 detailTexture[0].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
343 detailTexture[1].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
344 detailTexture[2].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
345 detailTexture[3].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
346 };
347
348 for(int y = 0; y < 256; y++)
349 {
350 int ty = (int)((255 - y) * yFactor);
351 int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride;
352
353 for(int x = 0; x < 256; x++)
354 {
355 int tx = (int)(x * xFactor);
356 float height = (float)terrain[tx, ty];
357 float layer = getLayerTex(height, x, (255 - y),
358 (uint)tx + regionPositionX, (uint)ty + regionPositionY,
359 startHeights, heightRanges);
360
361 // Select two textures
362 int l0 = (int)layer;
363 int l1 = Math.Min(l0 + 1, 3);
364
365 int patchOffset = (tx & 0x0f) * 3 + ypatch;
366 byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset;
367 byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset;
368 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
369
370 float aB = *(ptrA + 0);
371 float aG = *(ptrA + 1);
372 float aR = *(ptrA + 2);
373
374 float bB = *(ptrB + 0);
375 float bG = *(ptrB + 1);
376 float bR = *(ptrB + 2);
377
378 float layerDiff = layer - l0;
379
380 // Interpolate between the two selected textures
381 *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB));
382 *(ptrO + 1) = (byte)(aG + layerDiff * (bG - aG));
383 *(ptrO + 2) = (byte)(aR + layerDiff * (bR - aR));
384 }
385 }
386
387 for(int i = 0; i < detailTexture.Length; i++)
388 detailTexture[i].UnlockBits(datas[i]);
389 }
331 390
332 for (int i = 0; i < detailTexture.Length; i++) 391 for(int i = 0; i < detailTexture.Length; i++)
333 if (detailTexture[i] != null) 392 if(detailTexture[i] != null)
334 detailTexture[i].Dispose(); 393 detailTexture[i].Dispose();
394 }
335 395
336 output.UnlockBits(outputData); 396 output.UnlockBits(outputData);
337 397
338 // We generated the texture upside down, so flip it 398output.Save("terr.png",ImageFormat.Png);
339 output.RotateFlip(RotateFlipType.RotateNoneFlipY);
340 399
341 #endregion Texture Compositing 400 #endregion Texture Compositing
342 401
343 return output; 402 return output;
344 } 403 }
345 404
346 public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight) 405 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
347 { 406 private static float getLayerTex(float height, int x, int y, uint sourceX, uint sourceY,
348 m_log.DebugFormat("{0} ResizeBitmap. From <{1},{2}> to <{3},{4}>", 407 float[] startHeights, float[] heightRanges)
349 LogHeader, b.Width, b.Height, nWidth, nHeight);
350 Bitmap result = new Bitmap(nWidth, nHeight);
351 using (Graphics g = Graphics.FromImage(result))
352 g.DrawImage(b, 0, 0, nWidth, nHeight);
353 b.Dispose();
354 return result;
355 }
356 public static Bitmap SplatSimple(float[] heightmap)
357 { 408 {
358 const float BASE_HSV_H = 93f / 360f; 409 float pctX = (float)x / 255f;
359 const float BASE_HSV_S = 44f / 100f; 410 float pctY = (float)y / 255f;
360 const float BASE_HSV_V = 34f / 100f; 411
361 412 // Use bilinear interpolation between the four corners of start height and
362 Bitmap img = new Bitmap(256, 256); 413 // height range to select the current values at this position
363 BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 414 float startHeight = ImageUtils.Bilinear(
364 415 startHeights[0], startHeights[2],
365 unsafe 416 startHeights[1], startHeights[3],
366 { 417 pctX, pctY);
367 for (int y = 255; y >= 0; y--) 418 startHeight = Utils.Clamp(startHeight, 0f, 255f);
368 { 419
369 for (int x = 0; x < 256; x++) 420 float heightRange = ImageUtils.Bilinear(
370 { 421 heightRanges[0], heightRanges[2],
371 float normHeight = heightmap[y * 256 + x] / 255f; 422 heightRanges[1], heightRanges[3],
372 normHeight = Utils.Clamp(normHeight, BASE_HSV_V, 1.0f); 423 pctX, pctY);
373 424 heightRange = Utils.Clamp(heightRange, 0f, 255f);
374 Color4 color = Color4.FromHSV(BASE_HSV_H, BASE_HSV_S, normHeight); 425
375 426 // Generate two frequencies of perlin noise based on our global position
376 byte* ptr = (byte*)bitmapData.Scan0 + y * bitmapData.Stride + x * 3; 427 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
377 *(ptr + 0) = (byte)(color.B * 255f); 428 Vector3 vec = new Vector3
378 *(ptr + 1) = (byte)(color.G * 255f); 429 (
379 *(ptr + 2) = (byte)(color.R * 255f); 430 sourceX * 0.20319f,
380 } 431 sourceY * 0.20319f,
381 } 432 height * 0.25f
382 } 433 );
383 434
384 img.UnlockBits(bitmapData); 435 float noise = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 13.0f;
385 return img; 436 noise += Perlin.turbulence2(vec.X, vec.Y, 2f) * 4.5f;
437
438 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
439 float layer = ((height + noise - startHeight) / heightRange) * 4f;
440 if(Single.IsNaN(layer))
441 return 0;
442 return Utils.Clamp(layer, 0f, 3f);
386 } 443 }
387 } 444 }
388} 445}
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs
index 472f86e..5ea4d29 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
57 NearPlaneDistance = nearPlaneDist; 57 NearPlaneDistance = nearPlaneDist;
58 Width = width; 58 Width = width;
59 Height = height; 59 Height = height;
60 Orthographic = false;
60 } 61 }
61 62
62 public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight) 63 public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight)
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 387248c..9186fae 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -73,6 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
73 private IConfigSource m_config; 73 private IConfigSource m_config;
74 private bool m_drawPrimVolume = true; // true if should render the prims on the tile 74 private bool m_drawPrimVolume = true; // true if should render the prims on the tile
75 private bool m_textureTerrain = true; // true if to create terrain splatting texture 75 private bool m_textureTerrain = true; // true if to create terrain splatting texture
76 private bool m_textureAvegareTerrain = true; // replace terrain textures by their average color
76 private bool m_texturePrims = true; // true if should texture the rendered prims 77 private bool m_texturePrims = true; // true if should texture the rendered prims
77 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it 78 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
78 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes 79 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
@@ -96,16 +97,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
96 97
97 m_Enabled = true; 98 m_Enabled = true;
98 99
99 m_drawPrimVolume 100 m_drawPrimVolume =
100 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); 101 Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
101 m_textureTerrain 102 m_textureTerrain =
102 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); 103 Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
103 m_texturePrims 104 m_textureAvegareTerrain =
104 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); 105 Util.GetConfigVarFromSections<bool>(m_config, "AverageTextureColorOnMapTile", configSections, m_textureAvegareTerrain);
105 m_texturePrimSize 106 if(m_textureAvegareTerrain)
106 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); 107 m_textureTerrain = true;
107 m_renderMeshes 108 m_texturePrims =
108 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); 109 Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
110 m_texturePrimSize =
111 Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
112 m_renderMeshes =
113 Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
114
109 } 115 }
110 116
111 public void AddRegion(Scene scene) 117 public void AddRegion(Scene scene)
@@ -168,13 +174,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
168 Vector3 camPos = new Vector3( 174 Vector3 camPos = new Vector3(
169 (m_scene.RegionInfo.RegionSizeX) * 0.5f, 175 (m_scene.RegionInfo.RegionSizeX) * 0.5f,
170 (m_scene.RegionInfo.RegionSizeY) * 0.5f, 176 (m_scene.RegionInfo.RegionSizeY) * 0.5f,
171 221.7025033688163f); 177 250f);
172 // Viewport viewing down onto the region 178 // Viewport viewing down onto the region
173 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 179 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
174 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, 180 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
175 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY); 181 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY);
176 182
177 Bitmap tile = CreateMapTile(viewport, false); 183 Bitmap tile = CreateMapTile(viewport);
178 m_primMesher = null; 184 m_primMesher = null;
179 return tile; 185 return tile;
180/* 186/*
@@ -187,10 +193,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
187 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 193 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
188 { 194 {
189 Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height); 195 Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height);
190 return CreateMapTile(viewport, useTextures); 196 return CreateMapTile(viewport);
191 } 197 }
192 198
193 public Bitmap CreateMapTile(Viewport viewport, bool useTextures) 199 public Bitmap CreateMapTile(Viewport viewport)
194 { 200 {
195 m_colors.Clear(); 201 m_colors.Clear();
196 202
@@ -207,29 +213,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
207 warp_Vector pos = ConvertVector(viewport.Position); 213 warp_Vector pos = ConvertVector(viewport.Position);
208 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); 214 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection));
209 215
216
217 renderer.Scene.defaultCamera.setOrthographic(true, viewport.OrthoWindowWidth, viewport.OrthoWindowHeight);
218
210 renderer.Scene.defaultCamera.setPos(pos); 219 renderer.Scene.defaultCamera.setPos(pos);
211 renderer.Scene.defaultCamera.lookAt(lookat); 220 renderer.Scene.defaultCamera.lookAt(lookat);
212
213 if (viewport.Orthographic)
214 {
215 renderer.Scene.defaultCamera.setOrthographic(true,viewport.OrthoWindowWidth, viewport.OrthoWindowHeight);
216 }
217 else
218 {
219 float fov = viewport.FieldOfView;
220 fov *= 1.75f; // FIXME: ???
221 renderer.Scene.defaultCamera.setFov(fov);
222 }
223
224 #endregion Camera 221 #endregion Camera
225 222
226 renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); 223 renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40));
227 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); 224 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
228 225
229 CreateWater(renderer); 226 CreateWater(renderer);
230 CreateTerrain(renderer, m_textureTerrain); 227 CreateTerrain(renderer);
231 if (m_drawPrimVolume) 228 if (m_drawPrimVolume)
232 CreateAllPrims(renderer, useTextures); 229 CreateAllPrims(renderer);
233 230
234 renderer.Render(); 231 renderer.Render();
235 Bitmap bitmap = renderer.Scene.getImage(); 232 Bitmap bitmap = renderer.Scene.getImage();
@@ -286,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
286 // Add a terrain to the renderer. 283 // Add a terrain to the renderer.
287 // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for 284 // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for
288 // full resolution. This saves a lot of memory especially for very large regions. 285 // full resolution. This saves a lot of memory especially for very large regions.
289 private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) 286 private void CreateTerrain(WarpRenderer renderer)
290 { 287 {
291 ITerrainChannel terrain = m_scene.Heightmap; 288 ITerrainChannel terrain = m_scene.Heightmap;
292 289
@@ -296,11 +293,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
296 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding 293 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
297 float diff = regionsx / 256f; 294 float diff = regionsx / 256f;
298 295
299 int npointsx = (int)(regionsx / diff) + 1; 296 int npointsx = (int)(regionsx / diff);
300 int npointsy = (int)(regionsy / diff) + 1; 297 int npointsy = (int)(regionsy / diff);
301 298
302 float invsx = 1.0f / (npointsx * diff); 299 float invsx = 1.0f / (npointsx);
303 float invsy = 1.0f / (npointsy * diff); 300 float invsy = 1.0f / (npointsy);
301
302 npointsx++;
303 npointsy++;
304 304
305 // Create all the vertices for the terrain 305 // Create all the vertices for the terrain
306 warp_Object obj = new warp_Object(); 306 warp_Object obj = new warp_Object();
@@ -310,6 +310,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
310 { 310 {
311 for (x = 0; x < regionsx; x += diff) 311 for (x = 0; x < regionsx; x += diff)
312 { 312 {
313 if(x == 48 && y == 36)
314 {
315
316 }
313 pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]); 317 pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]);
314 obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy)); 318 obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy));
315 } 319 }
@@ -378,17 +382,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
378 warp_Texture texture; 382 warp_Texture texture;
379 using (Bitmap image = TerrainSplat.Splat( 383 using (Bitmap image = TerrainSplat.Splat(
380 terrain, textureIDs, startHeights, heightRanges, 384 terrain, textureIDs, startHeights, heightRanges,
381 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 385 m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY,
386 m_scene.AssetService, m_textureTerrain, m_textureAvegareTerrain))
382 texture = new warp_Texture(image); 387 texture = new warp_Texture(image);
383 388
384 warp_Material material = new warp_Material(texture); 389 warp_Material material = new warp_Material(texture);
385 material.setReflectivity(50); 390// material.setReflectivity(50);
386 renderer.Scene.addMaterial("TerrainColor", material); 391 renderer.Scene.addMaterial("TerrainColor", material);
387 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif 392// renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
388 renderer.SetObjectMaterial("Terrain", "TerrainColor"); 393 renderer.SetObjectMaterial("Terrain", "TerrainColor");
389 } 394 }
390 395
391 private void CreateAllPrims(WarpRenderer renderer, bool useTextures) 396 private void CreateAllPrims(WarpRenderer renderer)
392 { 397 {
393 if (m_primMesher == null) 398 if (m_primMesher == null)
394 return; 399 return;
@@ -397,13 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
397 delegate(SceneObjectGroup group) 402 delegate(SceneObjectGroup group)
398 { 403 {
399 foreach (SceneObjectPart child in group.Parts) 404 foreach (SceneObjectPart child in group.Parts)
400 CreatePrim(renderer, child, useTextures); 405 CreatePrim(renderer, child);
401 } 406 }
402 ); 407 );
403 } 408 }
404 409
405 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, 410 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim)
406 bool useTextures)
407 { 411 {
408 const float MIN_SIZE_SQUARE = 4f; 412 const float MIN_SIZE_SQUARE = 4f;
409 413
@@ -489,19 +493,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
489 } 493 }
490 494
491 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); 495 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
492 Color4 faceColor = GetFaceColor(teFace); 496 Color4 faceColor = teFace.RGBA;
493 string materialName = String.Empty; 497 string materialName = String.Empty;
494 if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) 498 if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize)
495 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); 499 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
496 else 500 else
497 materialName = GetOrCreateMaterial(renderer, faceColor); 501 materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace));
498 502
499 faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); 503 faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y);
500 504
501 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
502 warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); 505 warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation());
503 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); 506 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
504 faceObj.transform(m); 507 faceObj.transform(m);
508
509 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
505 faceObj.setPos(primPos); 510 faceObj.setPos(primPos);
506 511
507 renderer.Scene.addObject(meshName, faceObj); 512 renderer.Scene.addObject(meshName, faceObj);
@@ -645,7 +650,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
645 650
646 private static warp_Quaternion ConvertQuaternion(Quaternion quat) 651 private static warp_Quaternion ConvertQuaternion(Quaternion quat)
647 { 652 {
648 return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W); 653 return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W);
649 } 654 }
650 655
651 private static int ConvertColor(Color4 color) 656 private static int ConvertColor(Color4 color)
@@ -778,18 +783,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
778 /// <param name="width">New width</param> 783 /// <param name="width">New width</param>
779 /// <param name="height">New height</param> 784 /// <param name="height">New height</param>
780 /// <returns>Resized image</returns> 785 /// <returns>Resized image</returns>
781 public static Bitmap ResizeImage(Image image, int width, int height) 786 public static Bitmap ResizeImageSolid(Image image, int width, int height)
782 { 787 {
783 Bitmap result = new Bitmap(width, height); 788 Bitmap result = new Bitmap(width, height, PixelFormat.Format24bppRgb);
784 789
790 using (ImageAttributes atrib = new ImageAttributes())
785 using (Graphics graphics = Graphics.FromImage(result)) 791 using (Graphics graphics = Graphics.FromImage(result))
786 { 792 {
793 atrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
787 graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 794 graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
788 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 795 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
789 graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 796 graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
790 graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 797 graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
791 798
792 graphics.DrawImage(image, 0, 0, result.Width, result.Height); 799 graphics.DrawImage(image,new Rectangle(0,0, result.Width, result.Height),
800 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, atrib);
793 } 801 }
794 802
795 return result; 803 return result;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 476d90a..4b14c71 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -93,6 +93,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
93 private const double expireResponsesTime = 120.0; // 2 minutes ? 93 private const double expireResponsesTime = 120.0; // 2 minutes ?
94 //private int CacheRegionsDistance = 256; 94 //private int CacheRegionsDistance = 256;
95 95
96 private bool m_exportPrintScale = false; // prints the scale of map in meters on exported map
97 private bool m_exportPrintRegionName = false; // prints the region name exported map
98
96 #region INonSharedRegionModule Members 99 #region INonSharedRegionModule Members
97 public virtual void Initialise(IConfigSource config) 100 public virtual void Initialise(IConfigSource config)
98 { 101 {
@@ -103,6 +106,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
103 m_Enabled = true; 106 m_Enabled = true;
104 107
105 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60); 108 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
109
110 m_exportPrintScale =
111 Util.GetConfigVarFromSections<bool>(config, "ExportMapAddScale", configSections, m_exportPrintScale);
112 m_exportPrintRegionName =
113 Util.GetConfigVarFromSections<bool>(config, "ExportMapAddRegionName", configSections, m_exportPrintRegionName);
106 } 114 }
107 115
108 public virtual void AddRegion(Scene scene) 116 public virtual void AddRegion(Scene scene)
@@ -1418,14 +1426,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1418 int spanY = endY - startY + 2; 1426 int spanY = endY - startY + 2;
1419 1427
1420 Bitmap mapTexture = new Bitmap(spanX, spanY); 1428 Bitmap mapTexture = new Bitmap(spanX, spanY);
1429 ImageAttributes gatrib = new ImageAttributes();
1421 Graphics g = Graphics.FromImage(mapTexture); 1430 Graphics g = Graphics.FromImage(mapTexture);
1431 gatrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
1422 g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 1432 g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
1423 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 1433 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
1424 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 1434 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
1425 g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 1435 g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
1426 1436
1427 SolidBrush sea = new SolidBrush(Color.DarkBlue); 1437 SolidBrush sea = new SolidBrush(Color.DarkBlue);
1428 g.FillRectangle(sea, 0, 0, spanX - 1, spanY - 1); 1438 g.FillRectangle(sea, 0, 0, spanX, spanY);
1429 sea.Dispose(); 1439 sea.Dispose();
1430 1440
1431 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1441 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
@@ -1457,8 +1467,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1457 int y = r.RegionLocY - startY; 1467 int y = r.RegionLocY - startY;
1458 int sx = r.RegionSizeX; 1468 int sx = r.RegionSizeX;
1459 int sy = r.RegionSizeY; 1469 int sy = r.RegionSizeY;
1460 g.DrawImage(image, x, spanY - y - sy, sx, sy); // y origin is top 1470 // y origin is top
1461 if(r.RegionHandle == m_scene.RegionInfo.RegionHandle) 1471 g.DrawImage(image,new Rectangle(x, spanY - y - sy, sx, sy),
1472 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, gatrib);
1473
1474 if(m_exportPrintRegionName && r.RegionHandle == m_scene.RegionInfo.RegionHandle)
1462 { 1475 {
1463 SizeF stringSize = g.MeasureString(r.RegionName, drawFont); 1476 SizeF stringSize = g.MeasureString(r.RegionName, drawFont);
1464 g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); 1477 g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height);
@@ -1469,13 +1482,17 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1469 if(image != null) 1482 if(image != null)
1470 image.Dispose(); 1483 image.Dispose();
1471 1484
1472 String drawString = string.Format("{0}m x {1}m", spanX, spanY); 1485 if(m_exportPrintScale)
1473 g.DrawString(drawString, drawFont, drawBrush, 30, 30); 1486 {
1487 String drawString = string.Format("{0}m x {1}m", spanX, spanY);
1488 g.DrawString(drawString, drawFont, drawBrush, 30, 30);
1489 }
1474 1490
1475 drawBrush.Dispose(); 1491 drawBrush.Dispose();
1476 drawFont.Dispose(); 1492 drawFont.Dispose();
1477 } 1493 }
1478 1494
1495 gatrib.Dispose();
1479 g.Dispose(); 1496 g.Dispose();
1480 1497
1481 mapTexture.Save(exportPath, ImageFormat.Jpeg); 1498 mapTexture.Save(exportPath, ImageFormat.Jpeg);