break nap a bit more, add options ExportMapAddScale, ExportMapAddRegionName and (warp3d) AverageTextureColorOnMapTile

httptests
UbitUmarov 2018-05-06 17:32:03 +01:00
parent bf0ece8061
commit dffa628966
5 changed files with 313 additions and 230 deletions

View File

@ -56,7 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[] 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, 65, 87, 47),
Color.FromArgb(255, 157, 145, 131), Color.FromArgb(255, 157, 145, 131),
Color.FromArgb(255, 125, 128, 130) Color.FromArgb(255, 125, 128, 130)
@ -82,7 +84,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
public static Bitmap Splat(ITerrainChannel terrain, public static Bitmap Splat(ITerrainChannel terrain,
UUID[] textureIDs, float[] startHeights, float[] heightRanges, 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(textureIDs.Length == 4);
Debug.Assert(startHeights.Length == 4); Debug.Assert(startHeights.Length == 4);
@ -90,70 +93,81 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
Bitmap[] detailTexture = new Bitmap[4]; 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) if (textureTerrain)
{ {
// Swap empty terrain textureIDs with default IDs // 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]; textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
} }
#region Texture Fetching #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]); UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
// Try to fetch a cached copy of the decoded/resized version of this texture // Try to fetch a cached copy of the decoded/resized version of this texture
asset = assetService.GetCached(cacheID.ToString()); // asset = assetService.GetCached(cacheID.ToString());
if (asset != null) if(asset != null)
{ {
try 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); detailTexture[i] = (Bitmap)Image.FromStream(stream);
} }
catch (Exception ex) catch(Exception ex)
{ {
m_log.Warn("Failed to decode cached terrain texture " + cacheID + m_log.Warn("Failed to decode cached terrain texture " + cacheID +
" (textureID: " + textureIDs[i] + "): " + ex.Message); " (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 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
asset = assetService.Get(textureIDs[i].ToString()); asset = assetService.Get(textureIDs[i].ToString());
if (asset != null) if(asset != null)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } try
catch (Exception ex) {
detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data);
}
catch(Exception ex)
{ {
m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); 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].PixelFormat != PixelFormat.Format24bppRgb ||
if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
{ using(Bitmap origBitmap = detailTexture[i])
using (Bitmap origBitmap = detailTexture[i]) detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16);
{
detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
}
}
// Save the decoded and resized texture to the cache // Save the decoded and resized texture to the cache
byte[] data; 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); detailTexture[i].Save(stream, ImageFormat.Png);
data = stream.ToArray(); data = stream.ToArray();
@ -180,90 +194,96 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
} }
#endregion Texture Fetching #endregion Texture Fetching
} if(averagetextureTerrain)
// Fill in any missing textures with a solid color
for (int i = 0; i < 4; i++)
{
if (detailTexture[i] == null)
{ {
m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", for(int t = 0; t < 4; t++)
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]))
{ {
using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) usecolors = true;
gfx.FillRectangle(brush, 0, 0, 256, 256); 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 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 #region Layer Map
float[,] layermap = new float[256, 256];
// Scale difference between actual region size and the 256 texture being created // Scale difference between actual region size and the 256 texture being created
int xFactor = terrain.Width / 256; float xFactor = terrain.Width / 256f;
int yFactor = terrain.Height / 256; float yFactor = terrain.Height / 256f;
// 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);
}
}
#endregion Layer Map #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 // Unsafe work as we lock down the source textures for quicker access and access the
// pixel data directly // pixel data directly
unsafe if(usecolors)
{ {
// Get handles to all of the texture data arrays unsafe
BitmapData[] datas = new BitmapData[]
{ {
detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), for(int y = 0; y < 256; ++y)
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++)
{ {
float layer = layermap[x, y]; int ty = (int)((255 - y) * yFactor);
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride;
// Select two textures for(int x = 0; x < 256; ++x)
int l0 = (int)Math.Floor(layer); {
int l1 = Math.Min(l0 + 1, 3); 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]; // Select two textures
byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; int l0 = (int)layer;
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; int l1 = Math.Min(l0 + 1, 3);
float aB = *(ptrA + 0); float layerDiff = layer - l0;
float aG = *(ptrA + 1);
float aR = *(ptrA + 2);
float bB = *(ptrB + 0); float a = mapColorsRed[l0];
float bG = *(ptrB + 1); float b = mapColorsRed[l1];
float bR = *(ptrB + 2); *(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 a = mapColorsBlue[l0];
*(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); b = mapColorsBlue[l1];
*(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); *(ptrO++) = (byte)(a + layerDiff * (b - a));
*(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); }
} }
} }
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++) for(int y = 0; y < 256; y++)
if (detailTexture[i] != null) {
detailTexture[i].Dispose(); 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); output.UnlockBits(outputData);
// We generated the texture upside down, so flip it output.Save("terr.png",ImageFormat.Png);
output.RotateFlip(RotateFlipType.RotateNoneFlipY);
#endregion Texture Compositing #endregion Texture Compositing
return output; 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}>", float pctX = (float)x / 255f;
LogHeader, b.Width, b.Height, nWidth, nHeight); float pctY = (float)y / 255f;
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;
Bitmap img = new Bitmap(256, 256); // Use bilinear interpolation between the four corners of start height and
BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); // 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 float heightRange = ImageUtils.Bilinear(
{ heightRanges[0], heightRanges[2],
for (int y = 255; y >= 0; y--) heightRanges[1], heightRanges[3],
{ pctX, pctY);
for (int x = 0; x < 256; x++) heightRange = Utils.Clamp(heightRange, 0f, 255f);
{
float normHeight = heightmap[y * 256 + x] / 255f;
normHeight = Utils.Clamp(normHeight, BASE_HSV_V, 1.0f);
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; float noise = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 13.0f;
*(ptr + 0) = (byte)(color.B * 255f); noise += Perlin.turbulence2(vec.X, vec.Y, 2f) * 4.5f;
*(ptr + 1) = (byte)(color.G * 255f);
*(ptr + 2) = (byte)(color.R * 255f);
}
}
}
img.UnlockBits(bitmapData); // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
return img; float layer = ((height + noise - startHeight) / heightRange) * 4f;
if(Single.IsNaN(layer))
return 0;
return Utils.Clamp(layer, 0f, 3f);
} }
} }
} }

