mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 03:44:54 -04:00
world renderer: properly unload if empty
This commit is contained in:
parent
3988407c90
commit
072efe15eb
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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()) {
|
||||
|
@ -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<Chunk>, neighbours: Array<ChunkSection?>, 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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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<MutableSet<QueuePosition>>().remove(position)) {
|
||||
this.queue.unsafeCast<MutableList<QueuePosition>>() -= position
|
||||
}
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
fun queue(item: WorldQueueItem) {
|
||||
lock()
|
||||
|
@ -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<Chunk>): 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<Chunk>? = 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<Chunk>? = 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> = 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++
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user