diff options
-rw-r--r-- | OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs | 187 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | 296 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 64 | ||||
-rwxr-xr-x | bin/Warp3D.dll | bin | 69632 -> 73728 bytes |
4 files changed, 325 insertions, 222 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 95fa567..51f8f75 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs | |||
@@ -80,10 +80,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
80 | /// Note we create a 256x256 dimension texture even if the actual terrain is larger. | 80 | /// Note we create a 256x256 dimension texture even if the actual terrain is larger. |
81 | /// </remarks> | 81 | /// </remarks> |
82 | 82 | ||
83 | public static Bitmap Splat(ITerrainChannel terrain, | 83 | public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs, |
84 | UUID[] textureIDs, float[] startHeights, float[] heightRanges, | 84 | float[] startHeights, float[] heightRanges, |
85 | uint regionPositionX,uint regionPositionY, | 85 | uint regionPositionX,uint regionPositionY, |
86 | IAssetService assetService, bool textureTerrain, bool averagetextureTerrain, bool FlipedY) | 86 | IAssetService assetService, IJ2KDecoder decoder, |
87 | bool textureTerrain, bool averagetextureTerrain, bool FlipedY, | ||
88 | int twidth, int theight) | ||
87 | { | 89 | { |
88 | Debug.Assert(textureIDs.Length == 4); | 90 | Debug.Assert(textureIDs.Length == 4); |
89 | Debug.Assert(startHeights.Length == 4); | 91 | Debug.Assert(startHeights.Length == 4); |
@@ -113,27 +115,29 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
113 | for(int i = 0; i < 4; i++) | 115 | for(int i = 0; i < 4; i++) |
114 | { | 116 | { |
115 | AssetBase asset = null; | 117 | AssetBase asset = null; |
116 | UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); | 118 | |
119 | // asset cache indexes are strings | ||
120 | string cacheName ="MAP-Patch" + textureIDs[i].ToString(); | ||
117 | 121 | ||
118 | // Try to fetch a cached copy of the decoded/resized version of this texture | 122 | // Try to fetch a cached copy of the decoded/resized version of this texture |
119 | // asset = assetService.GetCached(cacheID.ToString()); | 123 | asset = assetService.GetCached(cacheName); |
120 | if(asset != null) | 124 | if(asset != null) |
121 | { | 125 | { |
122 | try | 126 | try |
123 | { | 127 | { |
124 | using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) | 128 | using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) |
125 | detailTexture[i] = (Bitmap)Image.FromStream(stream); | 129 | detailTexture[i] = (Bitmap)Image.FromStream(stream); |
130 | |||
131 | if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || | ||
132 | detailTexture[i].Width != 16 || detailTexture[i].Height != 16) | ||
133 | { | ||
134 | detailTexture[i].Dispose(); | ||
135 | detailTexture[i] = null; | ||
136 | } | ||
126 | } | 137 | } |
127 | catch(Exception ex) | 138 | catch(Exception ex) |
128 | { | 139 | { |
129 | m_log.Warn("Failed to decode cached terrain texture " + cacheID + | 140 | m_log.Warn("Failed to decode cached terrain patch texture" + textureIDs[i] + "): " + ex.Message); |
130 | " (textureID: " + textureIDs[i] + "): " + ex.Message); | ||
131 | } | ||
132 | if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || | ||
133 | detailTexture[i].Width != 16 || detailTexture[i].Height != 16) | ||
134 | { | ||
135 | detailTexture[i].Dispose(); | ||
136 | detailTexture[i] = null; | ||
137 | } | 141 | } |
138 | } | 142 | } |
139 | 143 | ||
@@ -143,12 +147,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
143 | asset = assetService.Get(textureIDs[i].ToString()); | 147 | asset = assetService.Get(textureIDs[i].ToString()); |
144 | if(asset != null) | 148 | if(asset != null) |
145 | { | 149 | { |
146 | // m_log.DebugFormat( | ||
147 | // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); | ||
148 | |||
149 | try | 150 | try |
150 | { | 151 | { |
151 | detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); | 152 | detailTexture[i] = (Bitmap)decoder.DecodeToImage(asset.Data); |
152 | } | 153 | } |
153 | catch(Exception ex) | 154 | catch(Exception ex) |
154 | { | 155 | { |
@@ -177,8 +178,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
177 | Data = data, | 178 | Data = data, |
178 | Description = "PNG", | 179 | Description = "PNG", |
179 | Flags = AssetFlags.Collectable, | 180 | Flags = AssetFlags.Collectable, |
180 | FullID = cacheID, | 181 | FullID = UUID.Zero, |
181 | ID = cacheID.ToString(), | 182 | ID = cacheName, |
182 | Local = true, | 183 | Local = true, |
183 | Name = String.Empty, | 184 | Name = String.Empty, |
184 | Temporary = true, | 185 | Temporary = true, |
@@ -279,46 +280,61 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
279 | 280 | ||
280 | #region Layer Map | 281 | #region Layer Map |
281 | 282 | ||
282 | // Scale difference between actual region size and the 256 texture being created | 283 | float xFactor = terrain.Width / twidth; |
283 | float xFactor = terrain.Width / 256f; | 284 | float yFactor = terrain.Height / theight; |
284 | float yFactor = terrain.Height / 256f; | ||
285 | 285 | ||
286 | #endregion Layer Map | 286 | #endregion Layer Map |
287 | 287 | ||
288 | #region Texture Compositing | 288 | #region Texture Compositing |
289 | 289 | ||
290 | Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); | 290 | Bitmap output = new Bitmap(twidth, theight, PixelFormat.Format24bppRgb); |
291 | BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); | 291 | BitmapData outputData = output.LockBits(new Rectangle(0, 0, twidth, theight), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); |
292 | 292 | ||
293 | // Unsafe work as we lock down the source textures for quicker access and access the | 293 | // Unsafe work as we lock down the source textures for quicker access and access the |
294 | // pixel data directly | 294 | // pixel data directly |
295 | float invtwitdthMinus1 = 1.0f / (twidth - 1); | ||
296 | float invtheightMinus1 = 1.0f / (theight - 1); | ||
297 | int ty; | ||
298 | int tx; | ||
299 | float pctx; | ||
300 | float pcty; | ||
301 | float height; | ||
302 | float layer; | ||
303 | float layerDiff; | ||
304 | int l0; | ||
305 | int l1; | ||
306 | |||
295 | if(usecolors) | 307 | if(usecolors) |
296 | { | 308 | { |
309 | float a; | ||
310 | float b; | ||
297 | if(FlipedY) | 311 | if(FlipedY) |
298 | { | 312 | { |
299 | unsafe | 313 | unsafe |
300 | { | 314 | { |
301 | for(int y = 0; y < 256; ++y) | 315 | for(int y = 0; y < theight; ++y) |
302 | { | 316 | { |
303 | int ty = (int)(y * yFactor); | 317 | ty = (int)(y * yFactor); |
318 | pcty = y * invtheightMinus1; | ||
304 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; | 319 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; |
305 | 320 | ||
306 | for(int x = 0; x < 256; ++x) | 321 | for(int x = 0; x < twidth; ++x) |
307 | { | 322 | { |
308 | int tx = (int)(x * xFactor); | 323 | tx = (int)(x * xFactor); |
309 | float height = (float)terrain[tx, ty]; | 324 | pctx = x * invtwitdthMinus1; |
310 | float layer = getLayerTex(height, x, y, | 325 | height = (float)terrain[tx, ty]; |
326 | layer = getLayerTex(height, pctx, pcty, | ||
311 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | 327 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, |
312 | startHeights, heightRanges); | 328 | startHeights, heightRanges); |
313 | 329 | ||
314 | // Select two textures | 330 | // Select two textures |
315 | int l0 = (int)layer; | 331 | l0 = (int)layer; |
316 | int l1 = Math.Min(l0 + 1, 3); | 332 | l1 = Math.Min(l0 + 1, 3); |
317 | 333 | ||
318 | float layerDiff = layer - l0; | 334 | layerDiff = layer - l0; |
319 | 335 | ||
320 | float a = mapColorsRed[l0]; | 336 | a = mapColorsRed[l0]; |
321 | float b = mapColorsRed[l1]; | 337 | b = mapColorsRed[l1]; |
322 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); | 338 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); |
323 | 339 | ||
324 | a = mapColorsGreen[l0]; | 340 | a = mapColorsGreen[l0]; |
@@ -336,27 +352,28 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
336 | { | 352 | { |
337 | unsafe | 353 | unsafe |
338 | { | 354 | { |
339 | for(int y = 0; y < 256; ++y) | 355 | for(int y = 0; y < theight; ++y) |
340 | { | 356 | { |
341 | int ty = (int)((255 - y) * yFactor); | 357 | ty = (int)((theight - y -1) * yFactor); |
358 | pcty = 1.0f - y * invtheightMinus1; | ||
342 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; | 359 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; |
343 | 360 | ||
344 | for(int x = 0; x < 256; ++x) | 361 | for(int x = 0; x < twidth; ++x) |
345 | { | 362 | { |
346 | int tx = (int)(x * xFactor); | 363 | tx = (int)(x * xFactor); |
347 | float height = (float)terrain[tx, ty]; | 364 | pctx = x * invtwitdthMinus1; |
348 | float layer = getLayerTex(height, x, (255 - y), | 365 | height = (float)terrain[tx, ty]; |
366 | layer = getLayerTex(height, pctx , pcty, | ||
349 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | 367 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, |
350 | startHeights, heightRanges); | 368 | startHeights, heightRanges); |
351 | 369 | ||
352 | // Select two textures | 370 | // Select two textures |
353 | int l0 = (int)layer; | 371 | l0 = (int)layer; |
354 | int l1 = Math.Min(l0 + 1, 3); | 372 | l1 = Math.Min(l0 + 1, 3); |
355 | 373 | ||
356 | float layerDiff = layer - l0; | 374 | layerDiff = layer - l0; |
357 | 375 | a = mapColorsRed[l0]; | |
358 | float a = mapColorsRed[l0]; | 376 | b = mapColorsRed[l1]; |
359 | float b = mapColorsRed[l1]; | ||
360 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); | 377 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); |
361 | 378 | ||
362 | a = mapColorsGreen[l0]; | 379 | a = mapColorsGreen[l0]; |
@@ -373,6 +390,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
373 | } | 390 | } |
374 | else | 391 | else |
375 | { | 392 | { |
393 | float aB; | ||
394 | float aG; | ||
395 | float aR; | ||
396 | float bB; | ||
397 | float bG; | ||
398 | float bR; | ||
376 | unsafe | 399 | unsafe |
377 | { | 400 | { |
378 | // Get handles to all of the texture data arrays | 401 | // Get handles to all of the texture data arrays |
@@ -386,37 +409,38 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
386 | 409 | ||
387 | if(FlipedY) | 410 | if(FlipedY) |
388 | { | 411 | { |
389 | for(int y = 0; y < 256; y++) | 412 | for(int y = 0; y < theight; y++) |
390 | { | 413 | { |
391 | int ty = (int)(y * yFactor); | 414 | ty = (int)(y * yFactor); |
415 | pcty = y * invtheightMinus1; | ||
392 | int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; | 416 | int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; |
393 | 417 | for(int x = 0; x < twidth; x++) | |
394 | for(int x = 0; x < 256; x++) | ||
395 | { | 418 | { |
396 | int tx = (int)(x * xFactor); | 419 | tx = (int)(x * xFactor); |
397 | float height = (float)terrain[tx, ty]; | 420 | pctx = x * invtwitdthMinus1; |
398 | float layer = getLayerTex(height, x, y, | 421 | height = (float)terrain[tx, ty]; |
422 | layer = getLayerTex(height, pctx, pcty, | ||
399 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | 423 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, |
400 | startHeights, heightRanges); | 424 | startHeights, heightRanges); |
401 | 425 | ||
402 | // Select two textures | 426 | // Select two textures |
403 | int l0 = (int)layer; | 427 | l0 = (int)layer; |
404 | int l1 = Math.Min(l0 + 1, 3); | 428 | l1 = Math.Min(l0 + 1, 3); |
405 | 429 | ||
406 | int patchOffset = (tx & 0x0f) * 3 + ypatch; | 430 | int patchOffset = (tx & 0x0f) * 3 + ypatch; |
407 | byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; | 431 | byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; |
408 | byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; | 432 | byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; |
409 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | 433 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; |
410 | 434 | ||
411 | float aB = *(ptrA + 0); | 435 | aB = *(ptrA + 0); |
412 | float aG = *(ptrA + 1); | 436 | aG = *(ptrA + 1); |
413 | float aR = *(ptrA + 2); | 437 | aR = *(ptrA + 2); |
414 | 438 | ||
415 | float bB = *(ptrB + 0); | 439 | bB = *(ptrB + 0); |
416 | float bG = *(ptrB + 1); | 440 | bG = *(ptrB + 1); |
417 | float bR = *(ptrB + 2); | 441 | bR = *(ptrB + 2); |
418 | 442 | ||
419 | float layerDiff = layer - l0; | 443 | layerDiff = layer - l0; |
420 | 444 | ||
421 | // Interpolate between the two selected textures | 445 | // Interpolate between the two selected textures |
422 | *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); | 446 | *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); |
@@ -427,37 +451,39 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
427 | } | 451 | } |
428 | else | 452 | else |
429 | { | 453 | { |
430 | for(int y = 0; y < 256; y++) | 454 | for(int y = 0; y < theight; y++) |
431 | { | 455 | { |
432 | int ty = (int)((255 - y) * yFactor); | 456 | ty = (int)((theight - y - 1) * yFactor); |
457 | pcty = 1.0f - y * invtheightMinus1; | ||
433 | int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; | 458 | int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; |
434 | 459 | ||
435 | for(int x = 0; x < 256; x++) | 460 | for(int x = 0; x < twidth; x++) |
436 | { | 461 | { |
437 | int tx = (int)(x * xFactor); | 462 | tx = (int)(x * xFactor); |
438 | float height = (float)terrain[tx, ty]; | 463 | pctx = x * invtwitdthMinus1; |
439 | float layer = getLayerTex(height, x, (255 - y), | 464 | height = (float)terrain[tx, ty]; |
465 | layer = getLayerTex(height, pctx, pcty, | ||
440 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | 466 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, |
441 | startHeights, heightRanges); | 467 | startHeights, heightRanges); |
442 | 468 | ||
443 | // Select two textures | 469 | // Select two textures |
444 | int l0 = (int)layer; | 470 | l0 = (int)layer; |
445 | int l1 = Math.Min(l0 + 1, 3); | 471 | l1 = Math.Min(l0 + 1, 3); |
446 | 472 | ||
447 | int patchOffset = (tx & 0x0f) * 3 + ypatch; | 473 | int patchOffset = (tx & 0x0f) * 3 + ypatch; |
448 | byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; | 474 | byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; |
449 | byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; | 475 | byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; |
450 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | 476 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; |
451 | 477 | ||
452 | float aB = *(ptrA + 0); | 478 | aB = *(ptrA + 0); |
453 | float aG = *(ptrA + 1); | 479 | aG = *(ptrA + 1); |
454 | float aR = *(ptrA + 2); | 480 | aR = *(ptrA + 2); |
455 | 481 | ||
456 | float bB = *(ptrB + 0); | 482 | bB = *(ptrB + 0); |
457 | float bG = *(ptrB + 1); | 483 | bG = *(ptrB + 1); |
458 | float bR = *(ptrB + 2); | 484 | bR = *(ptrB + 2); |
459 | 485 | ||
460 | float layerDiff = layer - l0; | 486 | layerDiff = layer - l0; |
461 | 487 | ||
462 | // Interpolate between the two selected textures | 488 | // Interpolate between the two selected textures |
463 | *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); | 489 | *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); |
@@ -486,12 +512,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
486 | } | 512 | } |
487 | 513 | ||
488 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] | 514 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
489 | private static float getLayerTex(float height, int x, int y, uint sourceX, uint sourceY, | 515 | private static float getLayerTex(float height, float pctX, float pctY, uint sourceX, uint sourceY, |
490 | float[] startHeights, float[] heightRanges) | 516 | float[] startHeights, float[] heightRanges) |
491 | { | 517 | { |
492 | float pctX = (float)x / 255f; | ||
493 | float pctY = (float)y / 255f; | ||
494 | |||
495 | // Use bilinear interpolation between the four corners of start height and | 518 | // Use bilinear interpolation between the four corners of start height and |
496 | // height range to select the current values at this position | 519 | // height range to select the current values at this position |
497 | float startHeight = ImageUtils.Bilinear( | 520 | float startHeight = ImageUtils.Bilinear( |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 4c0023c..450c679 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -50,15 +50,15 @@ using OpenMetaverse.Imaging; | |||
50 | using OpenMetaverse.Rendering; | 50 | using OpenMetaverse.Rendering; |
51 | using OpenMetaverse.StructuredData; | 51 | using OpenMetaverse.StructuredData; |
52 | 52 | ||
53 | using WarpRenderer = global::Warp3D.Warp3D; | 53 | using WarpRenderer = Warp3D.Warp3D; |
54 | 54 | ||
55 | namespace OpenSim.Region.CoreModules.World.Warp3DMap | 55 | namespace OpenSim.Region.CoreModules.World.Warp3DMap |
56 | { | 56 | { |
57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Warp3DImageModule")] | 57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Warp3DImageModule")] |
58 | public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule | 58 | public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule |
59 | { | 59 | { |
60 | private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); | ||
61 | private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); | 60 | private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); |
61 | // private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 128); | ||
62 | 62 | ||
63 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 63 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
64 | 64 | ||
@@ -66,9 +66,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
66 | private static string LogHeader = "[WARP 3D IMAGE MODULE]"; | 66 | private static string LogHeader = "[WARP 3D IMAGE MODULE]"; |
67 | #pragma warning restore 414 | 67 | #pragma warning restore 414 |
68 | 68 | ||
69 | private Scene m_scene; | 69 | internal Scene m_scene; |
70 | private IRendering m_primMesher; | 70 | private IRendering m_primMesher; |
71 | private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>(); | 71 | internal IJ2KDecoder m_imgDecoder; |
72 | |||
73 | // caches per rendering | ||
74 | private Dictionary<string, warp_Texture> m_warpTextures = new Dictionary<string, warp_Texture>(); | ||
75 | private Dictionary<UUID, int> m_colors = new Dictionary<UUID, int>(); | ||
72 | 76 | ||
73 | private IConfigSource m_config; | 77 | private IConfigSource m_config; |
74 | private bool m_drawPrimVolume = true; // true if should render the prims on the tile | 78 | private bool m_drawPrimVolume = true; // true if should render the prims on the tile |
@@ -132,6 +136,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
132 | 136 | ||
133 | public void RegionLoaded(Scene scene) | 137 | public void RegionLoaded(Scene scene) |
134 | { | 138 | { |
139 | m_imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>(); | ||
135 | } | 140 | } |
136 | 141 | ||
137 | public void RemoveRegion(Scene scene) | 142 | public void RemoveRegion(Scene scene) |
@@ -181,10 +186,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
181 | viewHeigth = (int)m_scene.RegionInfo.RegionSizeY; | 186 | viewHeigth = (int)m_scene.RegionInfo.RegionSizeY; |
182 | orto = true; | 187 | orto = true; |
183 | 188 | ||
184 | // fov = warp_Math.rad2deg(2f * (float)Math.Atan2(viewWitdh,4096f)); | 189 | // fov = warp_Math.rad2deg(2f * (float)Math.Atan2(viewWitdh, 4096f)); |
185 | // orto = false; | 190 | // orto = false; |
186 | 191 | ||
187 | Bitmap tile = GenMapTile(); | 192 | Bitmap tile = GenImage(); |
193 | // image may be reloaded elsewhere, so no compression format | ||
194 | string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png"; | ||
195 | tile.Save(filename, ImageFormat.Png); | ||
188 | m_primMesher = null; | 196 | m_primMesher = null; |
189 | return tile; | 197 | return tile; |
190 | } | 198 | } |
@@ -204,14 +212,15 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
204 | fov = pfov; | 212 | fov = pfov; |
205 | orto = false; | 213 | orto = false; |
206 | 214 | ||
207 | Bitmap tile = GenMapTile(); | 215 | Bitmap tile = GenImage(); |
208 | m_primMesher = null; | 216 | m_primMesher = null; |
209 | return tile; | 217 | return tile; |
210 | } | 218 | } |
211 | 219 | ||
212 | private Bitmap GenMapTile() | 220 | private Bitmap GenImage() |
213 | { | 221 | { |
214 | m_colors.Clear(); | 222 | m_colors.Clear(); |
223 | m_warpTextures.Clear(); | ||
215 | 224 | ||
216 | WarpRenderer renderer = new WarpRenderer(); | 225 | WarpRenderer renderer = new WarpRenderer(); |
217 | 226 | ||
@@ -233,7 +242,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
233 | #endregion Camera | 242 | #endregion Camera |
234 | 243 | ||
235 | renderer.Scene.setAmbient(warp_Color.getColor(192,191,173)); | 244 | renderer.Scene.setAmbient(warp_Color.getColor(192,191,173)); |
236 | renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0f, 1f, 8f), 0xffffff, 0, 320, 40)); | 245 | renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0f, 1f, 8f), warp_Color.White, 0, 320, 40)); |
237 | 246 | ||
238 | CreateWater(renderer); | 247 | CreateWater(renderer); |
239 | CreateTerrain(renderer); | 248 | CreateTerrain(renderer); |
@@ -248,6 +257,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
248 | renderer = null; | 257 | renderer = null; |
249 | 258 | ||
250 | m_colors.Clear(); | 259 | m_colors.Clear(); |
260 | m_warpTextures.Clear(); | ||
251 | GC.Collect(); | 261 | GC.Collect(); |
252 | // m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); | 262 | // m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); |
253 | 263 | ||
@@ -285,8 +295,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
285 | m_scene.RegionInfo.RegionSizeY * 0.5f); | 295 | m_scene.RegionInfo.RegionSizeY * 0.5f); |
286 | 296 | ||
287 | warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); | 297 | warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); |
288 | waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif | ||
289 | waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); | ||
290 | renderer.Scene.addMaterial("WaterColor", waterColorMaterial); | 298 | renderer.Scene.addMaterial("WaterColor", waterColorMaterial); |
291 | renderer.SetObjectMaterial("Water", "WaterColor"); | 299 | renderer.SetObjectMaterial("Water", "WaterColor"); |
292 | } | 300 | } |
@@ -302,7 +310,23 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
302 | float regionsy = m_scene.RegionInfo.RegionSizeY; | 310 | float regionsy = m_scene.RegionInfo.RegionSizeY; |
303 | 311 | ||
304 | // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding | 312 | // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding |
305 | float diff = regionsx / 256f; | 313 | |
314 | int bitWidth; | ||
315 | int bitHeight; | ||
316 | |||
317 | const double log2inv = 1.4426950408889634073599246810019; | ||
318 | bitWidth = (int)Math.Ceiling((Math.Log(terrain.Width) * log2inv)); | ||
319 | bitHeight = (int)Math.Ceiling((Math.Log(terrain.Height) * log2inv)); | ||
320 | |||
321 | if(bitWidth > 8) // more than 256 is very heavy :( | ||
322 | bitWidth = 8; | ||
323 | if(bitHeight > 8) | ||
324 | bitHeight = 8; | ||
325 | |||
326 | int twidth = (int)Math.Pow(2, bitWidth); | ||
327 | int theight = (int)Math.Pow(2, bitHeight); | ||
328 | |||
329 | float diff = regionsx / twidth; | ||
306 | 330 | ||
307 | int npointsx = (int)(regionsx / diff); | 331 | int npointsx = (int)(regionsx / diff); |
308 | int npointsy = (int)(regionsy / diff); | 332 | int npointsy = (int)(regionsy / diff); |
@@ -391,14 +415,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
391 | 415 | ||
392 | warp_Texture texture; | 416 | warp_Texture texture; |
393 | // get texture fliped on Y | 417 | // get texture fliped on Y |
394 | using (Bitmap image = TerrainSplat.Splat( | 418 | using (Bitmap image = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges, |
395 | terrain, textureIDs, startHeights, heightRanges, | ||
396 | m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY, | 419 | m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY, |
397 | m_scene.AssetService, m_textureTerrain, m_textureAvegareTerrain, true)) | 420 | m_scene.AssetService, m_imgDecoder, m_textureTerrain, m_textureAvegareTerrain, true, |
421 | twidth, twidth)) | ||
398 | texture = new warp_Texture(image); | 422 | texture = new warp_Texture(image); |
399 | 423 | ||
400 | warp_Material material = new warp_Material(texture); | 424 | warp_Material material = new warp_Material(texture); |
401 | material.setColor(warp_Color.getColor(255,255,255)); | ||
402 | renderer.Scene.addMaterial("TerrainColor", material); | 425 | renderer.Scene.addMaterial("TerrainColor", material); |
403 | renderer.SetObjectMaterial("Terrain", "TerrainColor"); | 426 | renderer.SetObjectMaterial("Terrain", "TerrainColor"); |
404 | } | 427 | } |
@@ -416,18 +439,31 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
416 | } | 439 | } |
417 | ); | 440 | ); |
418 | } | 441 | } |
419 | 442 | ||
420 | private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) | 443 | private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) |
421 | { | 444 | { |
422 | const float MIN_SIZE_SQUARE = 4f; | ||
423 | |||
424 | if ((PCode)prim.Shape.PCode != PCode.Prim) | 445 | if ((PCode)prim.Shape.PCode != PCode.Prim) |
425 | return; | 446 | return; |
426 | float primScaleLenSquared = prim.Scale.LengthSquared(); | ||
427 | 447 | ||
428 | if (primScaleLenSquared < MIN_SIZE_SQUARE) | 448 | warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); |
449 | warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); | ||
450 | warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); | ||
451 | |||
452 | float screenFactor = renderer.Scene.EstimateBoxProjectedArea(primPos, ConvertVector(prim.Scale), m); | ||
453 | if(screenFactor < 0) | ||
429 | return; | 454 | return; |
430 | 455 | ||
456 | int p2 = (int)( -(float)Math.Log(screenFactor) * 1.442695f * 0.5 - 1); | ||
457 | |||
458 | if(p2 < 0) | ||
459 | p2 = 0; | ||
460 | else if(p2>3) | ||
461 | p2 = 3; | ||
462 | |||
463 | DetailLevel lod = (DetailLevel)(3 - p2); | ||
464 | |||
465 | // DetailLevel lod = DetailLevel.High; | ||
466 | |||
431 | FacetedMesh renderMesh = null; | 467 | FacetedMesh renderMesh = null; |
432 | Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); | 468 | Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); |
433 | 469 | ||
@@ -443,18 +479,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
443 | if (omvPrim.Sculpt.Type == SculptType.Mesh) | 479 | if (omvPrim.Sculpt.Type == SculptType.Mesh) |
444 | { | 480 | { |
445 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | 481 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); |
446 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh); | 482 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, lod, out renderMesh); |
447 | meshAsset = null; | 483 | meshAsset = null; |
448 | } | 484 | } |
449 | else // It's sculptie | 485 | else // It's sculptie |
450 | { | 486 | { |
451 | IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>(); | 487 | if(m_imgDecoder != null) |
452 | if(imgDecoder != null) | ||
453 | { | 488 | { |
454 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | 489 | Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset); |
455 | if(sculpt != null) | 490 | if(sculpt != null) |
456 | { | 491 | { |
457 | renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim,(Bitmap)sculpt, DetailLevel.High); | 492 | renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim,(Bitmap)sculpt, lod); |
458 | sculpt.Dispose(); | 493 | sculpt.Dispose(); |
459 | } | 494 | } |
460 | } | 495 | } |
@@ -466,7 +501,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
466 | // If not a mesh or sculptie, try the regular mesher | 501 | // If not a mesh or sculptie, try the regular mesher |
467 | if (renderMesh == null) | 502 | if (renderMesh == null) |
468 | { | 503 | { |
469 | renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.High); | 504 | renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, lod); |
470 | } | 505 | } |
471 | 506 | ||
472 | if (renderMesh == null) | 507 | if (renderMesh == null) |
@@ -474,10 +509,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
474 | 509 | ||
475 | string primID = prim.UUID.ToString(); | 510 | string primID = prim.UUID.ToString(); |
476 | 511 | ||
477 | warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); | ||
478 | warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); | ||
479 | warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); | ||
480 | |||
481 | // Create the prim faces | 512 | // Create the prim faces |
482 | // TODO: Implement the useTextures flag behavior | 513 | // TODO: Implement the useTextures flag behavior |
483 | for (int i = 0; i < renderMesh.Faces.Count; i++) | 514 | for (int i = 0; i < renderMesh.Faces.Count; i++) |
@@ -493,20 +524,34 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
493 | 524 | ||
494 | Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); | 525 | Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); |
495 | Color4 faceColor = teFace.RGBA; | 526 | Color4 faceColor = teFace.RGBA; |
527 | if(faceColor.A == 0) | ||
528 | continue; | ||
496 | 529 | ||
497 | string materialName = String.Empty; | 530 | string materialName = String.Empty; |
498 | if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) | 531 | if (m_texturePrims) |
499 | materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); | 532 | { |
533 | // if(lod > DetailLevel.Low) | ||
534 | { | ||
535 | // materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, lod == DetailLevel.Low); | ||
536 | materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, false); | ||
537 | if(String.IsNullOrEmpty(materialName)) | ||
538 | continue; | ||
539 | int c = renderer.Scene.material(materialName).getColor(); | ||
540 | if((c & warp_Color.MASKALPHA) == 0) | ||
541 | continue; | ||
542 | } | ||
543 | } | ||
500 | else | 544 | else |
501 | materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace)); | 545 | materialName = GetOrCreateMaterial(renderer, faceColor); |
502 | 546 | ||
503 | if(renderer.Scene.material(materialName).getTexture() == null) | 547 | if(renderer.Scene.material(materialName).getTexture() == null) |
504 | { | 548 | { |
549 | // uv map details dont not matter for color; | ||
505 | for (int j = 0; j < face.Vertices.Count; j++) | 550 | for (int j = 0; j < face.Vertices.Count; j++) |
506 | { | 551 | { |
507 | Vertex v = face.Vertices[j]; | 552 | Vertex v = face.Vertices[j]; |
508 | warp_Vector pos = ConvertVector(v.Position); | 553 | warp_Vector pos = ConvertVector(v.Position); |
509 | warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, 1.0f - v.TexCoord.Y); | 554 | warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y); |
510 | faceObj.addVertex(vert); | 555 | faceObj.addVertex(vert); |
511 | } | 556 | } |
512 | } | 557 | } |
@@ -575,20 +620,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
575 | } | 620 | } |
576 | } | 621 | } |
577 | 622 | ||
578 | private Color4 GetFaceColor(Primitive.TextureEntryFace face) | 623 | private int GetFaceColor(Primitive.TextureEntryFace face) |
579 | { | 624 | { |
580 | Color4 color; | 625 | int color; |
626 | Color4 ctmp = Color4.White; | ||
581 | 627 | ||
582 | if (face.TextureID == UUID.Zero) | 628 | if (face.TextureID == UUID.Zero) |
583 | return face.RGBA; | 629 | return warp_Color.White; |
584 | 630 | ||
585 | if (!m_colors.TryGetValue(face.TextureID, out color)) | 631 | if (!m_colors.TryGetValue(face.TextureID, out color)) |
586 | { | 632 | { |
587 | bool fetched = false; | 633 | bool fetched = false; |
588 | 634 | ||
589 | // Attempt to fetch the texture metadata | 635 | // Attempt to fetch the texture metadata |
590 | UUID metadataID = UUID.Combine(face.TextureID, TEXTURE_METADATA_MAGIC); | 636 | string cacheName = "MAPCLR"+face.TextureID.ToString(); |
591 | AssetBase metadata = m_scene.AssetService.GetCached(metadataID.ToString()); | 637 | AssetBase metadata = m_scene.AssetService.GetCached(cacheName); |
592 | if (metadata != null) | 638 | if (metadata != null) |
593 | { | 639 | { |
594 | OSDMap map = null; | 640 | OSDMap map = null; |
@@ -596,7 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
596 | 642 | ||
597 | if (map != null) | 643 | if (map != null) |
598 | { | 644 | { |
599 | color = map["X-JPEG2000-RGBA"].AsColor4(); | 645 | ctmp = map["X-RGBA"].AsColor4(); |
600 | fetched = true; | 646 | fetched = true; |
601 | } | 647 | } |
602 | } | 648 | } |
@@ -609,16 +655,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
609 | if (textureAsset != null) | 655 | if (textureAsset != null) |
610 | { | 656 | { |
611 | int width, height; | 657 | int width, height; |
612 | color = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height); | 658 | ctmp = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height); |
613 | 659 | ||
614 | OSDMap data = new OSDMap { { "X-JPEG2000-RGBA", OSD.FromColor4(color) } }; | 660 | OSDMap data = new OSDMap { { "X-RGBA", OSD.FromColor4(ctmp) } }; |
615 | metadata = new AssetBase | 661 | metadata = new AssetBase |
616 | { | 662 | { |
617 | Data = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)), | 663 | Data = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)), |
618 | Description = "Metadata for JPEG2000 texture " + face.TextureID.ToString(), | 664 | Description = "Metadata for texture color" + face.TextureID.ToString(), |
619 | Flags = AssetFlags.Collectable, | 665 | Flags = AssetFlags.Collectable, |
620 | FullID = metadataID, | 666 | FullID = UUID.Zero, |
621 | ID = metadataID.ToString(), | 667 | ID = cacheName, |
622 | Local = true, | 668 | Local = true, |
623 | Temporary = true, | 669 | Temporary = true, |
624 | Name = String.Empty, | 670 | Name = String.Empty, |
@@ -628,14 +674,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
628 | } | 674 | } |
629 | else | 675 | else |
630 | { | 676 | { |
631 | color = new Color4(0.5f, 0.5f, 0.5f, 1.0f); | 677 | ctmp = new Color4(0.5f, 0.5f, 0.5f, 1.0f); |
632 | } | 678 | } |
633 | } | 679 | } |
634 | 680 | color = ConvertColor(ctmp); | |
635 | m_colors[face.TextureID] = color; | 681 | m_colors[face.TextureID] = color; |
636 | } | 682 | } |
637 | 683 | ||
638 | return color * face.RGBA; | 684 | return color; |
639 | } | 685 | } |
640 | 686 | ||
641 | private string GetOrCreateMaterial(WarpRenderer renderer, Color4 color) | 687 | private string GetOrCreateMaterial(WarpRenderer renderer, Color4 color) |
@@ -647,26 +693,32 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
647 | return name; | 693 | return name; |
648 | 694 | ||
649 | renderer.AddMaterial(name, ConvertColor(color)); | 695 | renderer.AddMaterial(name, ConvertColor(color)); |
650 | if (color.A < 1f) | ||
651 | renderer.Scene.material(name).setTransparency((byte)((1f - color.A) * 255f)); | ||
652 | return name; | 696 | return name; |
653 | } | 697 | } |
654 | 698 | ||
655 | public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID) | 699 | public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID, bool useAverageTextureColor) |
656 | { | 700 | { |
657 | string materialName = "Color-" + faceColor.ToString() + "-Texture-" + textureID.ToString(); | 701 | int color = ConvertColor(faceColor); |
702 | string idstr = textureID.ToString() + color.ToString(); | ||
703 | string materialName = "MAPMAT" + idstr; | ||
658 | 704 | ||
659 | if (renderer.Scene.material(materialName) == null) | 705 | if (renderer.Scene.material(materialName) != null) |
706 | return materialName; | ||
707 | |||
708 | warp_Material mat = new warp_Material(); | ||
709 | warp_Texture texture = GetTexture(textureID); | ||
710 | if (texture != null) | ||
660 | { | 711 | { |
661 | renderer.AddMaterial(materialName, ConvertColor(faceColor)); | 712 | if(useAverageTextureColor) |
662 | if (faceColor.A < 1f) | 713 | color = warp_Color.multiply(color, texture.averageColor); |
663 | { | 714 | else |
664 | renderer.Scene.material(materialName).setTransparency((byte) ((1f - faceColor.A)*255f)); | 715 | mat.setTexture(texture); |
665 | } | ||
666 | warp_Texture texture = GetTexture(textureID); | ||
667 | if (texture != null) | ||
668 | renderer.Scene.material(materialName).setTexture(texture); | ||
669 | } | 716 | } |
717 | else | ||
718 | color = warp_Color.multiply(color, warp_Color.Grey); | ||
719 | |||
720 | mat.setColor(color); | ||
721 | renderer.Scene.addMaterial(materialName, mat); | ||
670 | 722 | ||
671 | return materialName; | 723 | return materialName; |
672 | } | 724 | } |
@@ -674,13 +726,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
674 | private warp_Texture GetTexture(UUID id) | 726 | private warp_Texture GetTexture(UUID id) |
675 | { | 727 | { |
676 | warp_Texture ret = null; | 728 | warp_Texture ret = null; |
729 | if(id == UUID.Zero) | ||
730 | return ret; | ||
731 | |||
732 | if(m_warpTextures.TryGetValue(id.ToString(), out ret)) | ||
733 | return ret; | ||
677 | 734 | ||
678 | byte[] asset = m_scene.AssetService.GetData(id.ToString()); | 735 | byte[] asset = m_scene.AssetService.GetData(id.ToString()); |
679 | 736 | ||
680 | if (asset != null) | 737 | if (asset != null) |
681 | { | 738 | { |
682 | IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>(); | 739 | IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>(); |
683 | |||
684 | try | 740 | try |
685 | { | 741 | { |
686 | using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset)) | 742 | using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset)) |
@@ -691,7 +747,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
691 | m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id), e); | 747 | m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id), e); |
692 | } | 748 | } |
693 | } | 749 | } |
694 | 750 | m_warpTextures[id.ToString()] = ret; | |
695 | return ret; | 751 | return ret; |
696 | } | 752 | } |
697 | 753 | ||
@@ -716,10 +772,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
716 | 772 | ||
717 | private static int ConvertColor(Color4 color) | 773 | private static int ConvertColor(Color4 color) |
718 | { | 774 | { |
719 | int c = warp_Color.getColor((byte)(color.R * 255f), (byte)(color.G * 255f), (byte)(color.B * 255f)); | 775 | int c = warp_Color.getColor((byte)(color.R * 255f), (byte)(color.G * 255f), (byte)(color.B * 255f), (byte)(color.A * 255f)); |
720 | if (color.A < 1f) | ||
721 | c |= (byte)(color.A * 255f) << 24; | ||
722 | |||
723 | return c; | 776 | return c; |
724 | } | 777 | } |
725 | 778 | ||
@@ -734,86 +787,83 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
734 | return normal; | 787 | return normal; |
735 | } | 788 | } |
736 | 789 | ||
737 | public static Color4 GetAverageColor(UUID textureID, byte[] j2kData, out int width, out int height) | 790 | public Color4 GetAverageColor(UUID textureID, byte[] j2kData, out int width, out int height) |
738 | { | 791 | { |
739 | ulong r = 0; | 792 | ulong r = 0; |
740 | ulong g = 0; | 793 | ulong g = 0; |
741 | ulong b = 0; | 794 | ulong b = 0; |
742 | ulong a = 0; | 795 | ulong a = 0; |
796 | int pixelBytes; | ||
743 | 797 | ||
744 | using (MemoryStream stream = new MemoryStream(j2kData)) | 798 | try |
745 | { | 799 | { |
746 | try | 800 | using(MemoryStream stream = new MemoryStream(j2kData)) |
801 | using(Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream)) | ||
747 | { | 802 | { |
748 | int pixelBytes; | 803 | width = bitmap.Width; |
749 | 804 | height = bitmap.Height; | |
750 | using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream)) | ||
751 | { | ||
752 | width = bitmap.Width; | ||
753 | height = bitmap.Height; | ||
754 | 805 | ||
755 | BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); | 806 | BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); |
756 | pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; | 807 | pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; |
757 | 808 | ||
758 | // Sum up the individual channels | 809 | // Sum up the individual channels |
759 | unsafe | 810 | unsafe |
811 | { | ||
812 | if(pixelBytes == 4) | ||
760 | { | 813 | { |
761 | if (pixelBytes == 4) | 814 | for(int y = 0; y < height; y++) |
762 | { | 815 | { |
763 | for (int y = 0; y < height; y++) | 816 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); |
817 | |||
818 | for(int x = 0; x < width; x++) | ||
764 | { | 819 | { |
765 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); | 820 | b += row[x * pixelBytes + 0]; |
766 | 821 | g += row[x * pixelBytes + 1]; | |
767 | for (int x = 0; x < width; x++) | 822 | r += row[x * pixelBytes + 2]; |
768 | { | 823 | a += row[x * pixelBytes + 3]; |
769 | b += row[x * pixelBytes + 0]; | ||
770 | g += row[x * pixelBytes + 1]; | ||
771 | r += row[x * pixelBytes + 2]; | ||
772 | a += row[x * pixelBytes + 3]; | ||
773 | } | ||
774 | } | 824 | } |
775 | } | 825 | } |
776 | else | 826 | } |
827 | else | ||
828 | { | ||
829 | for(int y = 0; y < height; y++) | ||
777 | { | 830 | { |
778 | for (int y = 0; y < height; y++) | 831 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); |
832 | |||
833 | for(int x = 0; x < width; x++) | ||
779 | { | 834 | { |
780 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); | 835 | b += row[x * pixelBytes + 0]; |
781 | 836 | g += row[x * pixelBytes + 1]; | |
782 | for (int x = 0; x < width; x++) | 837 | r += row[x * pixelBytes + 2]; |
783 | { | ||
784 | b += row[x * pixelBytes + 0]; | ||
785 | g += row[x * pixelBytes + 1]; | ||
786 | r += row[x * pixelBytes + 2]; | ||
787 | } | ||
788 | } | 838 | } |
789 | } | 839 | } |
790 | } | 840 | } |
791 | } | 841 | } |
842 | } | ||
843 | // Get the averages for each channel | ||
844 | const decimal OO_255 = 1m / 255m; | ||
845 | decimal totalPixels = (decimal)(width * height); | ||
792 | 846 | ||
793 | // Get the averages for each channel | 847 | decimal rm = ((decimal)r / totalPixels) * OO_255; |
794 | const decimal OO_255 = 1m / 255m; | 848 | decimal gm = ((decimal)g / totalPixels) * OO_255; |
795 | decimal totalPixels = (decimal)(width * height); | 849 | decimal bm = ((decimal)b / totalPixels) * OO_255; |
850 | decimal am = ((decimal)a / totalPixels) * OO_255; | ||
796 | 851 | ||
797 | decimal rm = ((decimal)r / totalPixels) * OO_255; | 852 | if(pixelBytes == 3) |
798 | decimal gm = ((decimal)g / totalPixels) * OO_255; | 853 | am = 1m; |
799 | decimal bm = ((decimal)b / totalPixels) * OO_255; | ||
800 | decimal am = ((decimal)a / totalPixels) * OO_255; | ||
801 | 854 | ||
802 | if (pixelBytes == 3) | 855 | return new Color4((float)rm, (float)gm, (float)bm, (float)am); |
803 | am = 1m; | ||
804 | 856 | ||
805 | return new Color4((float)rm, (float)gm, (float)bm, (float)am); | 857 | } |
806 | } | 858 | catch(Exception ex) |
807 | catch (Exception ex) | 859 | { |
808 | { | 860 | m_log.WarnFormat( |
809 | m_log.WarnFormat( | 861 | "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", |
810 | "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", | 862 | textureID, j2kData.Length, ex.Message); |
811 | textureID, j2kData.Length, ex.Message); | ||
812 | 863 | ||
813 | width = 0; | 864 | width = 0; |
814 | height = 0; | 865 | height = 0; |
815 | return new Color4(0.5f, 0.5f, 0.5f, 1.0f); | 866 | return new Color4(0.5f, 0.5f, 0.5f, 1.0f); |
816 | } | ||
817 | } | 867 | } |
818 | } | 868 | } |
819 | 869 | ||
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index e899343..da54c54 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -1409,6 +1409,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1409 | 1409 | ||
1410 | // assumed this is 1m less than next grid line | 1410 | // assumed this is 1m less than next grid line |
1411 | int regionsView = (int)m_scene.MaxRegionViewDistance; | 1411 | int regionsView = (int)m_scene.MaxRegionViewDistance; |
1412 | |||
1413 | string regionName = m_scene.RegionInfo.RegionName; | ||
1414 | ulong regionHandle = m_scene.RegionInfo.RegionHandle; | ||
1412 | 1415 | ||
1413 | int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; | 1416 | int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; |
1414 | int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY; | 1417 | int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY; |
@@ -1439,25 +1442,52 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1439 | g.FillRectangle(sea, 0, 0, spanX, spanY); | 1442 | g.FillRectangle(sea, 0, 0, spanX, spanY); |
1440 | sea.Dispose(); | 1443 | sea.Dispose(); |
1441 | 1444 | ||
1445 | Font drawFont = new Font("Arial", 32); | ||
1446 | SolidBrush drawBrush = new SolidBrush(Color.White); | ||
1447 | |||
1442 | List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, | 1448 | List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, |
1443 | startX, startY, endX, endY); | 1449 | startX, startY, endX, endY); |
1444 | 1450 | ||
1445 | if(regions.Count > 0) | 1451 | startX--; |
1452 | startY--; | ||
1453 | |||
1454 | bool doneLocal = false; | ||
1455 | string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png"; | ||
1456 | try | ||
1446 | { | 1457 | { |
1447 | Font drawFont = new Font("Arial", 32); | 1458 | using(Image localMap = Bitmap.FromFile(filename)) |
1448 | SolidBrush drawBrush = new SolidBrush(Color.White); | 1459 | { |
1460 | int x = regionX - startX; | ||
1461 | int y = regionY - startY; | ||
1462 | int sx = regionSizeX; | ||
1463 | int sy = regionSizeY; | ||
1464 | // y origin is top | ||
1465 | g.DrawImage(localMap,new Rectangle(x, spanY - y - sy, sx, sy), | ||
1466 | 0, 0, localMap.Width, localMap.Height, GraphicsUnit.Pixel, gatrib); | ||
1467 | |||
1468 | if(m_exportPrintRegionName) | ||
1469 | { | ||
1470 | SizeF stringSize = g.MeasureString(regionName, drawFont); | ||
1471 | g.DrawString(regionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); | ||
1472 | } | ||
1473 | } | ||
1474 | doneLocal = true; | ||
1475 | } | ||
1476 | catch {} | ||
1449 | 1477 | ||
1478 | if(regions.Count > 0) | ||
1479 | { | ||
1450 | ManagedImage managedImage = null; | 1480 | ManagedImage managedImage = null; |
1451 | Image image = null; | 1481 | Image image = null; |
1452 | 1482 | ||
1453 | startX--; | ||
1454 | startY--; | ||
1455 | |||
1456 | foreach(GridRegion r in regions) | 1483 | foreach(GridRegion r in regions) |
1457 | { | 1484 | { |
1458 | if(r.TerrainImage == UUID.Zero) | 1485 | if(r.TerrainImage == UUID.Zero) |
1459 | continue; | 1486 | continue; |
1460 | 1487 | ||
1488 | if(doneLocal && r.RegionHandle == regionHandle) | ||
1489 | continue; | ||
1490 | |||
1461 | AssetBase texAsset = m_scene.AssetService.Get(r.TerrainImage.ToString()); | 1491 | AssetBase texAsset = m_scene.AssetService.Get(r.TerrainImage.ToString()); |
1462 | if(texAsset == null) | 1492 | if(texAsset == null) |
1463 | continue; | 1493 | continue; |
@@ -1472,7 +1502,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1472 | g.DrawImage(image,new Rectangle(x, spanY - y - sy, sx, sy), | 1502 | g.DrawImage(image,new Rectangle(x, spanY - y - sy, sx, sy), |
1473 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, gatrib); | 1503 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, gatrib); |
1474 | 1504 | ||
1475 | if(m_exportPrintRegionName && r.RegionHandle == m_scene.RegionInfo.RegionHandle) | 1505 | if(m_exportPrintRegionName && r.RegionHandle == regionHandle) |
1476 | { | 1506 | { |
1477 | SizeF stringSize = g.MeasureString(r.RegionName, drawFont); | 1507 | SizeF stringSize = g.MeasureString(r.RegionName, drawFont); |
1478 | g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); | 1508 | g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); |
@@ -1483,16 +1513,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1483 | if(image != null) | 1513 | if(image != null) |
1484 | image.Dispose(); | 1514 | image.Dispose(); |
1485 | 1515 | ||
1486 | if(m_exportPrintScale) | 1516 | } |
1487 | { | ||
1488 | String drawString = string.Format("{0}m x {1}m", spanX, spanY); | ||
1489 | g.DrawString(drawString, drawFont, drawBrush, 30, 30); | ||
1490 | } | ||
1491 | 1517 | ||
1492 | drawBrush.Dispose(); | 1518 | if(m_exportPrintScale) |
1493 | drawFont.Dispose(); | 1519 | { |
1520 | String drawString = string.Format("{0}m x {1}m", spanX, spanY); | ||
1521 | g.DrawString(drawString, drawFont, drawBrush, 30, 30); | ||
1494 | } | 1522 | } |
1495 | 1523 | ||
1524 | drawBrush.Dispose(); | ||
1525 | drawFont.Dispose(); | ||
1496 | gatrib.Dispose(); | 1526 | gatrib.Dispose(); |
1497 | g.Dispose(); | 1527 | g.Dispose(); |
1498 | 1528 | ||
@@ -1689,13 +1719,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1689 | { | 1719 | { |
1690 | float scale = (float)Constants.RegionSize/(float)mb; | 1720 | float scale = (float)Constants.RegionSize/(float)mb; |
1691 | using(Bitmap scaledbmp = Util.ResizeImageSolid(mapbmp, (int)(bx * scale), (int)(by * scale))) | 1721 | using(Bitmap scaledbmp = Util.ResizeImageSolid(mapbmp, (int)(bx * scale), (int)(by * scale))) |
1692 | data = OpenJPEG.EncodeFromImage(scaledbmp, false); | 1722 | data = OpenJPEG.EncodeFromImage(scaledbmp, true); |
1693 | } | 1723 | } |
1694 | else | 1724 | else |
1695 | data = OpenJPEG.EncodeFromImage(mapbmp, false); | 1725 | data = OpenJPEG.EncodeFromImage(mapbmp, true); |
1696 | } | 1726 | } |
1697 | else | 1727 | else |
1698 | data = OpenJPEG.EncodeFromImage(mapbmp, false); | 1728 | data = OpenJPEG.EncodeFromImage(mapbmp, true); |
1699 | 1729 | ||
1700 | if (data != null && data.Length > 0) | 1730 | if (data != null && data.Length > 0) |
1701 | { | 1731 | { |
diff --git a/bin/Warp3D.dll b/bin/Warp3D.dll index d80037c..f781022 100755 --- a/bin/Warp3D.dll +++ b/bin/Warp3D.dll | |||
Binary files differ | |||