diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 95fa567d4c..51f8f75d70 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 /// Note we create a 256x256 dimension texture even if the actual terrain is larger. /// - public static Bitmap Splat(ITerrainChannel terrain, - UUID[] textureIDs, float[] startHeights, float[] heightRanges, + public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs, + float[] startHeights, float[] heightRanges, uint regionPositionX,uint regionPositionY, - IAssetService assetService, bool textureTerrain, bool averagetextureTerrain, bool FlipedY) + IAssetService assetService, IJ2KDecoder decoder, + bool textureTerrain, bool averagetextureTerrain, bool FlipedY, + int twidth, int theight) { Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); @@ -113,27 +115,29 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap for(int i = 0; i < 4; i++) { AssetBase asset = null; - UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); + + // asset cache indexes are strings + string cacheName ="MAP-Patch" + textureIDs[i].ToString(); // Try to fetch a cached copy of the decoded/resized version of this texture - // asset = assetService.GetCached(cacheID.ToString()); + asset = assetService.GetCached(cacheName); if(asset != null) { try { using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); + + if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || + detailTexture[i].Width != 16 || detailTexture[i].Height != 16) + { + detailTexture[i].Dispose(); + detailTexture[i] = null; + } } catch(Exception ex) { - m_log.Warn("Failed to decode cached terrain texture " + cacheID + - " (textureID: " + textureIDs[i] + "): " + ex.Message); - } - if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || - detailTexture[i].Width != 16 || detailTexture[i].Height != 16) - { - detailTexture[i].Dispose(); - detailTexture[i] = null; + m_log.Warn("Failed to decode cached terrain patch texture" + textureIDs[i] + "): " + ex.Message); } } @@ -143,12 +147,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap asset = assetService.Get(textureIDs[i].ToString()); if(asset != null) { - // m_log.DebugFormat( - // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); - try { - detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); + detailTexture[i] = (Bitmap)decoder.DecodeToImage(asset.Data); } catch(Exception ex) { @@ -177,8 +178,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap Data = data, Description = "PNG", Flags = AssetFlags.Collectable, - FullID = cacheID, - ID = cacheID.ToString(), + FullID = UUID.Zero, + ID = cacheName, Local = true, Name = String.Empty, Temporary = true, @@ -279,46 +280,61 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #region Layer Map - // Scale difference between actual region size and the 256 texture being created - float xFactor = terrain.Width / 256f; - float yFactor = terrain.Height / 256f; + float xFactor = terrain.Width / twidth; + float yFactor = terrain.Height / theight; #endregion Layer Map #region Texture Compositing - Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); - BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); + Bitmap output = new Bitmap(twidth, theight, PixelFormat.Format24bppRgb); + BitmapData outputData = output.LockBits(new Rectangle(0, 0, twidth, theight), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); // Unsafe work as we lock down the source textures for quicker access and access the // pixel data directly + float invtwitdthMinus1 = 1.0f / (twidth - 1); + float invtheightMinus1 = 1.0f / (theight - 1); + int ty; + int tx; + float pctx; + float pcty; + float height; + float layer; + float layerDiff; + int l0; + int l1; + if(usecolors) { + float a; + float b; if(FlipedY) { unsafe { - for(int y = 0; y < 256; ++y) + for(int y = 0; y < theight; ++y) { - int ty = (int)(y * yFactor); + ty = (int)(y * yFactor); + pcty = y * invtheightMinus1; byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; - for(int x = 0; x < 256; ++x) + for(int x = 0; x < twidth; ++x) { - int tx = (int)(x * xFactor); - float height = (float)terrain[tx, ty]; - float layer = getLayerTex(height, x, y, + tx = (int)(x * xFactor); + pctx = x * invtwitdthMinus1; + height = (float)terrain[tx, ty]; + layer = getLayerTex(height, pctx, pcty, (uint)tx + regionPositionX, (uint)ty + regionPositionY, startHeights, heightRanges); // Select two textures - int l0 = (int)layer; - int l1 = Math.Min(l0 + 1, 3); + l0 = (int)layer; + l1 = Math.Min(l0 + 1, 3); - float layerDiff = layer - l0; + layerDiff = layer - l0; - float a = mapColorsRed[l0]; - float b = mapColorsRed[l1]; + a = mapColorsRed[l0]; + b = mapColorsRed[l1]; *(ptrO++) = (byte)(a + layerDiff * (b - a)); a = mapColorsGreen[l0]; @@ -336,27 +352,28 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap { unsafe { - for(int y = 0; y < 256; ++y) + for(int y = 0; y < theight; ++y) { - int ty = (int)((255 - y) * yFactor); + ty = (int)((theight - y -1) * yFactor); + pcty = 1.0f - y * invtheightMinus1; byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; - for(int x = 0; x < 256; ++x) + for(int x = 0; x < twidth; ++x) { - int tx = (int)(x * xFactor); - float height = (float)terrain[tx, ty]; - float layer = getLayerTex(height, x, (255 - y), + tx = (int)(x * xFactor); + pctx = x * invtwitdthMinus1; + height = (float)terrain[tx, ty]; + layer = getLayerTex(height, pctx , pcty, (uint)tx + regionPositionX, (uint)ty + regionPositionY, startHeights, heightRanges); // Select two textures - int l0 = (int)layer; - int l1 = Math.Min(l0 + 1, 3); + l0 = (int)layer; + l1 = Math.Min(l0 + 1, 3); - float layerDiff = layer - l0; - - float a = mapColorsRed[l0]; - float b = mapColorsRed[l1]; + layerDiff = layer - l0; + a = mapColorsRed[l0]; + b = mapColorsRed[l1]; *(ptrO++) = (byte)(a + layerDiff * (b - a)); a = mapColorsGreen[l0]; @@ -373,6 +390,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } else { + float aB; + float aG; + float aR; + float bB; + float bG; + float bR; unsafe { // Get handles to all of the texture data arrays @@ -386,37 +409,38 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap if(FlipedY) { - for(int y = 0; y < 256; y++) + for(int y = 0; y < theight; y++) { - int ty = (int)(y * yFactor); + ty = (int)(y * yFactor); + pcty = y * invtheightMinus1; int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; - - for(int x = 0; x < 256; x++) + for(int x = 0; x < twidth; x++) { - int tx = (int)(x * xFactor); - float height = (float)terrain[tx, ty]; - float layer = getLayerTex(height, x, y, + tx = (int)(x * xFactor); + pctx = x * invtwitdthMinus1; + height = (float)terrain[tx, ty]; + layer = getLayerTex(height, pctx, pcty, (uint)tx + regionPositionX, (uint)ty + regionPositionY, startHeights, heightRanges); // Select two textures - int l0 = (int)layer; - int l1 = Math.Min(l0 + 1, 3); + l0 = (int)layer; + l1 = Math.Min(l0 + 1, 3); int patchOffset = (tx & 0x0f) * 3 + ypatch; byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; - float aB = *(ptrA + 0); - float aG = *(ptrA + 1); - float aR = *(ptrA + 2); + aB = *(ptrA + 0); + aG = *(ptrA + 1); + aR = *(ptrA + 2); - float bB = *(ptrB + 0); - float bG = *(ptrB + 1); - float bR = *(ptrB + 2); + bB = *(ptrB + 0); + bG = *(ptrB + 1); + bR = *(ptrB + 2); - float layerDiff = layer - l0; + layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); @@ -427,37 +451,39 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } else { - for(int y = 0; y < 256; y++) + for(int y = 0; y < theight; y++) { - int ty = (int)((255 - y) * yFactor); + ty = (int)((theight - y - 1) * yFactor); + pcty = 1.0f - y * invtheightMinus1; int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; - for(int x = 0; x < 256; x++) + for(int x = 0; x < twidth; x++) { - int tx = (int)(x * xFactor); - float height = (float)terrain[tx, ty]; - float layer = getLayerTex(height, x, (255 - y), + tx = (int)(x * xFactor); + pctx = x * invtwitdthMinus1; + height = (float)terrain[tx, ty]; + layer = getLayerTex(height, pctx, pcty, (uint)tx + regionPositionX, (uint)ty + regionPositionY, startHeights, heightRanges); // Select two textures - int l0 = (int)layer; - int l1 = Math.Min(l0 + 1, 3); + l0 = (int)layer; + l1 = Math.Min(l0 + 1, 3); int patchOffset = (tx & 0x0f) * 3 + ypatch; byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; - float aB = *(ptrA + 0); - float aG = *(ptrA + 1); - float aR = *(ptrA + 2); + aB = *(ptrA + 0); + aG = *(ptrA + 1); + aR = *(ptrA + 2); - float bB = *(ptrB + 0); - float bG = *(ptrB + 1); - float bR = *(ptrB + 2); + bB = *(ptrB + 0); + bG = *(ptrB + 1); + bR = *(ptrB + 2); - float layerDiff = layer - l0; + layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); @@ -486,12 +512,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - private static float getLayerTex(float height, int x, int y, uint sourceX, uint sourceY, + private static float getLayerTex(float height, float pctX, float pctY, uint sourceX, uint sourceY, float[] startHeights, float[] heightRanges) { - float pctX = (float)x / 255f; - float pctY = (float)y / 255f; - // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = ImageUtils.Bilinear( diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 4c0023c2ec..450c67950f 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -50,15 +50,15 @@ using OpenMetaverse.Imaging; using OpenMetaverse.Rendering; using OpenMetaverse.StructuredData; -using WarpRenderer = global::Warp3D.Warp3D; +using WarpRenderer = Warp3D.Warp3D; namespace OpenSim.Region.CoreModules.World.Warp3DMap { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Warp3DImageModule")] public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule { - private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); +// private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 128); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -66,9 +66,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private static string LogHeader = "[WARP 3D IMAGE MODULE]"; #pragma warning restore 414 - private Scene m_scene; + internal Scene m_scene; private IRendering m_primMesher; - private Dictionary m_colors = new Dictionary(); + internal IJ2KDecoder m_imgDecoder; + + // caches per rendering + private Dictionary m_warpTextures = new Dictionary(); + private Dictionary m_colors = new Dictionary(); private IConfigSource m_config; private bool m_drawPrimVolume = true; // true if should render the prims on the tile @@ -132,6 +136,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public void RegionLoaded(Scene scene) { + m_imgDecoder = m_scene.RequestModuleInterface(); } public void RemoveRegion(Scene scene) @@ -181,10 +186,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap viewHeigth = (int)m_scene.RegionInfo.RegionSizeY; orto = true; -// fov = warp_Math.rad2deg(2f * (float)Math.Atan2(viewWitdh,4096f)); +// fov = warp_Math.rad2deg(2f * (float)Math.Atan2(viewWitdh, 4096f)); // orto = false; - Bitmap tile = GenMapTile(); + Bitmap tile = GenImage(); + // image may be reloaded elsewhere, so no compression format + string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png"; + tile.Save(filename, ImageFormat.Png); m_primMesher = null; return tile; } @@ -204,14 +212,15 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap fov = pfov; orto = false; - Bitmap tile = GenMapTile(); + Bitmap tile = GenImage(); m_primMesher = null; return tile; } - private Bitmap GenMapTile() + private Bitmap GenImage() { m_colors.Clear(); + m_warpTextures.Clear(); WarpRenderer renderer = new WarpRenderer(); @@ -233,7 +242,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Camera renderer.Scene.setAmbient(warp_Color.getColor(192,191,173)); - renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0f, 1f, 8f), 0xffffff, 0, 320, 40)); + renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0f, 1f, 8f), warp_Color.White, 0, 320, 40)); CreateWater(renderer); CreateTerrain(renderer); @@ -248,6 +257,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap renderer = null; m_colors.Clear(); + m_warpTextures.Clear(); GC.Collect(); // m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); @@ -285,8 +295,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap m_scene.RegionInfo.RegionSizeY * 0.5f); warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); - waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif - waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); renderer.Scene.addMaterial("WaterColor", waterColorMaterial); renderer.SetObjectMaterial("Water", "WaterColor"); } @@ -302,7 +310,23 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap float regionsy = m_scene.RegionInfo.RegionSizeY; // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding - float diff = regionsx / 256f; + + int bitWidth; + int bitHeight; + + const double log2inv = 1.4426950408889634073599246810019; + bitWidth = (int)Math.Ceiling((Math.Log(terrain.Width) * log2inv)); + bitHeight = (int)Math.Ceiling((Math.Log(terrain.Height) * log2inv)); + + if(bitWidth > 8) // more than 256 is very heavy :( + bitWidth = 8; + if(bitHeight > 8) + bitHeight = 8; + + int twidth = (int)Math.Pow(2, bitWidth); + int theight = (int)Math.Pow(2, bitHeight); + + float diff = regionsx / twidth; int npointsx = (int)(regionsx / diff); int npointsy = (int)(regionsy / diff); @@ -391,14 +415,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Texture texture; // get texture fliped on Y - using (Bitmap image = TerrainSplat.Splat( - terrain, textureIDs, startHeights, heightRanges, + using (Bitmap image = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges, m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY, - m_scene.AssetService, m_textureTerrain, m_textureAvegareTerrain, true)) + m_scene.AssetService, m_imgDecoder, m_textureTerrain, m_textureAvegareTerrain, true, + twidth, twidth)) texture = new warp_Texture(image); warp_Material material = new warp_Material(texture); - material.setColor(warp_Color.getColor(255,255,255)); renderer.Scene.addMaterial("TerrainColor", material); renderer.SetObjectMaterial("Terrain", "TerrainColor"); } @@ -416,18 +439,31 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } ); } - + private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) { - const float MIN_SIZE_SQUARE = 4f; - if ((PCode)prim.Shape.PCode != PCode.Prim) return; - float primScaleLenSquared = prim.Scale.LengthSquared(); - if (primScaleLenSquared < MIN_SIZE_SQUARE) + warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); + warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); + warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); + + float screenFactor = renderer.Scene.EstimateBoxProjectedArea(primPos, ConvertVector(prim.Scale), m); + if(screenFactor < 0) return; + int p2 = (int)( -(float)Math.Log(screenFactor) * 1.442695f * 0.5 - 1); + + if(p2 < 0) + p2 = 0; + else if(p2>3) + p2 = 3; + + DetailLevel lod = (DetailLevel)(3 - p2); + +// DetailLevel lod = DetailLevel.High; + FacetedMesh renderMesh = null; Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); @@ -443,18 +479,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap if (omvPrim.Sculpt.Type == SculptType.Mesh) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, lod, out renderMesh); meshAsset = null; } else // It's sculptie { - IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface(); - if(imgDecoder != null) + if(m_imgDecoder != null) { - Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset); if(sculpt != null) { - renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim,(Bitmap)sculpt, DetailLevel.High); + renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim,(Bitmap)sculpt, lod); sculpt.Dispose(); } } @@ -466,7 +501,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // If not a mesh or sculptie, try the regular mesher if (renderMesh == null) { - renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.High); + renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, lod); } if (renderMesh == null) @@ -474,10 +509,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap string primID = prim.UUID.ToString(); - warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); - warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); - warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); - // Create the prim faces // TODO: Implement the useTextures flag behavior for (int i = 0; i < renderMesh.Faces.Count; i++) @@ -493,20 +524,34 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = teFace.RGBA; + if(faceColor.A == 0) + continue; string materialName = String.Empty; - if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) - materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); + if (m_texturePrims) + { +// if(lod > DetailLevel.Low) + { +// materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, lod == DetailLevel.Low); + materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, false); + if(String.IsNullOrEmpty(materialName)) + continue; + int c = renderer.Scene.material(materialName).getColor(); + if((c & warp_Color.MASKALPHA) == 0) + continue; + } + } else - materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace)); + materialName = GetOrCreateMaterial(renderer, faceColor); if(renderer.Scene.material(materialName).getTexture() == null) { + // uv map details dont not matter for color; for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); - warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, 1.0f - v.TexCoord.Y); + warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } } @@ -575,20 +620,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } } - private Color4 GetFaceColor(Primitive.TextureEntryFace face) + private int GetFaceColor(Primitive.TextureEntryFace face) { - Color4 color; + int color; + Color4 ctmp = Color4.White; if (face.TextureID == UUID.Zero) - return face.RGBA; + return warp_Color.White; if (!m_colors.TryGetValue(face.TextureID, out color)) { bool fetched = false; // Attempt to fetch the texture metadata - UUID metadataID = UUID.Combine(face.TextureID, TEXTURE_METADATA_MAGIC); - AssetBase metadata = m_scene.AssetService.GetCached(metadataID.ToString()); + string cacheName = "MAPCLR"+face.TextureID.ToString(); + AssetBase metadata = m_scene.AssetService.GetCached(cacheName); if (metadata != null) { OSDMap map = null; @@ -596,7 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap if (map != null) { - color = map["X-JPEG2000-RGBA"].AsColor4(); + ctmp = map["X-RGBA"].AsColor4(); fetched = true; } } @@ -609,16 +655,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap if (textureAsset != null) { int width, height; - color = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height); + ctmp = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height); - OSDMap data = new OSDMap { { "X-JPEG2000-RGBA", OSD.FromColor4(color) } }; + OSDMap data = new OSDMap { { "X-RGBA", OSD.FromColor4(ctmp) } }; metadata = new AssetBase { Data = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)), - Description = "Metadata for JPEG2000 texture " + face.TextureID.ToString(), + Description = "Metadata for texture color" + face.TextureID.ToString(), Flags = AssetFlags.Collectable, - FullID = metadataID, - ID = metadataID.ToString(), + FullID = UUID.Zero, + ID = cacheName, Local = true, Temporary = true, Name = String.Empty, @@ -628,14 +674,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } else { - color = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + ctmp = new Color4(0.5f, 0.5f, 0.5f, 1.0f); } } - + color = ConvertColor(ctmp); m_colors[face.TextureID] = color; } - return color * face.RGBA; + return color; } private string GetOrCreateMaterial(WarpRenderer renderer, Color4 color) @@ -647,26 +693,32 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return name; renderer.AddMaterial(name, ConvertColor(color)); - if (color.A < 1f) - renderer.Scene.material(name).setTransparency((byte)((1f - color.A) * 255f)); return name; } - public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID) + public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID, bool useAverageTextureColor) { - string materialName = "Color-" + faceColor.ToString() + "-Texture-" + textureID.ToString(); + int color = ConvertColor(faceColor); + string idstr = textureID.ToString() + color.ToString(); + string materialName = "MAPMAT" + idstr; - if (renderer.Scene.material(materialName) == null) + if (renderer.Scene.material(materialName) != null) + return materialName; + + warp_Material mat = new warp_Material(); + warp_Texture texture = GetTexture(textureID); + if (texture != null) { - renderer.AddMaterial(materialName, ConvertColor(faceColor)); - if (faceColor.A < 1f) - { - renderer.Scene.material(materialName).setTransparency((byte) ((1f - faceColor.A)*255f)); - } - warp_Texture texture = GetTexture(textureID); - if (texture != null) - renderer.Scene.material(materialName).setTexture(texture); + if(useAverageTextureColor) + color = warp_Color.multiply(color, texture.averageColor); + else + mat.setTexture(texture); } + else + color = warp_Color.multiply(color, warp_Color.Grey); + + mat.setColor(color); + renderer.Scene.addMaterial(materialName, mat); return materialName; } @@ -674,13 +726,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private warp_Texture GetTexture(UUID id) { warp_Texture ret = null; + if(id == UUID.Zero) + return ret; + + if(m_warpTextures.TryGetValue(id.ToString(), out ret)) + return ret; byte[] asset = m_scene.AssetService.GetData(id.ToString()); if (asset != null) - { + { IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface(); - try { using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset)) @@ -691,7 +747,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id), e); } } - + m_warpTextures[id.ToString()] = ret; return ret; } @@ -716,10 +772,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private static int ConvertColor(Color4 color) { - int c = warp_Color.getColor((byte)(color.R * 255f), (byte)(color.G * 255f), (byte)(color.B * 255f)); - if (color.A < 1f) - c |= (byte)(color.A * 255f) << 24; - + int c = warp_Color.getColor((byte)(color.R * 255f), (byte)(color.G * 255f), (byte)(color.B * 255f), (byte)(color.A * 255f)); return c; } @@ -734,86 +787,83 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return normal; } - public static Color4 GetAverageColor(UUID textureID, byte[] j2kData, out int width, out int height) + public Color4 GetAverageColor(UUID textureID, byte[] j2kData, out int width, out int height) { ulong r = 0; ulong g = 0; ulong b = 0; ulong a = 0; + int pixelBytes; - using (MemoryStream stream = new MemoryStream(j2kData)) + try { - try + using(MemoryStream stream = new MemoryStream(j2kData)) + using(Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream)) { - int pixelBytes; + width = bitmap.Width; + height = bitmap.Height; - using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream)) + BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); + pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + + // Sum up the individual channels + unsafe { - width = bitmap.Width; - height = bitmap.Height; - - BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); - pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; - - // Sum up the individual channels - unsafe + if(pixelBytes == 4) { - if (pixelBytes == 4) + for(int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); + byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); - for (int x = 0; x < width; x++) - { - b += row[x * pixelBytes + 0]; - g += row[x * pixelBytes + 1]; - r += row[x * pixelBytes + 2]; - a += row[x * pixelBytes + 3]; - } + for(int x = 0; x < width; x++) + { + b += row[x * pixelBytes + 0]; + g += row[x * pixelBytes + 1]; + r += row[x * pixelBytes + 2]; + a += row[x * pixelBytes + 3]; } } - else + } + else + { + for(int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); + byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); - for (int x = 0; x < width; x++) - { - b += row[x * pixelBytes + 0]; - g += row[x * pixelBytes + 1]; - r += row[x * pixelBytes + 2]; - } + for(int x = 0; x < width; x++) + { + b += row[x * pixelBytes + 0]; + g += row[x * pixelBytes + 1]; + r += row[x * pixelBytes + 2]; } } } } - - // Get the averages for each channel - const decimal OO_255 = 1m / 255m; - decimal totalPixels = (decimal)(width * height); - - decimal rm = ((decimal)r / totalPixels) * OO_255; - decimal gm = ((decimal)g / totalPixels) * OO_255; - decimal bm = ((decimal)b / totalPixels) * OO_255; - decimal am = ((decimal)a / totalPixels) * OO_255; - - if (pixelBytes == 3) - am = 1m; - - return new Color4((float)rm, (float)gm, (float)bm, (float)am); } - catch (Exception ex) - { - m_log.WarnFormat( - "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", - textureID, j2kData.Length, ex.Message); + // Get the averages for each channel + const decimal OO_255 = 1m / 255m; + decimal totalPixels = (decimal)(width * height); - width = 0; - height = 0; - return new Color4(0.5f, 0.5f, 0.5f, 1.0f); - } + decimal rm = ((decimal)r / totalPixels) * OO_255; + decimal gm = ((decimal)g / totalPixels) * OO_255; + decimal bm = ((decimal)b / totalPixels) * OO_255; + decimal am = ((decimal)a / totalPixels) * OO_255; + + if(pixelBytes == 3) + am = 1m; + + return new Color4((float)rm, (float)gm, (float)bm, (float)am); + + } + catch(Exception ex) + { + m_log.WarnFormat( + "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", + textureID, j2kData.Length, ex.Message); + + width = 0; + height = 0; + return new Color4(0.5f, 0.5f, 0.5f, 1.0f); } } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index e89934399f..da54c543dd 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 // assumed this is 1m less than next grid line int regionsView = (int)m_scene.MaxRegionViewDistance; + + string regionName = m_scene.RegionInfo.RegionName; + ulong regionHandle = m_scene.RegionInfo.RegionHandle; int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY; @@ -1439,25 +1442,52 @@ namespace OpenSim.Region.CoreModules.World.WorldMap g.FillRectangle(sea, 0, 0, spanX, spanY); sea.Dispose(); + Font drawFont = new Font("Arial", 32); + SolidBrush drawBrush = new SolidBrush(Color.White); + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, startX, startY, endX, endY); + startX--; + startY--; + + bool doneLocal = false; + string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png"; + try + { + using(Image localMap = Bitmap.FromFile(filename)) + { + int x = regionX - startX; + int y = regionY - startY; + int sx = regionSizeX; + int sy = regionSizeY; + // y origin is top + g.DrawImage(localMap,new Rectangle(x, spanY - y - sy, sx, sy), + 0, 0, localMap.Width, localMap.Height, GraphicsUnit.Pixel, gatrib); + + if(m_exportPrintRegionName) + { + SizeF stringSize = g.MeasureString(regionName, drawFont); + g.DrawString(regionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); + } + } + doneLocal = true; + } + catch {} + if(regions.Count > 0) { - Font drawFont = new Font("Arial", 32); - SolidBrush drawBrush = new SolidBrush(Color.White); - ManagedImage managedImage = null; Image image = null; - startX--; - startY--; - foreach(GridRegion r in regions) { if(r.TerrainImage == UUID.Zero) continue; + if(doneLocal && r.RegionHandle == regionHandle) + continue; + AssetBase texAsset = m_scene.AssetService.Get(r.TerrainImage.ToString()); if(texAsset == null) continue; @@ -1472,7 +1502,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap g.DrawImage(image,new Rectangle(x, spanY - y - sy, sx, sy), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, gatrib); - if(m_exportPrintRegionName && r.RegionHandle == m_scene.RegionInfo.RegionHandle) + if(m_exportPrintRegionName && r.RegionHandle == regionHandle) { SizeF stringSize = g.MeasureString(r.RegionName, drawFont); g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); @@ -1483,16 +1513,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if(image != null) image.Dispose(); - if(m_exportPrintScale) - { - String drawString = string.Format("{0}m x {1}m", spanX, spanY); - g.DrawString(drawString, drawFont, drawBrush, 30, 30); - } - - drawBrush.Dispose(); - drawFont.Dispose(); } + if(m_exportPrintScale) + { + String drawString = string.Format("{0}m x {1}m", spanX, spanY); + g.DrawString(drawString, drawFont, drawBrush, 30, 30); + } + + drawBrush.Dispose(); + drawFont.Dispose(); gatrib.Dispose(); g.Dispose(); @@ -1689,13 +1719,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { float scale = (float)Constants.RegionSize/(float)mb; using(Bitmap scaledbmp = Util.ResizeImageSolid(mapbmp, (int)(bx * scale), (int)(by * scale))) - data = OpenJPEG.EncodeFromImage(scaledbmp, false); + data = OpenJPEG.EncodeFromImage(scaledbmp, true); } else - data = OpenJPEG.EncodeFromImage(mapbmp, false); + data = OpenJPEG.EncodeFromImage(mapbmp, true); } else - data = OpenJPEG.EncodeFromImage(mapbmp, false); + data = OpenJPEG.EncodeFromImage(mapbmp, true); if (data != null && data.Length > 0) { diff --git a/bin/Warp3D.dll b/bin/Warp3D.dll index d80037c433..f78102215b 100755 Binary files a/bin/Warp3D.dll and b/bin/Warp3D.dll differ