2 using System.Collections.Generic;
7 using Vintagestory.API.Client;
8 using Vintagestory.API.Common;
9 using Vintagestory.API.MathTools;
10 using Vintagestory.Common;
14 public class StandardRenderer : AChunkRenderer
16 public const string Name = @"Standard";
19 /// Renders shards similar to the Default VS version, plus P.O.I. markings.
21 /// <param name="clientAPI">Client API.</param>
22 /// <param name="logger">Logger.</param>
23 public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger, bool seasonalColor) : base(clientAPI, logger, seasonalColor)
28 public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta targetColMeta, ref ColumnsMetadata allCols, out uint pixelCount)
31 BlockPos tmpPos = new BlockPos( );
32 Vec2i localpos = new Vec2i( );
34 var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
36 //pre-create PNG line slices...
37 ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(this.PngWriter.ImgInfo)).ToArray( );
39 int topChunkY = targetColMeta.YMax / chunkSize;
41 for (int chunkY = 0; chunkY <= topChunkY; chunkY++) {
42 chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
43 WorldChunk ownChunk = chunksColumn[chunkY] as WorldChunk;
44 if (ownChunk != null) {
45 if (ownChunk.IsPacked( )) ownChunk.Unpack( );//Gah - probably done already by chunk processor
48 Logger.Warning("CHUNK A.W.O.L. : X{0} Y{1} Z{2} - Missing slice FOR COLUMN", chunkPos.X, chunkY, chunkPos.Y);
53 // Prefetch map chunks, in pattern
54 var mapCornerChunks = new List<ColumnMeta>(3);
56 var south_west = new Vec2i(chunkPos.X - 1, chunkPos.Y - 1);
57 var west = new Vec2i(chunkPos.X - 1, chunkPos.Y);
58 var south = new Vec2i(chunkPos.X, chunkPos.Y - 1);
60 bool nullSouthWest = false, nullSouth = false, nullWest = false;
63 For missing corners / cardinal heightmaps...
64 make fake heightmap dummy
67 if (allCols.Contains(south_west)) {
68 mapCornerChunks.Add(allCols[south_west]);
72 mapCornerChunks.Add(targetColMeta);//Temporary!
75 if (allCols.Contains(south)) {
76 mapCornerChunks.Add(allCols[south]);
80 mapCornerChunks.Add(targetColMeta);//Temporary!
83 if (allCols.Contains(west)) {
84 mapCornerChunks.Add(allCols[west]);
88 mapCornerChunks.Add(targetColMeta);//Temporary!
92 for (int pixelIndex = 0; pixelIndex < (chunkSize * chunkSize); pixelIndex++) {
93 MapUtil.PosInt2d(pixelIndex, chunkSize, localpos);
94 int localX = localpos.X;
95 int localZ = localpos.Y;
96 ushort localY = targetColMeta.HeightMap[localX, localZ];
98 int localChunkY = localY / chunkSize;
99 if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
100 if (chunksColumn[localChunkY] == null) continue;//BIG Gaps!
101 //if (mapCornerChunks.Any(chks => chks == null)) {
102 //Logger.Warning("mapCornerChunks A.W.O.L. near : X{0} Y{1} Z{2} - ", localX, localY, localZ);
106 float slopeBoost = 1f;
107 int leftTop, rightTop, leftBot;
109 ColumnMeta leftTopMapChunk = targetColMeta;
110 ColumnMeta rightTopMapChunk = targetColMeta;
111 ColumnMeta leftBotMapChunk = targetColMeta;
113 int topX = localX - 1;
115 int leftZ = localZ - 1;
118 if (topX < 0 && leftZ < 0) {
119 leftTopMapChunk = mapCornerChunks[0];
120 rightTopMapChunk = mapCornerChunks[1];
121 leftBotMapChunk = mapCornerChunks[2];
125 leftTopMapChunk = mapCornerChunks[1];
126 rightTopMapChunk = mapCornerChunks[1];
129 leftTopMapChunk = mapCornerChunks[2];
130 leftBotMapChunk = mapCornerChunks[2];
134 topX = GameMath.Mod(topX, chunkSize);
135 leftZ = GameMath.Mod(leftZ, chunkSize);
137 leftTop = nullSouthWest ? 0 : Math.Sign(localY - leftTopMapChunk.HeightMap[topX, leftZ]);
138 rightTop = nullSouth ? 0 : Math.Sign(localY - rightTopMapChunk.HeightMap[topX, rightZ]);
139 leftBot = nullWest ? 0 : Math.Sign(localY - leftBotMapChunk.HeightMap[botX, leftZ]);
141 float slopeness = (leftTop + rightTop + leftBot);
143 if (slopeness > 0) slopeBoost = 1.2f;
144 if (slopeness < 0) slopeBoost = 0.8f;
145 if (Math.Abs(slopeness) <= float.Epsilon) slopeBoost = 1.0f;//Same height
146 //slopeBoost -= 0.15f; //Slope boost value
148 //FIXME: disable slopes on edges...for now
149 if (localX == 0 || localX == 31) slopeBoost= 1.0f;
150 if (localZ == 0 || localZ == 31) slopeBoost= 1.0f;
152 int blockId = chunksColumn[localChunkY].MaybeBlocks[MapUtil.Index3d(localX, (localY % chunkSize), localZ, chunkSize, chunkSize)];
154 Block block = ClientAPI.World.Blocks[blockId];
156 tmpPos.Set(chunkSize * chunkPos.X + localpos.X, localY, chunkSize * chunkPos.Y + localpos.Y);
158 int red = 0, green = 0, blue = 0;
160 ExtractBlockColor(tmpPos, block, slopeBoost, out red, out green, out blue);
162 //============ POI Population =================
163 if (BlockID_Designators.ContainsKey(blockId)) {
164 var desig = BlockID_Designators[blockId];
168 red = desig.OverwriteColor.R;
169 green = desig.OverwriteColor.G;
170 blue = desig.OverwriteColor.B;
174 ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
178 for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++) {
179 this.PngWriter.WriteRow(lines[row], row);
182 this.PngWriter.End( );