diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index df5ac92bb4..91ca7e2ff6 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs @@ -32,6 +32,7 @@ using System.Drawing.Imaging; using log4net; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Warp3DMap @@ -66,6 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Constants private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); + private static string LogHeader = "[WARP3D TERRAIN SPLAT]"; /// /// Builds a composited terrain texture given the region texture @@ -76,9 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap /// A composited 256x256 RGB texture ready for rendering /// Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// - public static Bitmap Splat(float[] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) + public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) { - Debug.Assert(heightmap.Length == 256 * 256); Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); @@ -200,17 +201,27 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap gfx.FillRectangle(brush, 0, 0, 256, 256); } } + else + { + if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) + { + detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); + } + } } #region Layer Map - float[] layermap = new float[256 * 256]; + float[,] layermap = new float[256 , 256]; + + int xFactor = terrain.Width / 256; + int yFactor = terrain.Height / 256; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { - float height = heightmap[y * 256 + x]; + float height = (float)terrain[x * xFactor, y * yFactor]; float pctX = (float)x / 255f; float pctY = (float)y / 255f; @@ -237,8 +248,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( - ((float)regionPosition.X + x) * 0.20319f, - ((float)regionPosition.Y + y) * 0.20319f, + ((float)regionPosition.X + (x * xFactor)) * 0.20319f, + ((float)regionPosition.Y + (y * yFactor)) * 0.20319f, height * 0.25f ); @@ -249,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap // 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[y * 256 + x] = Utils.Clamp(layer, 0f, 3f); + layermap[x,y] = Utils.Clamp(layer, 0f, 3f); } } @@ -283,7 +294,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap { for (int x = 0; x < 256; x++) { - float layer = layermap[y * 256 + x]; + float layer = layermap[x, y]; // Select two textures int l0 = (int)Math.Floor(layer); @@ -331,6 +342,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return output; } + public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight) + { + 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; diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index d38f34ba9c..17066bdc3c 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -136,8 +136,15 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap m_primMesher = RenderingLoader.LoadRenderer(renderers[0]); } - Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); - Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize); + Vector3 camPos = new Vector3( + m_scene.RegionInfo.RegionSizeX / 2 - 0.5f, + m_scene.RegionInfo.RegionSizeY / 2 - 0.5f, + 221.7025033688163f); + // 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); m_primMesher = null; @@ -254,8 +261,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap { float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; - renderer.AddPlane("Water", 256f * 0.5f); - renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); + renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f); + renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX / 2 - 0.5f, + waterHeight, + m_scene.RegionInfo.RegionSizeY / 2 - 0.5f); renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif @@ -266,45 +275,51 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) { ITerrainChannel terrain = m_scene.Heightmap; - float[] heightmap = terrain.GetFloatsSerialised(); + + // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding + float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f; warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2); - for (int y = 0; y < 256; y++) + // Create all the vertices for the terrain + for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) { - for (int x = 0; x < 256; x++) + for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) { - int v = y * 256 + x; - float height = heightmap[v]; - - warp_Vector pos = ConvertVector(new Vector3(x, y, height)); - obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f)); + warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]); + obj.addVertex(new warp_Vertex(pos, + x / (float)m_scene.RegionInfo.RegionSizeX, + (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY)); } } - for (int y = 0; y < 256; y++) + // Now that we have all the vertices, make another pass and create + // the normals for each of the surface triangles and + // create the list of triangle indices. + for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) { - for (int x = 0; x < 256; x++) + for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) { - if (x < 255 && y < 255) + float newX = x / diff; + float newY = y / diff; + if (newX < 255 && newY < 255) { - int v = y * 256 + x; + int v = (int)newY * 256 + (int)newX; - // Normal - Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]); - Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]); - Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]); + // Normal for a triangle made up of three adjacent vertices + Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]); + Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]); + Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]); warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3)); norm = norm.reverse(); obj.vertex(v).n = norm; - // Triangle 1 + // Make two triangles for each of the squares in the grid of vertices obj.addTriangle( v, v + 1, v + 256); - // Triangle 2 obj.addTriangle( v + 256 + 1, v + 256, @@ -337,14 +352,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap heightRanges[3] = (float)regionInfo.Elevation2NE; uint globalX, globalY; - Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); + Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); warp_Texture texture; using ( Bitmap image = TerrainSplat.Splat( - heightmap, textureIDs, startHeights, heightRanges, + terrain, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) { texture = new warp_Texture(image); @@ -534,6 +549,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Rendering Methods #region Static Helpers + // Note: axis change. + private static warp_Vector ConvertVector(float x, float y, float z) + { + return new warp_Vector(x, z, y); + } private static warp_Vector ConvertVector(Vector3 vector) {