OSDN Git Service

Weighted Rankins for Colum Counters,
[automap/automap.git] / Automap / Renderers / StandardRenderer.cs
index 3ee4c7f..09a551f 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Linq;
 
 using Hjg.Pngcs;
@@ -6,156 +7,174 @@ using Hjg.Pngcs;
 using Vintagestory.API.Client;
 using Vintagestory.API.Common;
 using Vintagestory.API.MathTools;
+using Vintagestory.Common;
 
 namespace Automap
 {
-       public class StandardRenderer : IChunkRenderer
+       public class StandardRenderer : AChunkRenderer
        {
-               private readonly int chunkSize;
-
 
                /// <summary>
                /// Renders shards similar to the Default VS version, plus P.O.I. markings.
                /// </summary>
                /// <param name="clientAPI">Client API.</param>
                /// <param name="logger">Logger.</param>
-               public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger) : base(clientAPI, logger)
+               public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger, bool seasonalColor) : base(clientAPI, logger, seasonalColor)
                {
-                       chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
+
                }
 
-               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount)
+               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta targetColMeta, ref ColumnsMetadata allCols, out uint pixelCount)
                {
-                       pixelCount = 0;
-                       BlockPos tmpPos = new BlockPos();
-                       Vec2i localpos = new Vec2i();
+               pixelCount = 0;
+               BlockPos tmpPos = new BlockPos( );
+               Vec2i localpos = new Vec2i( );
 
-                       var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
+               var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
 
-                       int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate!
+               //pre-create PNG line slices...
+               ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(this.PngWriter.ImgInfo)).ToArray( );
 
-                       for (int chunkY = 0; chunkY <= topChunkY; chunkY++)
-                       {
-                               chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
-                               //What to do if chunk is a void? invalid?
-                       }
+               int topChunkY = targetColMeta.YMax / chunkSize;
 
-                       // Prefetch map chunks, in pattern
-                       IMapChunk[] mapChunks = new IMapChunk[]
-                       {
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y - 1),
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y),
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X, chunkPos.Y - 1)
-                       };
+               for (int chunkY = 0; chunkY <= topChunkY; chunkY++) {
+               chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
+               WorldChunk ownChunk = chunksColumn[chunkY] as WorldChunk;
+               if (ownChunk != null) {
+               if (ownChunk.IsPacked( )) ownChunk.Unpack( );//Gah - probably done already by chunk processor
+               }
+               else {
+               Logger.Warning("CHUNK A.W.O.L. : X{0} Y{1} Z{2} - Missing slice FOR COLUMN", chunkPos.X, chunkY, chunkPos.Y);
+               //return;
+               }
+               }
 
-                       //pre-create PNG line slices...
-                       ImageLine[] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray();
+               // 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);
+
+               bool nullSouthWest = false, nullSouth = false, nullWest = false;
+
+               /* 
+               For missing corners / cardinal heightmaps...
+               make fake heightmap dummy
+               */
+
+               if (allCols.Contains(south_west)) {
+               mapCornerChunks.Add(allCols[south_west]);               
+               }
+               else {
+               nullSouthWest = true;
+               mapCornerChunks.Add(targetColMeta);//Temporary!
+               }
+
+               if (allCols.Contains(south)) {
+               mapCornerChunks.Add(allCols[south]);
+               }
+               else {
+               nullSouth = true;
+               mapCornerChunks.Add(targetColMeta);//Temporary!
+               }
+
+               if (allCols.Contains(west)) {
+               mapCornerChunks.Add(allCols[west]);
+               }
+               else {
+               nullWest = true;
+               mapCornerChunks.Add(targetColMeta);//Temporary!
+               }
 
