OSDN Git Service

Fixed shading EDGE Defects on Chunk boundary / Missing data
[automap/automap.git] / Automap / Renderers / StandardRenderer.cs
index 09a551f..415f488 100644 (file)
@@ -1,5 +1,8 @@
 using System;
 using System.Collections.Generic;
+//using System.Drawing;
+//using System.Drawing.Imaging;
+//using System.IO;
 using System.Linq;
 
 using Hjg.Pngcs;
@@ -13,6 +16,7 @@ namespace Automap
 {
        public class StandardRenderer : AChunkRenderer
        {
+               public const string Name = @"Standard";
 
                /// <summary>
                /// Renders shards similar to the Default VS version, plus P.O.I. markings.
@@ -21,10 +25,10 @@ namespace Automap
                /// <param name="logger">Logger.</param>
                public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger, bool seasonalColor) : base(clientAPI, logger, seasonalColor)
                {
-
+                       
                }
 
-               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta targetColMeta, ref ColumnsMetadata allCols, out uint pixelCount)
+               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mapChunk, ColumnMeta targetColMeta, ref ColumnsMetadata allCols, out uint pixelCount)
                {
                pixelCount = 0;
                BlockPos tmpPos = new BlockPos( );
@@ -49,46 +53,96 @@ namespace Automap
                }
                }
 
-               // Prefetch map chunks, in pattern
-               var mapCornerChunks = new List<ColumnMeta>(3);
-
-               var south_west = new Vec2i(chunkPos.X - 1, chunkPos.Y - 1);
-               var west = new Vec2i(chunkPos.X - 1, chunkPos.Y);
-               var south = new Vec2i(chunkPos.X, chunkPos.Y - 1);
+               // Prefetch map chunks, in pattern              
+               var corner_pos = new Vec2i(chunkPos.X - 1, chunkPos.Y - 1);
+               var west_pos = new Vec2i(chunkPos.X, chunkPos.Y - 1);
+               var north_pos = new Vec2i(chunkPos.X - 1 , chunkPos.Y);
 
-               bool nullSouthWest = false, nullSouth = false, nullWest = false;
+               uint missingRainmap = 0, missingHeightmap = 0;
 
+               ColumnMeta north, northWest, west;
                /* 
-               For missing corners / cardinal heightmaps...
-               make fake heightmap dummy
+                 "Overlap" Heightmap for Slope (height) values; covers 1 whole + 2 chunk edges, and corner block,
+                  substitute ZERO with Average Height....better than nothing even if its wrong?
                */
+               var overlapHeightmap = new ushort[chunkSize + 1, chunkSize + 1];
 
