public ChannelPropagator(VoxelLightPropagator propagator, VoxelLightChannel channel) { Propagator = propagator; Volume = propagator.Volume; Channel = channel; _propQueue = new ConcurrentQueue <PropNode>(); _depropQueue = new ConcurrentQueue <DepropNode>(); }
protected override void Process() { Input.Wait(); var propagator = new VoxelLightPropagator(Volume); Parallel.For(0, 7, (i) => { if (i < 6) { CalculateSunlight(Volume, i, propagator[i]); } else { CalculatePoint(Volume, propagator[i]); } }); }
public PointChannelPropagator(VoxelLightPropagator propagator) : base(propagator, VoxelLightChannel.Point) { }
public SunChannelPropagator(VoxelLightPropagator propagator, VoxelLightChannel channel) : base(propagator, channel) { }
unsafe void WorkerThread() { var requests = new Stack <VoxelChangeRequest>(); var chunksToRemesh = new HashSet <VoxelChunk>(); var propagator = new VoxelLightPropagator(Volume); while (!_abortRequested) { _changeRequested.WaitOne(); while (_changeRequests.TryDequeue(out var request)) { requests.Push(request); } while (requests.TryPop(out var request)) { var chunkCoords = Volume.GlobalToChunkCoords(request.Coords); var chunk = Volume[chunkCoords]; if (chunk != null) { var localCoords = chunk.VolumeToLocalCoords(request.Coords); var oldOpacity = chunk.Voxels[localCoords].IsOpaque; var voxel = request.Voxel; var newOpacity = voxel.IsOpaque; var pointLight = chunk.LightData[VoxelLightChannel.Point][localCoords]; var typePointLight = voxel.PointLightLevel; if (typePointLight > *pointLight) { propagator.PointPropagationChannel.QueueForPropagation(chunk, localCoords, typePointLight); } if (voxel.IsEmpty) { propagator.PointPropagationChannel.QueueForDepropagation(chunk, localCoords); } if (oldOpacity != newOpacity) { if (newOpacity) { propagator.QueueForDepropagation(chunk, localCoords); } else { propagator.QueueNeighborsForPropagation(chunk, localCoords); } } chunk.Voxels[localCoords] = voxel; chunksToRemesh.Add(chunk); if (localCoords.X == 0) { var neighbor = Volume[chunk.Coords + new Coords(-1, 0, 0)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } else if (localCoords.X == VoxelChunk.SIZE - 1) { var neighbor = Volume[chunk.Coords + new Coords(1, 0, 0)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } if (localCoords.Y == 0) { var neighbor = Volume[chunk.Coords + new Coords(0, -1, 0)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } else if (localCoords.Y == VoxelChunk.SIZE - 1) { var neighbor = Volume[chunk.Coords + new Coords(0, 1, 0)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } if (localCoords.Z == 0) { var neighbor = Volume[chunk.Coords + new Coords(0, 0, -1)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } else if (localCoords.Z == VoxelChunk.SIZE - 1) { var neighbor = Volume[chunk.Coords + new Coords(0, 0, 1)]; if (neighbor is VoxelChunk neighborChunk) { chunksToRemesh.Add(neighborChunk); } } } } propagator.StartPropagationTask(); List <VoxelChunkMesh> meshes = null; if (chunksToRemesh.Count <= _multipleMeshThreshold) { meshes = new List <VoxelChunkMesh>(); } Parallel.ForEach(chunksToRemesh, (chunk) => { var mesh = chunk.Mesh ?? new VoxelChunkMesh(chunk); mesh.GenerateGeometryAndLighting(); if (meshes != null) { meshes.Add(mesh); } else { _singleMeshes.Enqueue(mesh); } }); if (meshes != null) { _multipleMeshes.Enqueue(meshes); } propagator.Wait(); Parallel.ForEach(propagator.AlteredChunks, (chunk) => { var mesh = chunk.Mesh; mesh.GenerateLighting(); _singleMeshes.Enqueue(mesh); }); propagator.Clear(); chunksToRemesh.Clear(); } }