public byte[] MatImgToPng(MaterialImage img) { using (Bitmap bmp = new Bitmap(img.Width, img.Height)) { BitmapData bdat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int stride = bdat.Stride; // Surely there's a better way to do this! unsafe { byte *ptr = (byte *)bdat.Scan0; for (int x = 0; x < img.Width; x++) { for (int y = 0; y < img.Height; y++) { FastColor tcol = img.GetAt(x, y); ptr[(x * 4) + y * stride + 0] = tcol.B; ptr[(x * 4) + y * stride + 1] = tcol.G; ptr[(x * 4) + y * stride + 2] = tcol.R; ptr[(x * 4) + y * stride + 3] = tcol.A; } } } using (DataStream ds = new DataStream()) { bmp.Save(ds, ImageFormat.Png); return(ds.ToArray()); } } }
FastColor Multiply(FastColor one, FastColor two) { return(new FastColor() { R = (byte)((one.R * two.R) / 255), G = (byte)((one.G * two.G) / 255), B = (byte)((one.B * two.B) / 255), A = (byte)((one.A * two.A) / 255) }); }
FastColor Blend(FastColor one, FastColor two) { int a2 = 255 - one.A; return(new FastColor() { R = (byte)(((one.R * one.A) / 255) + ((two.R * a2) / 255)), G = (byte)(((one.G * one.A) / 255) + ((two.G * a2) / 255)), B = (byte)(((one.B * one.A) / 255) + ((two.B * a2) / 255)), A = (byte)Math.Min(one.A + two.A, 255) }); }
public byte[] GetChunkRenderLD(WorldSystem.Region tregion, int tx, int ty, int tz) { int wid = Constants.CHUNK_WIDTH; int divvy = GetDividerForZ(tz) * Constants.CHUNK_WIDTH; MaterialImage bmp = GenerateSeedImageBmp(tregion, tx * divvy, ty * divvy, (tx + 1) * divvy, (ty + 1) * divvy, wid); KeyValuePair <byte[], byte[]> bitters = tregion.ChunkManager.GetTopsHigher(tx, ty, tz); byte[] bits = bitters.Key; byte[] bits_trans = bitters.Value; if (bits == null || bits_trans == null) { return(MatImgToPng(bmp)); } for (int x = 0; x < Constants.CHUNK_WIDTH; x++) { for (int y = 0; y < Constants.CHUNK_WIDTH; y++) { int ind = tregion.TopsHigherBlockIndex(x, y); ushort mat = Utilities.BytesToUshort(Utilities.BytesPartial(bits, ind * 2, 2)); FastColor fc; if (mat == 0) { fc = new FastColor() { A = 0 }; } else { MaterialImage imag = MaterialImages[mat]; fc = imag.GetAt(0, 0); } for (int i = 3; i >= 0; i--) { mat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, ind * 2 * 4, 2)); if (mat != 0) { MaterialImage simag = MaterialImages[mat]; FastColor fc2 = simag.Colors[0]; fc = Blend(fc2, fc); } } fc = Blend(fc, bmp.GetAt(x, y)); bmp.SetAt(x, y, fc); } } // TODO: Add entity icons? (Trees in particular!) return(MatImgToPng(bmp)); }
public byte[] GetChunkRenderHD(WorldSystem.Region tregion, int tx, int ty, bool fullzoom) { const int wid = TexWidth * Constants.CHUNK_WIDTH; MaterialImage bmp = new MaterialImage() { Colors = new FastColor[wid * wid], Width = wid, Height = wid }; KeyValuePair <byte[], byte[]> bitters = tregion.ChunkManager.GetTops(tx, ty); byte[] xp = null; byte[] xm = null; byte[] yp = null; byte[] ym = null; if (!fullzoom) { xp = tregion.ChunkManager.GetTops(tx + 1, ty).Key; xm = tregion.ChunkManager.GetTops(tx - 1, ty).Key; yp = tregion.ChunkManager.GetTops(tx, ty + 1).Key; ym = tregion.ChunkManager.GetTops(tx, ty - 1).Key; } byte[] bits = bitters.Key; byte[] bits_trans = bitters.Value; if (bits == null || bits_trans == null) { return(null); } for (int x = 0; x < Constants.CHUNK_WIDTH; x++) { for (int y = 0; y < Constants.CHUNK_WIDTH; y++) { int ind = tregion.TopsHigherBlockIndex(x, y); ushort mat = Utilities.BytesToUshort(Utilities.BytesPartial(bits, ind * 2, 2)); MaterialImage imag = MaterialImages[mat]; if (fullzoom) { for (int sx = 0; sx < TexWidth; sx++) { for (int sy = 0; sy < TexWidth; sy++) { FastColor fc = imag.GetAt(sx, sy); fc.A = 255; for (int i = 3; i >= 0; i--) { ushort smat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, (ind * 4 + i) * 2, 2)); if (smat != 0) { MaterialImage simag = MaterialImages[smat]; FastColor fc2 = simag.GetAt(sx, sy); fc = Blend(fc2, fc); } } bmp.SetAt(x * TexWidth + sx, y * TexWidth + sy, fc); } } } else { int height = Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + ind * 4, 4)); FastColor fc = imag.GetAt(0, 0); fc.A = 255; for (int i = 3; i >= 0; i--) { ushort smat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, ind * 2 * 4, 2)); if (smat != 0) { MaterialImage simag = MaterialImages[smat]; FastColor fc2 = simag.Colors[0]; fc = Blend(fc2, fc); } } FastColor lightened = fc; lightened.R = (byte)Math.Min(lightened.R + 20, 255); lightened.G = (byte)Math.Min(lightened.G + 20, 255); lightened.B = (byte)Math.Min(lightened.B + 20, 255); FastColor darkened = fc; darkened.R = (byte)Math.Max(darkened.R - 20, 0); darkened.G = (byte)Math.Max(darkened.G - 20, 0); darkened.B = (byte)Math.Max(darkened.B - 20, 0); FastColor doublelightened = fc; doublelightened.R = (byte)Math.Min(doublelightened.R + 40, 255); doublelightened.G = (byte)Math.Min(doublelightened.G + 40, 255); doublelightened.B = (byte)Math.Min(doublelightened.B + 40, 255); FastColor doubledarkened = fc; doubledarkened.R = (byte)Math.Max(doubledarkened.R - 40, 0); doubledarkened.G = (byte)Math.Max(doubledarkened.G - 40, 0); doubledarkened.B = (byte)Math.Max(doubledarkened.B - 40, 0); int relxp = x + 1 < Constants.CHUNK_WIDTH ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x + 1, y) * 4, 4)) : (xp == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(xp, CWCW2 + tregion.TopsHigherBlockIndex(0, y) * 4, 4))); int relyp = y + 1 < Constants.CHUNK_WIDTH ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x, y + 1) * 4, 4)) : (yp == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(yp, CWCW2 + tregion.TopsHigherBlockIndex(x, 0) * 4, 4))); int relxm = x - 1 >= 0 ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x - 1, y) * 4, 4)) : (xm == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(xm, CWCW2 + tregion.TopsHigherBlockIndex(Constants.CHUNK_WIDTH - 1, y) * 4, 4))); int relym = y - 1 >= 0 ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x, y - 1) * 4, 4)) : (ym == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(ym, CWCW2 + tregion.TopsHigherBlockIndex(x, Constants.CHUNK_WIDTH - 1) * 4, 4))); bmp.SetAt(x * 4 + 0, y * 4 + 0, ((relym < height) ? ((relxm < height) ? doublelightened : (relxm > height ? fc : lightened)) : ((relym > height) ? ((relxm < height) ? fc : ((relxm > height) ? doubledarkened : darkened)) : ((relxm < height) ? lightened : ((relxm > height) ? darkened : fc))))); bmp.SetAt(x * 4 + 1, y * 4 + 0, (relym < height) ? lightened : ((relym > height) ? darkened : fc)); bmp.SetAt(x * 4 + 2, y * 4 + 0, (relym < height) ? lightened : ((relym > height) ? darkened : fc)); bmp.SetAt(x * 4 + 3, y * 4 + 0, (relym < height) ? ((relxp < height) ? doublelightened : ((relxp > height) ? fc : lightened)) : ((relym > height) ? ((relxp < height) ? fc : ((relxp > height) ? doubledarkened : darkened)) : ((relxp < height) ? lightened : ((relxp > height) ? darkened : fc)))); bmp.SetAt(x * 4 + 0, y * 4 + 1, (relxm < height) ? lightened : ((relxm > height) ? darkened : fc)); bmp.SetAt(x * 4 + 1, y * 4 + 1, fc); bmp.SetAt(x * 4 + 2, y * 4 + 1, fc); bmp.SetAt(x * 4 + 3, y * 4 + 1, (relxp < height) ? lightened : ((relxp > height) ? darkened : fc)); bmp.SetAt(x * 4 + 0, y * 4 + 2, (relxm < height) ? lightened : ((relxm > height) ? darkened : fc)); bmp.SetAt(x * 4 + 1, y * 4 + 2, fc); bmp.SetAt(x * 4 + 2, y * 4 + 2, fc); bmp.SetAt(x * 4 + 3, y * 4 + 2, (relxp < height) ? lightened : ((relxp > height) ? darkened : fc)); bmp.SetAt(x * 4 + 0, y * 4 + 3, (relxm < height) ? ((relyp < height) ? doublelightened : ((relyp > height) ? fc : lightened)) : ((relxm > height) ? ((relyp < height) ? lightened : ((relyp > height) ? doubledarkened : darkened)) : ((relyp < height) ? lightened : ((relyp > height) ? darkened : fc)))); bmp.SetAt(x * 4 + 1, y * 4 + 3, (relyp < height) ? lightened : ((relyp > height) ? darkened : fc)); bmp.SetAt(x * 4 + 2, y * 4 + 3, (relyp < height) ? lightened : ((relyp > height) ? darkened : fc)); bmp.SetAt(x * 4 + 3, y * 4 + 3, (relxp < height) ? ((relyp < height) ? doublelightened : ((relyp > height) ? fc : lightened)) : ((relxp > height) ? ((relyp < height) ? fc : ((relyp > height) ? doubledarkened : darkened)) : ((relyp < height) ? lightened : ((relyp > height) ? darkened : fc)))); } } } // TODO: Add entity icons? (Trees in particular!) return(MatImgToPng(bmp)); }
public void SetAt(int x, int y, FastColor c) { Colors[x + y * Width] = c; }