mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 05:10:57 +00:00
implement infinite worlds with threaded chunk generation
This commit is contained in:
92
Sources/Voxelotl/ChunkGeneration.swift
Normal file
92
Sources/Voxelotl/ChunkGeneration.swift
Normal file
@ -0,0 +1,92 @@
|
||||
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),
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user