예제 #1
0
        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);
            }
        }
예제 #2
0
 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;
             }
         }
     }
 }
예제 #3
0
        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);
        }
예제 #5
0
 public static void GlobalPropagate(VoxelChunkAddress address) => GlobalPropagate(new Queue<VoxelChunkAddress>(new[] {address}));
예제 #6
0
 public static IEnumerable<Int3> Sunlight(VoxelChunkAddress address, byte toLightness, bool isChangeTracking = false)
  => Sunlight(address.Chunk, address.RelativeVoxelIndex, toLightness, isChangeTracking);
예제 #7
0
 public bool TryGetLocalWithNeighborChunk(Int3 ijk, out VoxelChunkAddress address, out Voxel voxel) => TryGetLocalWithNeighborChunk(ijk.X, ijk.Y, ijk.Z, out address, out voxel);