voxelotl-engine/Sources/Voxelotl/ChunkGeneration.swift

93 lines
2.4 KiB
Swift

import Foundation
public struct ChunkGeneration {
private let queue: OperationQueue
private let localReadyChunks = ConcurrentDictionary<SIMD3<Int>, Chunk>()
private var generatingChunkSet = Set<SIMD3<Int>>()
weak var world: World?
init(queue: DispatchQueue) {
self.queue = OperationQueue()
self.queue.underlyingQueue = queue
self.queue.maxConcurrentOperationCount = 8
self.queue.qualityOfService = .userInitiated
}
public mutating func generate(chunkID: SIMD3<Int>) {
if !generatingChunkSet.insert(chunkID).inserted {
return
}
self.queueGenerateJob(chunkID: chunkID)
}
func queueGenerateJob(chunkID: SIMD3<Int>) {
self.queue.addOperation {
guard let world = self.world else {
return
}
let chunk = world.generateSingleChunkUncommitted(chunkID: chunkID)
self.localReadyChunks[chunkID] = chunk
}
}
public mutating func generateAdjacentIfNeeded(position: SIMD3<Float>) {
guard let world = self.world else {
return
}
let centerChunkID = World.makeID(position: position)
for offset in ChunkGeneration.chunkGenerateNeighbors {
let chunkID = centerChunkID &+ offset
if world.getChunk(id: chunkID) == nil {
self.generate(chunkID: chunkID)
}
}
}
public mutating func acceptReadyChunks() {
guard let world = self.world else {
return
}
if self.generatingChunkSet.isEmpty {
return
}
for (chunkID, chunk) in self.localReadyChunks.take() {
world.addChunk(chunkID: chunkID, chunk: chunk)
self.generatingChunkSet.remove(chunkID)
}
}
private static let chunkGenerateNeighbors: [SIMD3<Int>] = [
SIMD3<Int>(-1, -1, -1),
SIMD3<Int>(0, -1, -1),
SIMD3<Int>(1, -1, -1),
SIMD3<Int>(-1, 0, -1),
SIMD3<Int>(0, 0, -1),
SIMD3<Int>(1, 0, -1),
SIMD3<Int>(-1, 1, -1),
SIMD3<Int>(0, 1, -1),
SIMD3<Int>(1, 1, -1),
SIMD3<Int>(-1, -1, 0),
SIMD3<Int>(0, -1, 0),
SIMD3<Int>(1, -1, 0),
SIMD3<Int>(-1, 0, 0),
SIMD3<Int>(0, 0, 0),
SIMD3<Int>(1, 0, 0),
SIMD3<Int>(-1, 1, 0),
SIMD3<Int>(0, 1, 0),
SIMD3<Int>(1, 1, 0),
SIMD3<Int>(-1, -1, 1),
SIMD3<Int>(0, -1, 1),
SIMD3<Int>(1, -1, 1),
SIMD3<Int>(-1, 0, 1),
SIMD3<Int>(0, 0, 1),
SIMD3<Int>(1, 0, 1),
SIMD3<Int>(-1, 1, 1),
SIMD3<Int>(0, 1, 1),
SIMD3<Int>(1, 1, 1),
]
}