-                       for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++)
-                       {
-                               int mapY = mc.RainHeightMap[posIndex];
-                               int localChunkY = mapY / chunkSize;
-                               if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
-
-                               MapUtil.PosInt2d(posIndex, chunkSize, localpos);
-                               int localX = localpos.X;
-                               int localZ = localpos.Y;
-
-                               float b = 1;
-                               int leftTop, rightTop, leftBot;
-
-                               IMapChunk leftTopMapChunk = mc;
-                               IMapChunk rightTopMapChunk = mc;
-                               IMapChunk leftBotMapChunk = mc;
-
-                               int topX = localX - 1;
-                               int botX = localX;
-                               int leftZ = localZ - 1;
-                               int rightZ = localZ;
-
-                               if (topX < 0 && leftZ < 0)
-                               {
-                                       leftTopMapChunk = mapChunks[0];
-                                       rightTopMapChunk = mapChunks[1];
-                                       leftBotMapChunk = mapChunks[2];
-                               }
-                               else
-                               {
-                                       if (topX < 0)
-                                       {
-                                               leftTopMapChunk = mapChunks[1];
-                                               rightTopMapChunk = mapChunks[1];
-                                       }
-                                       if (leftZ < 0)
-                                       {
-                                               leftTopMapChunk = mapChunks[2];
-                                               leftBotMapChunk = mapChunks[2];
-                                       }
-                               }
-
-                               topX = GameMath.Mod(topX, chunkSize);
-                               leftZ = GameMath.Mod(leftZ, chunkSize);
-
-                               leftTop = leftTopMapChunk == null ? 0 : Math.Sign(mapY - leftTopMapChunk.RainHeightMap[leftZ * chunkSize + topX]);
-                               rightTop = rightTopMapChunk == null ? 0 : Math.Sign(mapY - rightTopMapChunk.RainHeightMap[rightZ * chunkSize + topX]);
-                               leftBot = leftBotMapChunk == null ? 0 : Math.Sign(mapY - leftBotMapChunk.RainHeightMap[leftZ * chunkSize + botX]);
-
-                               float slopeness = (leftTop + rightTop + leftBot);
-
-                               if (slopeness > 0) b = 1.2f;
-                               if (slopeness < 0) b = 0.8f;
-
-                               b -= 0.15f; //Slope boost value 
-
-                               if (chunksColumn[localChunkY] == null)
-                               {
-
-                                       continue;
-                               }
-
-                               chunksColumn[localChunkY].Unpack();
-                               int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localpos.X, mapY % chunkSize, localpos.Y, chunkSize, chunkSize)];
-
-                               Block block = ClientAPI.World.Blocks[blockId];
-
-                               tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y);
-
-                               int avgCol = block.GetColor(ClientAPI, tmpPos);
-                               int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP);
-                               int col = ColorUtil.ColorOverlay(avgCol, rndCol, 0.125f);
-                               var packedFormat = ColorUtil.ColorMultiply3Clamped(col, b);
-
-                               int red = ColorUtil.ColorB(packedFormat);
-                               int green = ColorUtil.ColorG(packedFormat);
-                               int blue = ColorUtil.ColorR(packedFormat);
-
-
-                               //============ POI Population =================
-                               if (BlockID_Designators.ContainsKey(blockId))
-                               {
-                                       var desig = BlockID_Designators[blockId];
-
-                                       if (desig.Enabled)
-                                       {
-                                               red = desig.OverwriteColor.R;
-                                               green = desig.OverwriteColor.G;
-                                               blue = desig.OverwriteColor.B;
-                                       }
-                               }
-
-                               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
-
-                               //chunkImage.SetPixel(localX, localZ, pixelColor);
-                               pixelCount++;
-                       }
 
-                       for (int row = 0; row < pngWriter.ImgInfo.Rows; row++)
+               for (int pixelIndex = 0; pixelIndex < (chunkSize * chunkSize); pixelIndex++) {
+               MapUtil.PosInt2d(pixelIndex, chunkSize, localpos);
+               int localX = localpos.X;
+               int localZ = localpos.Y;
+               ushort localY = targetColMeta.HeightMap[localX, localZ];
+
+               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];
+               }
+               }
+
+               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 slopeness = (leftTop + rightTop + leftBot);
+
+               if (slopeness > 0) slopeBoost = 1.2f;
+               if (slopeness < 0) slopeBoost = 0.8f;
+
+               slopeBoost -= 0.15f; //Slope boost value 
+
+               int blockId = chunksColumn[localChunkY].MaybeBlocks[MapUtil.Index3d(localX, (localY % chunkSize), localZ, chunkSize, chunkSize)];
+
+               Block block = ClientAPI.World.Blocks[blockId];
+
+               tmpPos.Set(chunkSize * chunkPos.X + localpos.X, localY, chunkSize * chunkPos.Y + localpos.Y);
+
+               int red = 0, green = 0, blue = 0;
+
+               ExtractBlockColor(tmpPos, block, slopeBoost, out red, out green, out blue);
+
+               //============ POI Population =================
+               if (BlockID_Designators.ContainsKey(blockId)) {
+               var desig = BlockID_Designators[blockId];
+
+                       if (desig.Enabled) 
                        {
-                               pngWriter.WriteRow(lines[row], row);
+                       red = desig.OverwriteColor.R;
+                       green = desig.OverwriteColor.G;
+                       blue = desig.OverwriteColor.B;
                        }
+               }
 
-                       pngWriter.End();
+               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+               pixelCount++;
+               }
+
+               for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++) {
+               this.PngWriter.WriteRow(lines[row], row);
                }
-       }
-}
 
+               this.PngWriter.End( );
+               }
+       }
+}
\ No newline at end of file