View File

@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
NearPlaneDistance = nearPlaneDist; NearPlaneDistance = nearPlaneDist;
Width = width; Width = width;
Height = height; Height = height;
Orthographic = false;
} }
public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight) public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight)

View File

@ -73,6 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
private IConfigSource m_config; private IConfigSource m_config;
private bool m_drawPrimVolume = true; // true if should render the prims on the tile 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_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 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 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 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_Enabled = true;
m_drawPrimVolume m_drawPrimVolume =
= Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
m_textureTerrain m_textureTerrain =
= Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
m_texturePrims m_textureAvegareTerrain =
= Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); Util.GetConfigVarFromSections<bool>(m_config, "AverageTextureColorOnMapTile", configSections, m_textureAvegareTerrain);
m_texturePrimSize if(m_textureAvegareTerrain)
= Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); m_textureTerrain = true;
m_renderMeshes m_texturePrims =
= Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
m_texturePrimSize =
Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
m_renderMeshes =
Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
@ -168,13 +174,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
Vector3 camPos = new Vector3( Vector3 camPos = new Vector3(
(m_scene.RegionInfo.RegionSizeX) * 0.5f, (m_scene.RegionInfo.RegionSizeX) * 0.5f,
(m_scene.RegionInfo.RegionSizeY) * 0.5f, (m_scene.RegionInfo.RegionSizeY) * 0.5f,
221.7025033688163f); 250f);
// Viewport viewing down onto the region // Viewport viewing down onto the region
Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
(float)m_scene.RegionInfo.RegionSizeX, (float)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; m_primMesher = null;
return tile; 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) 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); 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(); m_colors.Clear();
@ -207,29 +213,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
warp_Vector pos = ConvertVector(viewport.Position); warp_Vector pos = ConvertVector(viewport.Position);
warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); 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.setPos(pos);
renderer.Scene.defaultCamera.lookAt(lookat); 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 #endregion Camera
renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); 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)); renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
CreateWater(renderer); CreateWater(renderer);
CreateTerrain(renderer, m_textureTerrain); CreateTerrain(renderer);
if (m_drawPrimVolume) if (m_drawPrimVolume)
CreateAllPrims(renderer, useTextures); CreateAllPrims(renderer);
renderer.Render(); renderer.Render();
Bitmap bitmap = renderer.Scene.getImage(); Bitmap bitmap = renderer.Scene.getImage();
@ -286,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
// Add a terrain to the renderer. // Add a terrain to the renderer.
// Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for // 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. // 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; 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 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
float diff = regionsx / 256f; float diff = regionsx / 256f;
int npointsx = (int)(regionsx / diff) + 1; int npointsx = (int)(regionsx / diff);
int npointsy = (int)(regionsy / diff) + 1; int npointsy = (int)(regionsy / diff);
float invsx = 1.0f / (npointsx * diff); float invsx = 1.0f / (npointsx);
float invsy = 1.0f / (npointsy * diff); float invsy = 1.0f / (npointsy);
npointsx++;
npointsy++;
// Create all the vertices for the terrain // Create all the vertices for the terrain
warp_Object obj = new warp_Object(); warp_Object obj = new warp_Object();
@ -310,6 +310,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
{ {
for (x = 0; x < regionsx; x += diff) for (x = 0; x < regionsx; x += diff)
{ {
if(x == 48 && y == 36)
{
}
pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]); pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]);
obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy)); 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; warp_Texture texture;
using (Bitmap image = TerrainSplat.Splat( using (Bitmap image = TerrainSplat.Splat(
terrain, textureIDs, startHeights, heightRanges, 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); texture = new warp_Texture(image);
warp_Material material = new warp_Material(texture); warp_Material material = new warp_Material(texture);
material.setReflectivity(50); // material.setReflectivity(50);
renderer.Scene.addMaterial("TerrainColor", material); 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"); renderer.SetObjectMaterial("Terrain", "TerrainColor");
} }
private void CreateAllPrims(WarpRenderer renderer, bool useTextures) private void CreateAllPrims(WarpRenderer renderer)
{ {
if (m_primMesher == null) if (m_primMesher == null)
return; return;
@ -397,13 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
delegate(SceneObjectGroup group) delegate(SceneObjectGroup group)
{ {
foreach (SceneObjectPart child in group.Parts) foreach (SceneObjectPart child in group.Parts)
CreatePrim(renderer, child, useTextures); CreatePrim(renderer, child);
} }
); );
} }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim)
bool useTextures)
{ {
const float MIN_SIZE_SQUARE = 4f; 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); Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
Color4 faceColor = GetFaceColor(teFace); Color4 faceColor = teFace.RGBA;
string materialName = String.Empty; string materialName = String.Empty;
if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize)
materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
else else
materialName = GetOrCreateMaterial(renderer, faceColor); materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace));
faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y);
warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation());
warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
faceObj.transform(m); faceObj.transform(m);
warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
faceObj.setPos(primPos); faceObj.setPos(primPos);
renderer.Scene.addObject(meshName, faceObj); renderer.Scene.addObject(meshName, faceObj);
@ -645,7 +650,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
private static warp_Quaternion ConvertQuaternion(Quaternion quat) 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) private static int ConvertColor(Color4 color)
@ -778,18 +783,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
/// <param name="width">New width</param> /// <param name="width">New width</param>
/// <param name="height">New height</param> /// <param name="height">New height</param>
/// <returns>Resized image</returns> /// <returns>Resized image</returns>
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)) using (Graphics graphics = Graphics.FromImage(result))
{ {
atrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 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; return result;

View File

@ -93,6 +93,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private const double expireResponsesTime = 120.0; // 2 minutes ? private const double expireResponsesTime = 120.0; // 2 minutes ?
//private int CacheRegionsDistance = 256; //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 #region INonSharedRegionModule Members
public virtual void Initialise(IConfigSource config) public virtual void Initialise(IConfigSource config)
{ {
@ -103,6 +106,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
m_Enabled = true; m_Enabled = true;
expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60); expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
m_exportPrintScale =
Util.GetConfigVarFromSections<bool>(config, "ExportMapAddScale", configSections, m_exportPrintScale);
m_exportPrintRegionName =
Util.GetConfigVarFromSections<bool>(config, "ExportMapAddRegionName", configSections, m_exportPrintRegionName);
} }
public virtual void AddRegion(Scene scene) public virtual void AddRegion(Scene scene)
@ -1418,14 +1426,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
int spanY = endY - startY + 2; int spanY = endY - startY + 2;
Bitmap mapTexture = new Bitmap(spanX, spanY); Bitmap mapTexture = new Bitmap(spanX, spanY);
ImageAttributes gatrib = new ImageAttributes();
Graphics g = Graphics.FromImage(mapTexture); Graphics g = Graphics.FromImage(mapTexture);
gatrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 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); SolidBrush sea = new SolidBrush(Color.DarkBlue);
g.FillRectangle(sea, 0, 0, spanX - 1, spanY - 1); g.FillRectangle(sea, 0, 0, spanX, spanY);
sea.Dispose(); sea.Dispose();
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, List<GridRegion> 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 y = r.RegionLocY - startY;
int sx = r.RegionSizeX; int sx = r.RegionSizeX;
int sy = r.RegionSizeY; int sy = r.RegionSizeY;
g.DrawImage(image, x, spanY - y - sy, sx, sy); // y origin is top // y origin is top
if(r.RegionHandle == m_scene.RegionInfo.RegionHandle) 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); SizeF stringSize = g.MeasureString(r.RegionName, drawFont);
g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); 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) if(image != null)
image.Dispose(); image.Dispose();
String drawString = string.Format("{0}m x {1}m", spanX, spanY); if(m_exportPrintScale)
g.DrawString(drawString, drawFont, drawBrush, 30, 30); {
String drawString = string.Format("{0}m x {1}m", spanX, spanY);
g.DrawString(drawString, drawFont, drawBrush, 30, 30);
}
drawBrush.Dispose(); drawBrush.Dispose();
drawFont.Dispose(); drawFont.Dispose();
} }
gatrib.Dispose();
g.Dispose(); g.Dispose();
mapTexture.Save(exportPath, ImageFormat.Jpeg); mapTexture.Save(exportPath, ImageFormat.Jpeg);

Binary file not shown.