diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 226b330bda..ba6ebfc4f1 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 private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[] { - Color.FromArgb(255, 164, 136, 117), +// Color.FromArgb(255, 164, 136, 117), + Color.FromArgb(255, 255, 136, 117), + Color.FromArgb(255, 65, 87, 47), Color.FromArgb(255, 157, 145, 131), Color.FromArgb(255, 125, 128, 130) @@ -82,7 +84,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs, float[] startHeights, float[] heightRanges, - Vector3d regionPosition, IAssetService assetService, bool textureTerrain) + uint regionPositionX,uint regionPositionY, + IAssetService assetService, bool textureTerrain, bool averagetextureTerrain) { Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); @@ -90,70 +93,81 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap Bitmap[] detailTexture = new Bitmap[4]; + byte[] mapColorsRed = new byte[4]; + byte[] mapColorsGreen = new byte[4]; + byte[] mapColorsBlue = new byte[4]; + + bool usecolors = false; + if (textureTerrain) { // Swap empty terrain textureIDs with default IDs - for (int i = 0; i < textureIDs.Length; i++) + for(int i = 0; i < textureIDs.Length; i++) { - if (textureIDs[i] == UUID.Zero) + if(textureIDs[i] == UUID.Zero) textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } #region Texture Fetching - if (assetService != null) + if(assetService != null) { - for (int i = 0; i < 4; i++) + for(int i = 0; i < 4; i++) { - AssetBase asset; + AssetBase asset = null; UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); // Try to fetch a cached copy of the decoded/resized version of this texture - asset = assetService.GetCached(cacheID.ToString()); - if (asset != null) + // asset = assetService.GetCached(cacheID.ToString()); + if(asset != null) { try { - using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) + using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); } - catch (Exception ex) + 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; + } } - if (detailTexture[i] == null) + if(detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG asset = assetService.Get(textureIDs[i].ToString()); - if (asset != null) + 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); } - catch (Exception ex) + try + { + detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); + } + catch(Exception ex) { m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); } } - if (detailTexture[i] != null) + if(detailTexture[i] != null) { - // Make sure this texture is the correct size, otherwise resize - if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) - { - using (Bitmap origBitmap = detailTexture[i]) - { - detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256); - } - } + if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || + detailTexture[i].Width != 16 || detailTexture[i].Height != 16) + using(Bitmap origBitmap = detailTexture[i]) + detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16); // Save the decoded and resized texture to the cache byte[] data; - using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) + using(System.IO.MemoryStream stream = new System.IO.MemoryStream()) { detailTexture[i].Save(stream, ImageFormat.Png); data = stream.ToArray(); @@ -180,90 +194,96 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } #endregion Texture Fetching - } - - // Fill in any missing textures with a solid color - for (int i = 0; i < 4; i++) - { - if (detailTexture[i] == null) + if(averagetextureTerrain) { - m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", - LogHeader, i); - // Create a solid color texture for this layer - detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); - using (Graphics gfx = Graphics.FromImage(detailTexture[i])) + for(int t = 0; t < 4; t++) { - using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) - gfx.FillRectangle(brush, 0, 0, 256, 256); + usecolors = true; + if(detailTexture[t] == null) + { + mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R; + mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G; + mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B; + continue; + } + + int npixeis = 0; + int cR = 0; + int cG = 0; + int cB = 0; + + BitmapData bmdata = detailTexture[t].LockBits(new Rectangle(0, 0, 16, 16), + ImageLockMode.ReadOnly, detailTexture[t].PixelFormat); + + npixeis = bmdata.Height * bmdata.Width; + int ylen = bmdata.Height * bmdata.Stride; + + unsafe + { + for(int y = 0; y < ylen; y += bmdata.Stride) + { + byte* ptrc = (byte*)bmdata.Scan0 + y; + for(int x = 0 ; x < bmdata.Width; ++x) + { + cR += *(ptrc++); + cG += *(ptrc++); + cB += *(ptrc++); + } + } + + } + detailTexture[t].UnlockBits(bmdata); + detailTexture[t].Dispose(); + + mapColorsRed[t] = (byte)Util.Clamp(cR / npixeis, 0 , 255); + mapColorsGreen[t] = (byte)Util.Clamp(cG / npixeis, 0 , 255); + mapColorsBlue[t] = (byte)Util.Clamp(cB / npixeis, 0 , 255); } } else { - if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) + // Fill in any missing textures with a solid color + for(int i = 0; i < 4; i++) { - detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); + if(detailTexture[i] == null) + { + m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", LogHeader, i); + + // Create a solid color texture for this layer + detailTexture[i] = new Bitmap(16, 16, PixelFormat.Format24bppRgb); + using(Graphics gfx = Graphics.FromImage(detailTexture[i])) + { + using(SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) + gfx.FillRectangle(brush, 0, 0, 16, 16); + } + } + else + { + if(detailTexture[i].Width != 16 || detailTexture[i].Height != 16) + { + using(Bitmap origBitmap = detailTexture[i]) + detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16); + } + } } } } + else + { + usecolors = true; + for(int t = 0; t < 4; t++) + { + mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R; + mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G; + mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B; + } + } #region Layer Map - float[,] layermap = new float[256, 256]; - // Scale difference between actual region size and the 256 texture being created - int xFactor = terrain.Width / 256; - int yFactor = terrain.Height / 256; - - // Create 'layermap' where each value is the fractional layer number to place - // at that point. For instance, a value of 1.345 gives the blending of - // layer 1 and layer 2 for that point. - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - float height = (float)terrain[x * xFactor, y * yFactor]; - - 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( - startHeights[0], - startHeights[2], - startHeights[1], - startHeights[3], - pctX, pctY); - startHeight = Utils.Clamp(startHeight, 0f, 255f); - - float heightRange = ImageUtils.Bilinear( - heightRanges[0], - heightRanges[2], - heightRanges[1], - heightRanges[3], - pctX, pctY); - heightRange = Utils.Clamp(heightRange, 0f, 255f); - - // Generate two frequencies of perlin noise based on our global position - // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting - Vector3 vec = new Vector3 - ( - ((float)regionPosition.X + (x * xFactor)) * 0.20319f, - ((float)regionPosition.Y + (y * yFactor)) * 0.20319f, - height * 0.25f - ); - - float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; - float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; - float noise = (lowFreq + highFreq) * 2f; - - // Combine the current height, generated noise, start height, and height range parameters, then scale all of it - float layer = ((height + noise - startHeight) / heightRange) * 4f; - if (Single.IsNaN(layer)) - layer = 0f; - layermap[x, y] = Utils.Clamp(layer, 0f, 3f); - } - } + float xFactor = terrain.Width / 256f; + float yFactor = terrain.Height / 256f; #endregion Layer Map @@ -274,115 +294,152 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // Unsafe work as we lock down the source textures for quicker access and access the // pixel data directly - unsafe + if(usecolors) { - // Get handles to all of the texture data arrays - BitmapData[] datas = new BitmapData[] + unsafe { - detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), - detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), - detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), - detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) - }; - - // Compute size of each pixel data (used to address into the pixel data array) - int[] comps = new int[] - { - (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, - (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, - (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, - (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 - }; - - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) + for(int y = 0; y < 256; ++y) { - float layer = layermap[x, y]; + int ty = (int)((255 - y) * yFactor); + byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; - // Select two textures - int l0 = (int)Math.Floor(layer); - int l1 = Math.Min(l0 + 1, 3); + for(int x = 0; x < 256; ++x) + { + int tx = (int)(x * xFactor); + float height = (float)terrain[tx, ty]; + float layer = getLayerTex(height, x, (255 - y), + (uint)tx + regionPositionX, (uint)ty + regionPositionY, + startHeights, heightRanges); - byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; - byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; - byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; + // Select two textures + int l0 = (int)layer; + int l1 = Math.Min(l0 + 1, 3); - float aB = *(ptrA + 0); - float aG = *(ptrA + 1); - float aR = *(ptrA + 2); + float layerDiff = layer - l0; - float bB = *(ptrB + 0); - float bG = *(ptrB + 1); - float bR = *(ptrB + 2); + float a = mapColorsRed[l0]; + float b = mapColorsRed[l1]; + *(ptrO++) = (byte)(a + layerDiff * (b - a)); - float layerDiff = layer - l0; + a = mapColorsGreen[l0]; + b = mapColorsGreen[l1]; + *(ptrO++) = (byte)(a + layerDiff * (b - a)); - // Interpolate between the two selected textures - *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); - *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); - *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); + a = mapColorsBlue[l0]; + b = mapColorsBlue[l1]; + *(ptrO++) = (byte)(a + layerDiff * (b - a)); + } } } - - for (int i = 0; i < detailTexture.Length; i++) - detailTexture[i].UnlockBits(datas[i]); } + else + { + unsafe + { + // Get handles to all of the texture data arrays + BitmapData[] datas = new BitmapData[] + { + detailTexture[0].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), + detailTexture[1].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), + detailTexture[2].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), + detailTexture[3].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) + }; - for (int i = 0; i < detailTexture.Length; i++) - if (detailTexture[i] != null) - detailTexture[i].Dispose(); + for(int y = 0; y < 256; y++) + { + int ty = (int)((255 - y) * yFactor); + int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; + + for(int x = 0; x < 256; x++) + { + int tx = (int)(x * xFactor); + float height = (float)terrain[tx, ty]; + float layer = getLayerTex(height, x, (255 - y), + (uint)tx + regionPositionX, (uint)ty + regionPositionY, + startHeights, heightRanges); + + // Select two textures + int l0 = (int)layer; + int 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); + + float bB = *(ptrB + 0); + float bG = *(ptrB + 1); + float bR = *(ptrB + 2); + + float layerDiff = layer - l0; + + // Interpolate between the two selected textures + *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); + *(ptrO + 1) = (byte)(aG + layerDiff * (bG - aG)); + *(ptrO + 2) = (byte)(aR + layerDiff * (bR - aR)); + } + } + + for(int i = 0; i < detailTexture.Length; i++) + detailTexture[i].UnlockBits(datas[i]); + } + + for(int i = 0; i < detailTexture.Length; i++) + if(detailTexture[i] != null) + detailTexture[i].Dispose(); + } output.UnlockBits(outputData); - // We generated the texture upside down, so flip it - output.RotateFlip(RotateFlipType.RotateNoneFlipY); +output.Save("terr.png",ImageFormat.Png); #endregion Texture Compositing return output; } - public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight) + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + private static float getLayerTex(float height, int x, int y, uint sourceX, uint sourceY, + float[] startHeights, float[] heightRanges) { - m_log.DebugFormat("{0} ResizeBitmap. From <{1},{2}> to <{3},{4}>", - LogHeader, b.Width, b.Height, nWidth, nHeight); - Bitmap result = new Bitmap(nWidth, nHeight); - using (Graphics g = Graphics.FromImage(result)) - g.DrawImage(b, 0, 0, nWidth, nHeight); - b.Dispose(); - return result; - } - public static Bitmap SplatSimple(float[] heightmap) - { - const float BASE_HSV_H = 93f / 360f; - const float BASE_HSV_S = 44f / 100f; - const float BASE_HSV_V = 34f / 100f; + float pctX = (float)x / 255f; + float pctY = (float)y / 255f; - Bitmap img = new Bitmap(256, 256); - BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); + // 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( + startHeights[0], startHeights[2], + startHeights[1], startHeights[3], + pctX, pctY); + startHeight = Utils.Clamp(startHeight, 0f, 255f); - unsafe - { - for (int y = 255; y >= 0; y--) - { - for (int x = 0; x < 256; x++) - { - float normHeight = heightmap[y * 256 + x] / 255f; - normHeight = Utils.Clamp(normHeight, BASE_HSV_V, 1.0f); + float heightRange = ImageUtils.Bilinear( + heightRanges[0], heightRanges[2], + heightRanges[1], heightRanges[3], + pctX, pctY); + heightRange = Utils.Clamp(heightRange, 0f, 255f); - Color4 color = Color4.FromHSV(BASE_HSV_H, BASE_HSV_S, normHeight); + // Generate two frequencies of perlin noise based on our global position + // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting + Vector3 vec = new Vector3 + ( + sourceX * 0.20319f, + sourceY * 0.20319f, + height * 0.25f + ); - byte* ptr = (byte*)bitmapData.Scan0 + y * bitmapData.Stride + x * 3; - *(ptr + 0) = (byte)(color.B * 255f); - *(ptr + 1) = (byte)(color.G * 255f); - *(ptr + 2) = (byte)(color.R * 255f); - } - } - } + float noise = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 13.0f; + noise += Perlin.turbulence2(vec.X, vec.Y, 2f) * 4.5f; - img.UnlockBits(bitmapData); - return img; + // Combine the current height, generated noise, start height, and height range parameters, then scale all of it + float layer = ((height + noise - startHeight) / heightRange) * 4f; + if(Single.IsNaN(layer)) + return 0; + return Utils.Clamp(layer, 0f, 3f); } } } diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs index 472f86e5fa..5ea4d29c32 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 NearPlaneDistance = nearPlaneDist; Width = width; Height = height; + Orthographic = false; } 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 387248c8f6..9186fae8a0 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 private IConfigSource m_config; private bool m_drawPrimVolume = true; // true if should render the prims on the tile private bool m_textureTerrain = true; // true if to create terrain splatting texture + private bool m_textureAvegareTerrain = true; // replace terrain textures by their average color private bool m_texturePrims = true; // true if should texture the rendered prims private float m_texturePrimSize = 48f; // size of prim before we consider texturing it 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 m_Enabled = true; - m_drawPrimVolume - = Util.GetConfigVarFromSections(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); - m_textureTerrain - = Util.GetConfigVarFromSections(m_config, "TextureOnMapTile", configSections, m_textureTerrain); - m_texturePrims - = Util.GetConfigVarFromSections(m_config, "TexturePrims", configSections, m_texturePrims); - m_texturePrimSize - = Util.GetConfigVarFromSections(m_config, "TexturePrimSize", configSections, m_texturePrimSize); - m_renderMeshes - = Util.GetConfigVarFromSections(m_config, "RenderMeshes", configSections, m_renderMeshes); + m_drawPrimVolume = + Util.GetConfigVarFromSections(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); + m_textureTerrain = + Util.GetConfigVarFromSections(m_config, "TextureOnMapTile", configSections, m_textureTerrain); + m_textureAvegareTerrain = + Util.GetConfigVarFromSections(m_config, "AverageTextureColorOnMapTile", configSections, m_textureAvegareTerrain); + if(m_textureAvegareTerrain) + m_textureTerrain = true; + m_texturePrims = + Util.GetConfigVarFromSections(m_config, "TexturePrims", configSections, m_texturePrims); + m_texturePrimSize = + Util.GetConfigVarFromSections(m_config, "TexturePrimSize", configSections, m_texturePrimSize); + m_renderMeshes = + Util.GetConfigVarFromSections(m_config, "RenderMeshes", configSections, m_renderMeshes); + } public void AddRegion(Scene scene) @@ -168,13 +174,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap Vector3 camPos = new Vector3( (m_scene.RegionInfo.RegionSizeX) * 0.5f, (m_scene.RegionInfo.RegionSizeY) * 0.5f, - 221.7025033688163f); + 250f); // Viewport viewing down onto the region Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY); - Bitmap tile = CreateMapTile(viewport, false); + Bitmap tile = CreateMapTile(viewport); m_primMesher = null; return tile; /* @@ -187,10 +193,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) { Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height); - return CreateMapTile(viewport, useTextures); + return CreateMapTile(viewport); } - public Bitmap CreateMapTile(Viewport viewport, bool useTextures) + public Bitmap CreateMapTile(Viewport viewport) { m_colors.Clear(); @@ -207,29 +213,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Vector pos = ConvertVector(viewport.Position); warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); + + renderer.Scene.defaultCamera.setOrthographic(true, viewport.OrthoWindowWidth, viewport.OrthoWindowHeight); + renderer.Scene.defaultCamera.setPos(pos); renderer.Scene.defaultCamera.lookAt(lookat); - - if (viewport.Orthographic) - { - renderer.Scene.defaultCamera.setOrthographic(true,viewport.OrthoWindowWidth, viewport.OrthoWindowHeight); - } - else - { - float fov = viewport.FieldOfView; - fov *= 1.75f; // FIXME: ??? - renderer.Scene.defaultCamera.setFov(fov); - } - #endregion Camera renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); CreateWater(renderer); - CreateTerrain(renderer, m_textureTerrain); + CreateTerrain(renderer); if (m_drawPrimVolume) - CreateAllPrims(renderer, useTextures); + CreateAllPrims(renderer); renderer.Render(); Bitmap bitmap = renderer.Scene.getImage(); @@ -286,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // Add a terrain to the renderer. // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for // full resolution. This saves a lot of memory especially for very large regions. - private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) + private void CreateTerrain(WarpRenderer renderer) { ITerrainChannel terrain = m_scene.Heightmap; @@ -296,11 +293,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding float diff = regionsx / 256f; - int npointsx = (int)(regionsx / diff) + 1; - int npointsy = (int)(regionsy / diff) + 1; + int npointsx = (int)(regionsx / diff); + int npointsy = (int)(regionsy / diff); - float invsx = 1.0f / (npointsx * diff); - float invsy = 1.0f / (npointsy * diff); + float invsx = 1.0f / (npointsx); + float invsy = 1.0f / (npointsy); + + npointsx++; + npointsy++; // Create all the vertices for the terrain warp_Object obj = new warp_Object(); @@ -310,6 +310,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap { for (x = 0; x < regionsx; x += diff) { + if(x == 48 && y == 36) + { + + } pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]); obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy)); } @@ -378,17 +382,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Texture texture; using (Bitmap image = TerrainSplat.Splat( terrain, textureIDs, startHeights, heightRanges, - new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) + m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY, + m_scene.AssetService, m_textureTerrain, m_textureAvegareTerrain)) texture = new warp_Texture(image); warp_Material material = new warp_Material(texture); - material.setReflectivity(50); +// material.setReflectivity(50); renderer.Scene.addMaterial("TerrainColor", material); - renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif +// renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif renderer.SetObjectMaterial("Terrain", "TerrainColor"); } - private void CreateAllPrims(WarpRenderer renderer, bool useTextures) + private void CreateAllPrims(WarpRenderer renderer) { if (m_primMesher == null) return; @@ -397,13 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap delegate(SceneObjectGroup group) { foreach (SceneObjectPart child in group.Parts) - CreatePrim(renderer, child, useTextures); + CreatePrim(renderer, child); } ); } - private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, - bool useTextures) + private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) { const float MIN_SIZE_SQUARE = 4f; @@ -489,19 +493,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); - Color4 faceColor = GetFaceColor(teFace); + Color4 faceColor = teFace.RGBA; string materialName = String.Empty; if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); else - materialName = GetOrCreateMaterial(renderer, faceColor); + materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace)); faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); - warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); faceObj.transform(m); + + warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); faceObj.setPos(primPos); renderer.Scene.addObject(meshName, faceObj); @@ -645,7 +650,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private static warp_Quaternion ConvertQuaternion(Quaternion quat) { - return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W); + return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W); } private static int ConvertColor(Color4 color) @@ -778,18 +783,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap /// New width /// New height /// Resized image - public static Bitmap ResizeImage(Image image, int width, int height) + public static Bitmap ResizeImageSolid(Image image, int width, int height) { - Bitmap result = new Bitmap(width, height); + Bitmap result = new Bitmap(width, height, PixelFormat.Format24bppRgb); + using (ImageAttributes atrib = new ImageAttributes()) using (Graphics graphics = Graphics.FromImage(result)) { + atrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY); graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; - graphics.DrawImage(image, 0, 0, result.Width, result.Height); + graphics.DrawImage(image,new Rectangle(0,0, result.Width, result.Height), + 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, atrib); } return result; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 476d90a2ef..4b14c71964 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 private const double expireResponsesTime = 120.0; // 2 minutes ? //private int CacheRegionsDistance = 256; + private bool m_exportPrintScale = false; // prints the scale of map in meters on exported map + private bool m_exportPrintRegionName = false; // prints the region name exported map + #region INonSharedRegionModule Members public virtual void Initialise(IConfigSource config) { @@ -103,6 +106,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_Enabled = true; expireBlackListTime = (double)Util.GetConfigVarFromSections(config, "BlacklistTimeout", configSections, 10 * 60); + + m_exportPrintScale = + Util.GetConfigVarFromSections(config, "ExportMapAddScale", configSections, m_exportPrintScale); + m_exportPrintRegionName = + Util.GetConfigVarFromSections(config, "ExportMapAddRegionName", configSections, m_exportPrintRegionName); } public virtual void AddRegion(Scene scene) @@ -1418,14 +1426,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap int spanY = endY - startY + 2; Bitmap mapTexture = new Bitmap(spanX, spanY); + ImageAttributes gatrib = new ImageAttributes(); Graphics g = Graphics.FromImage(mapTexture); + gatrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY); g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; SolidBrush sea = new SolidBrush(Color.DarkBlue); - g.FillRectangle(sea, 0, 0, spanX - 1, spanY - 1); + g.FillRectangle(sea, 0, 0, spanX, spanY); sea.Dispose(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -1457,8 +1467,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap int y = r.RegionLocY - startY; int sx = r.RegionSizeX; int sy = r.RegionSizeY; - g.DrawImage(image, x, spanY - y - sy, sx, sy); // y origin is top - if(r.RegionHandle == m_scene.RegionInfo.RegionHandle) + // y origin is top + 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) { SizeF stringSize = g.MeasureString(r.RegionName, drawFont); g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); @@ -1469,13 +1482,17 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if(image != null) image.Dispose(); - String drawString = string.Format("{0}m x {1}m", spanX, spanY); - g.DrawString(drawString, drawFont, drawBrush, 30, 30); + 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(); mapTexture.Save(exportPath, ImageFormat.Jpeg); diff --git a/bin/Warp3D.dll b/bin/Warp3D.dll index 520e04cf01..4000aebd60 100755 Binary files a/bin/Warp3D.dll and b/bin/Warp3D.dll differ