diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/ChunkMesher.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/ChunkMesher.kt index f9088d258..c8b2fbf3f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/ChunkMesher.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/ChunkMesher.kt @@ -31,12 +31,12 @@ class ChunkMesher( private fun mesh(item: WorldQueueItem): WorldMesh? { if (item.section.blocks.isEmpty) { - renderer.queueItemUnload(item) + renderer.unload(item) return null } val neighbours = item.chunk.neighbours.get() if (neighbours == null) { - renderer.queueItemUnload(item) + renderer.unload(item) return null } val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours, item.chunk, item.section.sectionHeight) @@ -55,7 +55,7 @@ class ChunkMesher( runnable.interruptable = false if (Thread.interrupted()) return if (mesh.clearEmpty() == 0) { - return renderer.queueItemUnload(item) + return renderer.unload(item) } mesh.finish() item.mesh = mesh diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldQueueItem.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldQueueItem.kt index 1b13afed2..4164abc2a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldQueueItem.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldQueueItem.kt @@ -19,6 +19,7 @@ import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.minosoft.data.world.chunk.Chunk import de.bixilon.minosoft.data.world.chunk.ChunkSection import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition import java.util.* class WorldQueueItem( @@ -32,11 +33,13 @@ class WorldQueueItem( var mesh: WorldMesh? = null override fun equals(other: Any?): Boolean { - if (other !is WorldQueueItem) { - return false + if (other is WorldQueueItem) { + return chunkPosition == other.chunkPosition && sectionHeight == other.sectionHeight } - - return chunkPosition == other.chunkPosition && sectionHeight == other.sectionHeight + if (other is QueuePosition) { + return chunkPosition == other.position && sectionHeight == other.sectionHeight + } + return false } override fun hashCode(): Int { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt index 6306e123c..7f63f34ac 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt @@ -39,6 +39,7 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.world.mesh.VisibleMeshes import de.bixilon.minosoft.gui.rendering.world.queue.CulledQueue +import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition import de.bixilon.minosoft.gui.rendering.world.queue.loading.MeshLoadingQueue import de.bixilon.minosoft.gui.rendering.world.queue.loading.MeshUnloadingQueue import de.bixilon.minosoft.gui.rendering.world.queue.meshing.ChunkMeshingQueue @@ -189,18 +190,15 @@ class WorldRenderer( } - fun queueItemUnload(item: WorldQueueItem) { + fun unload(item: WorldQueueItem) = unload(QueuePosition(item.chunkPosition, item.sectionHeight)) + fun unload(position: QueuePosition) { lock.lock() - loaded.unload(item.chunkPosition, item.sectionHeight, false) - - culledQueue.remove(item.chunkPosition, item.sectionHeight, false) - - meshingQueue.remove(item, false) - - loadingQueue.abort(item.chunkPosition, false) - - meshingQueue.tasks.interrupt(item.chunkPosition, item.sectionHeight) + loaded.unload(position.position, position.sectionHeight, false) + culledQueue.remove(position.position, position.sectionHeight, false) + meshingQueue.remove(position, false) + loadingQueue.abort(position.position, false) + meshingQueue.tasks.interrupt(position.position, position.sectionHeight) lock.unlock() } @@ -287,9 +285,9 @@ class WorldRenderer( for ((chunk, sectionHeight) in nextQueue) { - val neighbours = chunk.neighbours.get() ?: continue + chunk.neighbours.get() ?: continue val section = chunk[sectionHeight] ?: continue - master.tryQueue(section, force = true, chunk = chunk, neighbours = neighbours) + master.tryQueue(section, force = true, chunk = chunk) } if (sortQueue && nextQueue.isNotEmpty()) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt index 731e3bc59..2d6749eac 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt @@ -15,7 +15,6 @@ package de.bixilon.minosoft.gui.rendering.world.preparer.cull import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec3.Vec3i -import de.bixilon.kutil.exception.Broken import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN @@ -61,11 +60,6 @@ class SolidCullSectionPreparer( override fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: Array, neighbours: Array, mesh: WorldMesh) { val random = Random(0L) - for (chunk in neighbourChunks) { - if (chunk == null || chunk.sections == null || chunk.light == null) { - Broken("null!!!") - } - } val randomBlockModels = profile.antiMoirePattern val isLowestSection = sectionHeight == chunk.minSection diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/QueuePosition.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/QueuePosition.kt index 62591d301..d91d59b5c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/QueuePosition.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/QueuePosition.kt @@ -14,12 +14,29 @@ package de.bixilon.minosoft.gui.rendering.world.queue import de.bixilon.minosoft.data.world.positions.ChunkPosition +import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import java.util.* -data class QueuePosition( +class QueuePosition( val position: ChunkPosition, val sectionHeight: Int, ) { constructor(mesh: WorldMesh) : this(mesh.chunkPosition, mesh.sectionHeight) + + + override fun equals(other: Any?): Boolean { + if (other is WorldQueueItem) { + return position == other.chunkPosition && sectionHeight == other.sectionHeight + } + if (other is QueuePosition) { + return position == other.position && sectionHeight == other.sectionHeight + } + return false + } + + override fun hashCode(): Int { + return Objects.hash(position, sectionHeight) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/meshing/ChunkMeshingQueue.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/meshing/ChunkMeshingQueue.kt index e4fd8e840..d20c4cf7b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/meshing/ChunkMeshingQueue.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/meshing/ChunkMeshingQueue.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.world.queue.meshing import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.concurrent.lock.simple.SimpleLock import de.bixilon.kutil.concurrent.pool.ThreadPool import de.bixilon.kutil.concurrent.pool.ThreadPoolRunnable @@ -21,6 +22,7 @@ import de.bixilon.minosoft.data.world.positions.ChunkPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.length2 import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem import de.bixilon.minosoft.gui.rendering.world.WorldRenderer +import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition import de.bixilon.minosoft.gui.rendering.world.queue.meshing.tasks.MeshPrepareTask import de.bixilon.minosoft.gui.rendering.world.queue.meshing.tasks.MeshPrepareTaskManager import de.bixilon.minosoft.util.SystemInformation @@ -141,6 +143,15 @@ class ChunkMeshingQueue( if (lock) unlock() } + fun remove(position: QueuePosition, lock: Boolean) { + if (lock) lock() + // dirty hacking + if (this.set.unsafeCast>().remove(position)) { + this.queue.unsafeCast>() -= position + } + if (lock) unlock() + } + fun queue(item: WorldQueueItem) { lock() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/queue/ChunkQueueMaster.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/queue/ChunkQueueMaster.kt index f422f5885..7f95afceb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/queue/ChunkQueueMaster.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/queue/queue/ChunkQueueMaster.kt @@ -24,16 +24,16 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.of import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3 import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem import de.bixilon.minosoft.gui.rendering.world.WorldRenderer +import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition class ChunkQueueMaster( private val renderer: WorldRenderer, ) { - private fun queue(section: ChunkSection, chunk: Chunk, force: Boolean, neighbours: Array): Boolean { + private fun queue(section: ChunkSection, chunk: Chunk, force: Boolean): Boolean { if (section.blocks.isEmpty) { - // TODO: unload - + renderer.unload(QueuePosition(chunk.chunkPosition, section.sectionHeight)) return false } @@ -50,27 +50,27 @@ class ChunkQueueMaster( return false } - fun tryQueue(section: ChunkSection, force: Boolean = false, chunk: Chunk? = null, neighbours: Array? = null) { + fun tryQueue(section: ChunkSection, force: Boolean = false, chunk: Chunk? = null) { if (!canQueue()) return val chunk = chunk ?: section.chunk ?: return if (!chunk.isFullyLoaded) return - val neighbours = neighbours ?: chunk.neighbours.get() ?: return + chunk.neighbours.get() ?: return - if (queue(section, chunk, force, neighbours)) { + if (queue(section, chunk, force)) { renderer.meshingQueue.sort() renderer.meshingQueue.work() } } - fun tryQueue(chunk: Chunk, sectionHeight: SectionHeight, force: Boolean = false, neighbours: Array? = null) { + fun tryQueue(chunk: Chunk, sectionHeight: SectionHeight, force: Boolean = false) { val section = chunk[sectionHeight] ?: return - tryQueue(section, force, chunk, neighbours) + tryQueue(section, force, chunk) } fun tryQueue(chunk: Chunk, ignoreLoaded: Boolean = false, force: Boolean = false) { if (!canQueue() || !chunk.isFullyLoaded) return - val neighbours: Array = chunk.neighbours.get() ?: return + chunk.neighbours.get() ?: return if (!ignoreLoaded && chunk.chunkPosition in renderer.loaded) { // chunks only get queued when the server sends them, we normally do not want to queue them again. @@ -81,7 +81,7 @@ class ChunkQueueMaster( var changes = 0 for (sectionHeight in chunk.minSection..chunk.maxSection) { // TODO .. or until? val section = chunk[sectionHeight] ?: continue - if (queue(section, chunk, force, neighbours)) { + if (queue(section, chunk, force)) { changes++ } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/util/WorldRendererChangeListener.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/util/WorldRendererChangeListener.kt index f8d58fcce..cf6103212 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/util/WorldRendererChangeListener.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/util/WorldRendererChangeListener.kt @@ -42,13 +42,13 @@ object WorldRendererChangeListener { val chunk = renderer.world[chunkPosition] ?: return@listen val neighbours = chunk.neighbours.get() ?: return@listen - master.tryQueue(chunk, sectionHeight, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight) val inPosition = it.blockPosition.inChunkSectionPosition if (inPosition.y == 0) { - master.tryQueue(chunk, sectionHeight - 1, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight - 1) } else if (inPosition.y == ProtocolDefinition.SECTION_MAX_Y) { - master.tryQueue(chunk, sectionHeight + 1, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight + 1) } if (inPosition.z == 0) { master.tryQueue(chunk = neighbours[3], sectionHeight) @@ -92,13 +92,13 @@ object WorldRendererChangeListener { } val neighbours = chunk.neighbours.get() ?: return@listen for ((sectionHeight, neighbourUpdates) in sectionHeights) { - master.tryQueue(chunk, sectionHeight, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight) if (neighbourUpdates[0]) { - master.tryQueue(chunk, sectionHeight - 1, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight - 1) } if (neighbourUpdates[1]) { - master.tryQueue(chunk, sectionHeight + 1, neighbours = neighbours) + master.tryQueue(chunk, sectionHeight + 1) } if (neighbourUpdates[2]) { master.tryQueue(neighbours[3], sectionHeight)