public bool TryGetLocalWithNeighborChunk(int i, int j, int k, out VoxelChunkAddress address, out Voxel voxel) { if (j < 0) { address = VoxelChunkAddress.Zero; voxel = Voxel.Bedrock; return(false); } var cx = (int)(-((i & 0b10000000_00000000_00000000_00000000) >> 31) + ((i / SizeXy))); var cy = (int)(-((k & 0b10000000_00000000_00000000_00000000) >> 31) + ((k / SizeXy))); var chunk = GetNeighbor(cx, cy); if (chunk.CurrentHeight <= j) { address = VoxelChunkAddress.Zero; voxel = Voxel.SunBlock; return(false); } else { address = new VoxelChunkAddress(chunk, new Int3(i & (SizeXy - 1), j, k & (SizeXy - 1))); voxel = chunk.GetVoxel(address.RelativeVoxelIndex.X, j, address.RelativeVoxelIndex.Z); return(true); } }
public static IEnumerable<VoxelChunkAddress> GetAllLightSourceNeighbor(VoxelChunkAddress targetAddress, Voxel targetVoxel) { foreach (var direction in LightDirections.All) { var sourceIndex = targetAddress.RelativeVoxelIndex + direction.Step; if (targetAddress.Chunk.TryGetLocalWithNeighborChunk(sourceIndex, out var sourceAddress, out var sourceVoxel) && sourceVoxel.CompositeLight > 0) { var sourceDefinition = sourceVoxel.GetDefinition(); var targetDefinition = targetVoxel.GetDefinition(); var brightnessLoss = VoxelDefinition.GetBrightnessLoss(sourceDefinition, targetDefinition, direction.Direction); if (brightnessLoss > 0) { yield return sourceAddress; } } } }
private void UpdateLighting(VoxelChunkAddress address, Voxel oldVoxel, Voxel newVoxel) { // there are multiple steps which are generating dark spots var darknessSources = new Queue <DarknessSource>(); // SUNLIGHT DARKENING: in case the lower voxel is/was under the sky, the sunlight must be deleted downward if (address.RelativeVoxelIndex.Y > 1 && address.Chunk.GetVoxel(address.RelativeVoxelIndex - Int3.UnitY).Sunlight == 15) { foreach (var sunlightRelativeIndex in LightingService.Sunlight(address, 0, true)) { darknessSources.Enqueue(new DarknessSource(new VoxelChunkAddress(address.Chunk, sunlightRelativeIndex), oldVoxel.SetSunlight(15))); } } // ROOT DARKENING: the root cause voxel always suspect of darkening darknessSources.Enqueue(new DarknessSource(address, oldVoxel)); // PROPAGATE DARKNESS var lightSources = LightingService.GlobalPropagateDarkness(darknessSources); // SUNLIGHT PROPAGATION: in case the upper voxel is/was under the sky, the sunlight must be propagated var upperVoxelIndex = address.RelativeVoxelIndex + Int3.UnitY; if (upperVoxelIndex.Y < address.Chunk.CurrentHeight - 1 && address.Chunk.GetVoxel(upperVoxelIndex).Sunlight == 15) { foreach (var sunlightSources in LightingService.Sunlight(address.Chunk, upperVoxelIndex, 15, true)) { lightSources.Add(new VoxelChunkAddress(address.Chunk, sunlightSources)); } } // NEIGHBOR SOURCES: in case a block was removed and was not under the sky, all the neighbors are potential light sources foreach (var neighborLightSourceAddress in LightingService.GetAllLightSourceNeighbor(address, newVoxel)) { lightSources.Add(neighborLightSourceAddress); } // ROOT PROPAGATE: the root case voxel always suspect of propagation lightSources.Add(address); foreach (var lightSource in lightSources) { LightingService.GlobalPropagate(lightSource); } }
public bool TryGetVoxelAddress(Int3 absoluteVoxelIndex, out VoxelChunkAddress address) { if (!TryGetChunkIndexByAbsoluteVoxelIndex(absoluteVoxelIndex, out var chunkIndex)) { address = VoxelChunkAddress.Zero; return(false); } if (!TryGetChunk(chunkIndex, out var chunk)) { address = VoxelChunkAddress.Zero; return(false); } var voxelIndex = new Int3(absoluteVoxelIndex.X & Chunk.SizeXy - 1, absoluteVoxelIndex.Y, absoluteVoxelIndex.Z & Chunk.SizeXy - 1); address = new VoxelChunkAddress(chunk, voxelIndex); return(true); }
public static void GlobalPropagate(VoxelChunkAddress address) => GlobalPropagate(new Queue<VoxelChunkAddress>(new[] {address}));
public static IEnumerable<Int3> Sunlight(VoxelChunkAddress address, byte toLightness, bool isChangeTracking = false) => Sunlight(address.Chunk, address.RelativeVoxelIndex, toLightness, isChangeTracking);
public bool TryGetLocalWithNeighborChunk(Int3 ijk, out VoxelChunkAddress address, out Voxel voxel) => TryGetLocalWithNeighborChunk(ijk.X, ijk.Y, ijk.Z, out address, out voxel);