CNCMaps.Engine.Rendering.TmpRenderer.Draw C# (CSharp) Method

Draw() public static method

public static Draw ( CNCMaps.Engine.Map.MapTile tile, CNCMaps.FileFormats.TmpFile tmp, CNCMaps.Engine.Rendering.DrawingSurface ds ) : void
tile CNCMaps.Engine.Map.MapTile
tmp CNCMaps.FileFormats.TmpFile
ds CNCMaps.Engine.Rendering.DrawingSurface
return void
        public static unsafe void Draw(MapTile tile, TmpFile tmp, DrawingSurface ds)
        {
            tmp.Initialize();

            if (tile.SubTile >= tmp.Images.Count) return;
            TmpFile.TmpImage img = tmp.Images[tile.SubTile];
            var zBuffer = ds.GetZBuffer();
            var heightBuffer = ds.GetHeightBuffer();
            Palette p = tile.Palette;

            // calculate tile index -> pixel index
            Point offset = new Point(tile.Dx * tmp.BlockWidth / 2, (tile.Dy - tile.Z) * tmp.BlockHeight / 2);

            // make touched tiles (used for determining image cutoff)
            Point center = offset + new Size(tmp.BlockWidth / 2, tmp.BlockHeight / 2);
            var centerGridTile = tile.Layer.GetTileScreen(center, true, true);
            if (centerGridTile != null) {
                tile.Layer.GridTouched[centerGridTile.Dx, centerGridTile.Dy / 2] |= TileLayer.TouchType.ByNormalData;
                tile.Layer.GridTouchedBy[centerGridTile.Dx, centerGridTile.Dy / 2] = tile;
            }

            Logger.Trace("Drawing TMP file {0} (subtile {1}) at ({2},{3})", tmp.FileName, tile.SubTile, offset.X, offset.Y);

            int stride = ds.BitmapData.Stride;

            int halfCx = tmp.BlockWidth / 2,
                halfCy = tmp.BlockHeight / 2;

            // writing bounds
            var w_low = (byte*)ds.BitmapData.Scan0;
            byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height;
            byte* w = (byte*)ds.BitmapData.Scan0 + stride * offset.Y + (offset.X + halfCx - 2) * 3;

            int rIdx = 0, x, y = 0;
            int zIdx = offset.Y * ds.Width + offset.X + halfCx - 2;
            int cx = 0; // Amount of pixel to copy

            for (; y < halfCy; y++) {
                cx += 4;
                for (ushort c = 0; c < cx; c++) {
                    byte paletteValue = img.TileData[rIdx];

                    short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0));
                    if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
                        *(w + 0) = p.Colors[paletteValue].B;
                        *(w + 1) = p.Colors[paletteValue].G;
                        *(w + 2) = p.Colors[paletteValue].R;
                        zBuffer[zIdx] = zBufVal;
                        heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2);
                    }
                    w += 3;
                    zIdx++;
                    rIdx++;
                }
                w += stride - 3 * (cx + 2);
                zIdx += ds.Width - (cx + 2);
            }

            w += 12;
            zIdx += 4;
            for (; y < tmp.BlockHeight; y++) {
                cx -= 4;
                for (ushort c = 0; c < cx; c++) {
                    byte paletteValue = img.TileData[rIdx];

                    short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0));
                    if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
                        *(w + 0) = p.Colors[paletteValue].B;
                        *(w + 1) = p.Colors[paletteValue].G;
                        *(w + 2) = p.Colors[paletteValue].R;
                        zBuffer[zIdx] = zBufVal;
                        heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2);
                    }
                    w += 3;
                    zIdx++;
                    rIdx++;
                }
                w += stride - 3 * (cx - 2);
                zIdx += ds.Width - (cx - 2);
            }

            if (!img.HasExtraData) return; // we're done now

            offset.X += img.ExtraX - img.X;
            offset.Y += img.ExtraY - img.Y;
            w = w_low + stride * offset.Y + 3 * offset.X;
            zIdx = offset.X + offset.Y * ds.Width;
            rIdx = 0;

            // identify extra-data affected tiles for cutoff
            var extraScreenBounds = Rectangle.FromLTRB(
                Math.Max(0, offset.X), Math.Max(0, offset.Y),
                Math.Min(offset.X + img.ExtraWidth, ds.Width), Math.Min(offset.Y + img.ExtraHeight, ds.Height));

            for (int by = extraScreenBounds.Top; by < extraScreenBounds.Bottom; by += tmp.BlockHeight / 2) {
                for (int bx = extraScreenBounds.Left; bx < extraScreenBounds.Right; bx += tmp.BlockWidth / 2) {
                    var gridTileNoZ = tile.Layer.GetTileScreen(new Point(bx, by), true, true);
                    if (gridTileNoZ != null) {
                        Logger.Trace("Tile at ({0},{1}) has extradata affecting ({2},{3})", tile.Dx, tile.Dy, gridTileNoZ.Dx,
                            gridTileNoZ.Dy);
                        tile.Layer.GridTouched[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] |= TileLayer.TouchType.ByExtraData;
                        tile.Layer.GridTouchedBy[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] = tile;
                    }
                }
            }

            // Extra graphics are just a square
            for (y = 0; y < img.ExtraHeight; y++) {
                for (x = 0; x < img.ExtraWidth; x++) {
                    // Checking per line is required because v needs to be checked every time
                    byte paletteValue = img.ExtraData[rIdx];
                    short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 + (img.ExtraZData != null ? img.ExtraZData[rIdx] : 0));

                    if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
                        *w++ = p.Colors[paletteValue].B;
                        *w++ = p.Colors[paletteValue].G;
                        *w++ = p.Colors[paletteValue].R;
                        zBuffer[zIdx] = zBufVal;
                        heightBuffer[zIdx] = (short)(img.ExtraHeight - y + tile.Z * Drawable.TileHeight / 2);
                    }
                    else
                        w += 3;
                    zIdx++;
                    rIdx++;
                }
                w += stride - img.ExtraWidth * 3;
                zIdx += ds.Width - img.ExtraWidth;
            }
        }