breaking map a bit more...

httptests
UbitUmarov 2018-05-15 23:56:12 +01:00
parent f87219975d
commit 06d6c4abda
4 changed files with 329 additions and 226 deletions

View File

@ -80,10 +80,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
/// Note we create a 256x256 dimension texture even if the actual terrain is larger.
/// </remarks>
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(

View File

@ -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<UUID, Color4> m_colors = new Dictionary<UUID, Color4>();
internal IJ2KDecoder m_imgDecoder;
// caches per rendering
private Dictionary<string, warp_Texture> m_warpTextures = new Dictionary<string, warp_Texture>();
private Dictionary<UUID, int> m_colors = new Dictionary<UUID, int>();
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<IJ2KDecoder>();
}
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<IJ2KDecoder>();
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<IJ2KDecoder>();
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);
}
}

View File

@ -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<GridRegion> 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)
{

Binary file not shown.