-               if (allCols.Contains(south_west)) {
-               mapCornerChunks.Add(allCols[south_west]);               
-               }
-               else {
-               nullSouthWest = true;
-               mapCornerChunks.Add(targetColMeta);//Temporary!
+               //Ofset copy of Heightmap...copied to Bottom, Rightmost
+               for (int copyX = 0; copyX < chunkSize; copyX++)
+               {
+                       for (int copyY = 0; copyY < chunkSize; copyY++) {
+                               overlapHeightmap[copyX + 1, copyY + 1] = targetColMeta.HeightMap[copyX, copyY];
+                       }                       
                }
 
-               if (allCols.Contains(south)) {
-               mapCornerChunks.Add(allCols[south]);
+
+
+               if (allCols.Contains(corner_pos) && allCols[corner_pos].HeightMap != null) {
+               northWest = allCols[corner_pos];
+               overlapHeightmap[0, 0] = northWest.HeightMap[chunkSize - 1, chunkSize - 1];
                }
                else {
-               nullSouth = true;
-               mapCornerChunks.Add(targetColMeta);//Temporary!
-               }
+               missingHeightmap++;
+               var cornerMC = ClientAPI.World.BlockAccessor.GetMapChunk(corner_pos);
+               if (cornerMC != null && cornerMC.RainHeightMap != null) 
+                       {
+                       overlapHeightmap[0, 0] = cornerMC.RainHeight2DMap(chunkSize - 1, (chunkSize - 1));
+                       } else missingRainmap++;
+               } 
+               
+               if (allCols.Contains(north_pos) && allCols[north_pos].HeightMap != null) {
+               north = allCols[north_pos];
 
-               if (allCols.Contains(west)) {
-               mapCornerChunks.Add(allCols[west]);
+                       for (int northEdgeIndex = 0; northEdgeIndex < chunkSize; northEdgeIndex++) 
+                       {
+                       overlapHeightmap[0, northEdgeIndex + 1 ] = north.HeightMap[ (chunkSize - 1), northEdgeIndex];                   
+                       }
+               }               
+               else {
+                       missingHeightmap++;
+                       var northMC = ClientAPI.World.BlockAccessor.GetMapChunk(north_pos);
+                       if (northMC != null && northMC.RainHeightMap != null) {
+                               for (int northEdgeIndex = 0; northEdgeIndex < chunkSize; northEdgeIndex++) 
+                               {
+                               overlapHeightmap[0, northEdgeIndex + 1] = northMC.RainHeight2DMap((chunkSize - 1), northEdgeIndex);
+                               }
+                       } else missingRainmap++;
                }
+
+               if (allCols.Contains(west_pos) && allCols[west_pos].HeightMap != null) {
+               west = allCols[west_pos];
+
+                       for (int westEdgeIndex = 0; westEdgeIndex < chunkSize; westEdgeIndex++) 
+                       {
+                       overlapHeightmap[westEdgeIndex + 1, 0] = west.HeightMap[westEdgeIndex, chunkSize - 1];
+                       }
+               }               
                else {
-               nullWest = true;
-               mapCornerChunks.Add(targetColMeta);//Temporary!
+               missingHeightmap++;
+               var westMC = ClientAPI.World.BlockAccessor.GetMapChunk(west_pos);
+               if (westMC != null && westMC.RainHeightMap != null) {
+               for (int westEdgeIndex = 0; westEdgeIndex < chunkSize; westEdgeIndex++) {
+               overlapHeightmap[westEdgeIndex + 1, 0] = westMC.RainHeight2DMap(westEdgeIndex, chunkSize - 1);
                }
+               } else missingRainmap++;
+               }
+               
+               ushort avgOverlap_Y = ( ushort )overlapHeightmap.OfType<ushort>( ).Average((ushort sel) => sel == 0 ? targetColMeta.YMax : sel);                                
+               //TODO: Row - then - Column averaging at Edges?
+
+               #if DEBUG
+               var badHeightData = overlapHeightmap.OfType<ushort>( ).Count((ushort arg) => arg == 0); 
+
+               if (badHeightData > 0)
+               Logger.VerboseDebug("H.M Zeros# {0} , Missing Rainmaps {1} Heightmaps {2}",badHeightData ,missingRainmap, missingHeightmap);
+
+               //RenderDebugBitmap(overlapHeightmap, chunkPos);
+               #endif
+               
 
 
                for (int pixelIndex = 0; pixelIndex < (chunkSize * chunkSize); pixelIndex++) {
+               /********* PIXEL RENDERING LOOP **********/
                MapUtil.PosInt2d(pixelIndex, chunkSize, localpos);
                int localX = localpos.X;
                int localZ = localpos.Y;
@@ -96,53 +150,37 @@ namespace Automap
 
                int localChunkY = localY / chunkSize;
                if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
-               if (chunksColumn[localChunkY] == null) continue;//BIG Gaps!
-               //if (mapCornerChunks.Any(chks => chks == null)) {
-               //Logger.Warning("mapCornerChunks A.W.O.L. near : X{0} Y{1} Z{2}        - ", localX, localY, localZ);
-               //continue;
-               //}
-
-               float slopeBoost = 1;
-               int leftTop, rightTop, leftBot;
-
-               ColumnMeta leftTopMapChunk = targetColMeta;
-               ColumnMeta rightTopMapChunk = targetColMeta;
-               ColumnMeta leftBotMapChunk = targetColMeta;
-
-               int topX = localX - 1;
-               int botX = localX;
-               int leftZ = localZ - 1;
-               int rightZ = localZ;
-
-               if (topX < 0 && leftZ < 0) {
-               leftTopMapChunk = mapCornerChunks[0];
-               rightTopMapChunk = mapCornerChunks[1];
-               leftBotMapChunk = mapCornerChunks[2];
-               }
-               else {
-               if (topX < 0) {
-               leftTopMapChunk = mapCornerChunks[1];
-               rightTopMapChunk = mapCornerChunks[1];
-               }
-               if (leftZ < 0) {
-               leftTopMapChunk = mapCornerChunks[2];
-               leftBotMapChunk = mapCornerChunks[2];
-               }
+               if (chunksColumn[localChunkY] == null) 
+               {
+               #if DEBUG
+               Logger.VerboseDebug("Gap in chunk-column at render time Chunk-Y:{0}", localChunkY);
+               #endif
+               continue;
                }
 
-               topX = GameMath.Mod(topX, chunkSize);
-               leftZ = GameMath.Mod(leftZ, chunkSize);
-               
-               leftTop = nullSouthWest ? 0 : Math.Sign(localY - leftTopMapChunk.HeightMap[topX, leftZ]);
-               rightTop = nullSouth ? 0 : Math.Sign(localY - rightTopMapChunk.HeightMap[topX, rightZ]);
-               leftBot = nullWest ? 0 : Math.Sign(localY - leftBotMapChunk.HeightMap[botX, leftZ]);
+               float slopeBoost = 1f;
+               int northH, northWestH, westH;
 
-               float slopeness = (leftTop + rightTop + leftBot);
+               int north_X = localX + 1;
+               int north_Z = localZ;
+               int west_X = localX;
+               int west_Z = localZ + 1;
+               int northWest_X = localX;
+               int northWest_Z = localZ;
+               bool edge = localX == 0 || localZ == 0;
+                       
+               northH = Math.Sign(localY - (overlapHeightmap[north_X, north_Z] == 0 ? localY : overlapHeightmap[north_X, north_Z]));
+               northWestH = Math.Sign(localY - (overlapHeightmap[northWest_X, northWest_Z] == 0 ? localY : overlapHeightmap[northWest_X, northWest_Z]));
+               westH  = Math.Sign(localY - (overlapHeightmap[west_X, west_Z] == 0 ? localY : overlapHeightmap[west_X, west_Z]));
 
-               if (slopeness > 0) slopeBoost = 1.2f;
-               if (slopeness < 0) slopeBoost = 0.8f;
+               float slopeness = (northH + northWestH + westH);
+               float tolerance = edge ? 2.0f : 0f;
 
-               slopeBoost -= 0.15f; //Slope boost value 
+
+               if (slopeness > tolerance) slopeBoost = 1.2f;
+               if (slopeness < tolerance) slopeBoost = 0.8f;
+               if (Math.Abs(slopeness) <= float.Epsilon) slopeBoost = 1.0f;//Same height
+               //slopeBoost -= 0.15f; //Slope boost value                                              
 
                int blockId = chunksColumn[localChunkY].MaybeBlocks[MapUtil.Index3d(localX, (localY % chunkSize), localZ, chunkSize, chunkSize)];
 
@@ -176,5 +214,29 @@ namespace Automap
 
                this.PngWriter.End( );
                }
+
+               /*
+               private void RenderDebugBitmap( ushort[ , ] heightmap, Vec2i chunkOrigin )
+               {
+               Bitmap mapBitmap = null;
+               Graphics gContext = null;
+               mapBitmap = new Bitmap(33, 33, PixelFormat.Format24bppRgb);             
+               gContext = Graphics.FromImage(mapBitmap);
+
+               for (int x = 0; x <= chunkSize; x++) {
+               for (int y = 0; y <= chunkSize; y++) {
+               ushort heightCol = heightmap[x, y];
+               Color color= Color.FromArgb((byte)heightCol,( byte )heightCol,( byte )heightCol);
+               mapBitmap.SetPixel(x, y, color);
+               }
+               }
+               
+               gContext.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);
+
+               var fileName = Path.Combine( ClientAPI.GetOrCreateDataPath("Heightmaps"),$"offhm_{chunkOrigin.X}-{chunkOrigin.Y}.png");                         
+               mapBitmap.Save(fileName, ImageFormat.Png);
+
+               }
+               */
        }
 }
\ No newline at end of file