private int NeighborSkyLight(IBoundedLitBlockCollection[,] chunkMap, int x, int y, int z) { if (y < 0 || y >= _ydim) { return(0); } int xdim = _xdim; int zdim = _zdim; int xi = x + xdim; int zi = z + zdim; IBoundedLitBlockCollection src = chunkMap[xi / xdim, zi / zdim]; if (src == null) { return(0); } x = xi % xdim; z = zi % zdim; BlockInfo info = src.GetInfo(x, y, z); if (!info.TransmitsLight) { return(BlockInfo.MIN_LUMINANCE); } int light = src.GetSkyLight(x, y, z); return((info.Opacity > 0) ? light : light - 1); }
public void UpdateHeightMap(int lx, int ly, int lz) { BlockInfo info = _blockset.GetInfo(lx, ly, lz); int h = Math.Min(ly + 1, _ydim - 1); int height = _blockset.GetHeight(lx, lz); if (h < height) { return; } if (h == height && !info.ObscuresLight) { for (int i = ly - 1; i >= 0; i--) { BlockInfo info2 = _blockset.GetInfo(lx, i, lz); if (info2.ObscuresLight) { _blockset.SetHeight(lx, lz, Math.Min(i + 1, _ydim - 1)); break; } } UpdateBlockSkyLight(lx, h, lz); } else if (h > height && info.ObscuresLight) { _blockset.SetHeight(lx, lz, h); UpdateBlockSkyLight(lx, h, lz); } }
private void TestBlockLight(IBoundedLitBlockCollection chunk, int x1, int y1, int z1, int x2, int y2, int z2) { int light1 = _blockset.GetBlockLight(x1, y1, z1); int light2 = chunk.GetBlockLight(x2, y2, z2); int lum1 = _blockset.GetInfo(x1, y1, z1).Luminance; int lum2 = chunk.GetInfo(x2, y2, z2).Luminance; int v1 = Math.Max(light1, lum1); int v2 = Math.Max(light2, lum2); if (Math.Abs(v1 - v2) > 1) { QueueRelight(new BlockKey(x1, y1, z1)); } }
private void SpreadSkyLight(IBoundedLitBlockCollection[,] chunkMap, int[,] heightMap, int lx, int ly, int lz) { BlockInfo primary = _blockset.GetInfo(lx, ly, lz); int primaryLight = _blockset.GetSkyLight(lx, ly, lz); int priLum = Math.Max(BlockInfo.MAX_LUMINANCE - primary.Opacity, 0); if (primaryLight < priLum) { _blockset.SetSkyLight(lx, ly, lz, priLum); } if (primaryLight > BlockInfo.MAX_LUMINANCE - 1 || !primary.TransmitsLight) { return; } Queue <LightRecord> spread = new Queue <LightRecord>(); int xdim = _xdim; int ydim = _ydim; int zdim = _zdim; int lxi = lx + xdim; int lzi = lz + zdim; int strength = (primary.Opacity > 0) ? priLum : priLum - 1; if (ly > 0) { if (heightMap[lxi, lzi] > ly - 1) { spread.Enqueue(new LightRecord(lx, ly - 1, lz, strength)); } else { spread.Enqueue(new LightRecord(lx, ly - 1, lz, priLum)); } } if (ly < ydim - 1) { if (heightMap[lxi, lzi] > ly + 1) { spread.Enqueue(new LightRecord(lx, ly + 1, lz, strength)); } } if (heightMap[lxi - 1, lzi] > ly) { spread.Enqueue(new LightRecord(lx - 1, ly, lz, strength)); } if (heightMap[lxi + 1, lzi] > ly) { spread.Enqueue(new LightRecord(lx + 1, ly, lz, strength)); } if (heightMap[lxi, lzi - 1] > ly) { spread.Enqueue(new LightRecord(lx, ly, lz - 1, strength)); } if (heightMap[lxi, lzi + 1] > ly) { spread.Enqueue(new LightRecord(lx, ly, lz + 1, strength)); } while (spread.Count > 0) { LightRecord rec = spread.Dequeue(); int xi = rec.x + xdim; int zi = rec.z + zdim; IBoundedLitBlockCollection cc = chunkMap[xi / xdim, zi / zdim]; if (cc == null) { continue; } int x = xi % xdim; int y = rec.y; int z = zi % zdim; BlockInfo info = cc.GetInfo(x, y, z); int light = cc.GetSkyLight(x, y, z); int dimStr = Math.Max(rec.str - info.Opacity, 0); if (dimStr > light) { cc.SetSkyLight(x, y, z, dimStr); if (info.TransmitsLight) { strength = (info.Opacity > 0) ? dimStr : dimStr - 1; if (rec.y > 0) { if (heightMap[xi, zi] > rec.y - 1) { spread.Enqueue(new LightRecord(rec.x, rec.y - 1, rec.z, strength)); } else { spread.Enqueue(new LightRecord(rec.x, rec.y - 1, rec.z, dimStr)); } } if (rec.y < ydim - 1) { if (heightMap[xi, zi] > rec.y + 1) { spread.Enqueue(new LightRecord(rec.x, rec.y + 1, rec.z, strength)); } } if (heightMap[xi - 1, zi] > rec.y) { spread.Enqueue(new LightRecord(rec.x - 1, rec.y, rec.z, strength)); } if (heightMap[xi + 1, zi] > rec.y) { spread.Enqueue(new LightRecord(rec.x + 1, rec.y, rec.z, strength)); } if (heightMap[xi, zi - 1] > rec.y) { spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z - 1, strength)); } if (heightMap[xi, zi + 1] > rec.y) { spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z + 1, strength)); } } } } }
private void SpreadBlockLight(IBoundedLitBlockCollection[,] chunkMap, int lx, int ly, int lz) { BlockInfo primary = _blockset.GetInfo(lx, ly, lz); int primaryLight = _blockset.GetBlockLight(lx, ly, lz); int priLum = Math.Max(primary.Luminance - primary.Opacity, 0); if (primaryLight < priLum) { _blockset.SetBlockLight(lx, ly, lz, priLum); } if (primaryLight > primary.Luminance - 1 && !primary.TransmitsLight) { return; } int xdim = _xdim; int ydim = _ydim; int zdim = _zdim; Queue <LightRecord> spread = new Queue <LightRecord>(); if (ly > 0) { spread.Enqueue(new LightRecord(lx, ly - 1, lz, primary.Luminance - 1)); } if (ly < ydim - 1) { spread.Enqueue(new LightRecord(lx, ly + 1, lz, primary.Luminance - 1)); } spread.Enqueue(new LightRecord(lx - 1, ly, lz, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx + 1, ly, lz, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx, ly, lz - 1, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx, ly, lz + 1, primary.Luminance - 1)); while (spread.Count > 0) { LightRecord rec = spread.Dequeue(); int xi = rec.x + xdim; int zi = rec.z + zdim; IBoundedLitBlockCollection cc = chunkMap[xi / xdim, zi / zdim]; if (cc == null) { continue; } int x = xi % xdim; int y = rec.y; int z = zi % zdim; BlockInfo info = cc.GetInfo(x, y, z); int light = cc.GetBlockLight(x, y, z); int dimStr = Math.Max(rec.str - info.Opacity, 0); if (dimStr > light) { cc.SetBlockLight(x, y, z, dimStr); if (info.TransmitsLight) { int strength = (info.Opacity > 0) ? dimStr : dimStr - 1; if (rec.y > 0) { spread.Enqueue(new LightRecord(rec.x, rec.y - 1, rec.z, strength)); } if (rec.y < ydim - 1) { spread.Enqueue(new LightRecord(rec.x, rec.y + 1, rec.z, strength)); } spread.Enqueue(new LightRecord(rec.x - 1, rec.y, rec.z, strength)); spread.Enqueue(new LightRecord(rec.x + 1, rec.y, rec.z, strength)); spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z - 1, strength)); spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z + 1, strength)); } } } }
private void UpdateBlockSkyLight() { IBoundedLitBlockCollection[,] chunkMap = LocalBlockLightMap(); int xdim = _xdim; int ydim = _ydim; int zdim = _zdim; while (_update.Count > 0) { BlockKey k = _update.Dequeue(); int index = LightBitmapIndex(k); _lightbit[index] = false; int xi = k.x + xdim; int zi = k.z + zdim; IBoundedLitBlockCollection cc = chunkMap[xi / xdim, zi / zdim]; if (cc == null) { continue; } int x = xi % xdim; int y = k.y; int z = zi % zdim; int lightval = cc.GetSkyLight(x, y, z); BlockInfo info = cc.GetInfo(x, y, z); int light = BlockInfo.MIN_LUMINANCE; if (cc.GetHeight(x, z) <= y) { light = BlockInfo.MAX_LUMINANCE; } else { int lle = NeighborSkyLight(chunkMap, k.x, k.y, k.z - 1); int lln = NeighborSkyLight(chunkMap, k.x - 1, k.y, k.z); int lls = NeighborSkyLight(chunkMap, k.x, k.y, k.z + 1); int llw = NeighborSkyLight(chunkMap, k.x + 1, k.y, k.z); int lld = NeighborSkyLight(chunkMap, k.x, k.y - 1, k.z); int llu = NeighborSkyLight(chunkMap, k.x, k.y + 1, k.z); light = Math.Max(light, lle); light = Math.Max(light, lln); light = Math.Max(light, lls); light = Math.Max(light, llw); light = Math.Max(light, lld); light = Math.Max(light, llu); } light = Math.Max(light - info.Opacity, 0); if (light != lightval) { //Console.WriteLine("Block SkyLight: ({0},{1},{2}) " + lightval + " -> " + light, k.x, k.y, k.z); cc.SetSkyLight(x, y, z, light); if (info.TransmitsLight) { if (k.y > 0) { QueueRelight(new BlockKey(k.x, k.y - 1, k.z)); } if (k.y < ydim - 1) { QueueRelight(new BlockKey(k.x, k.y + 1, k.z)); } QueueRelight(new BlockKey(k.x - 1, k.y, k.z)); QueueRelight(new BlockKey(k.x + 1, k.y, k.z)); QueueRelight(new BlockKey(k.x, k.y, k.z - 1)); QueueRelight(new BlockKey(k.x, k.y, k.z + 1)); } } } }