mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -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? {
|
private fun mesh(item: WorldQueueItem): WorldMesh? {
|
||||||
if (item.section.blocks.isEmpty) {
|
if (item.section.blocks.isEmpty) {
|
||||||
renderer.queueItemUnload(item)
|
renderer.unload(item)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val neighbours = item.chunk.neighbours.get()
|
val neighbours = item.chunk.neighbours.get()
|
||||||
if (neighbours == null) {
|
if (neighbours == null) {
|
||||||
renderer.queueItemUnload(item)
|
renderer.unload(item)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours, item.chunk, item.section.sectionHeight)
|
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours, item.chunk, item.section.sectionHeight)
|
||||||
@ -55,7 +55,7 @@ class ChunkMesher(
|
|||||||
runnable.interruptable = false
|
runnable.interruptable = false
|
||||||
if (Thread.interrupted()) return
|
if (Thread.interrupted()) return
|
||||||
if (mesh.clearEmpty() == 0) {
|
if (mesh.clearEmpty() == 0) {
|
||||||
return renderer.queueItemUnload(item)
|
return renderer.unload(item)
|
||||||
}
|
}
|
||||||
mesh.finish()
|
mesh.finish()
|
||||||
item.mesh = mesh
|
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.Chunk
|
||||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||||
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||||
|
import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class WorldQueueItem(
|
class WorldQueueItem(
|
||||||
@ -32,11 +33,13 @@ class WorldQueueItem(
|
|||||||
var mesh: WorldMesh? = null
|
var mesh: WorldMesh? = null
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is WorldQueueItem) {
|
if (other is WorldQueueItem) {
|
||||||
return false
|
return chunkPosition == other.chunkPosition && sectionHeight == other.sectionHeight
|
||||||
}
|
}
|
||||||
|
if (other is QueuePosition) {
|
||||||
return chunkPosition == other.chunkPosition && sectionHeight == other.sectionHeight
|
return chunkPosition == other.position && sectionHeight == other.sectionHeight
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
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.util.vec.vec3.Vec3iUtil.chunkPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.world.mesh.VisibleMeshes
|
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.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.MeshLoadingQueue
|
||||||
import de.bixilon.minosoft.gui.rendering.world.queue.loading.MeshUnloadingQueue
|
import de.bixilon.minosoft.gui.rendering.world.queue.loading.MeshUnloadingQueue
|
||||||
import de.bixilon.minosoft.gui.rendering.world.queue.meshing.ChunkMeshingQueue
|
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()
|
lock.lock()
|
||||||
|
|
||||||
loaded.unload(item.chunkPosition, item.sectionHeight, false)
|
loaded.unload(position.position, position.sectionHeight, false)
|
||||||
|
culledQueue.remove(position.position, position.sectionHeight, false)
|
||||||
culledQueue.remove(item.chunkPosition, item.sectionHeight, false)
|
meshingQueue.remove(position, false)
|
||||||
|
loadingQueue.abort(position.position, false)
|
||||||
meshingQueue.remove(item, false)
|
meshingQueue.tasks.interrupt(position.position, position.sectionHeight)
|
||||||
|
|
||||||
loadingQueue.abort(item.chunkPosition, false)
|
|
||||||
|
|
||||||
meshingQueue.tasks.interrupt(item.chunkPosition, item.sectionHeight)
|
|
||||||
|
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
}
|
}
|
||||||
@ -287,9 +285,9 @@ class WorldRenderer(
|
|||||||
|
|
||||||
|
|
||||||
for ((chunk, sectionHeight) in nextQueue) {
|
for ((chunk, sectionHeight) in nextQueue) {
|
||||||
val neighbours = chunk.neighbours.get() ?: continue
|
chunk.neighbours.get() ?: continue
|
||||||
val section = chunk[sectionHeight] ?: 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()) {
|
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.vec2.Vec2i
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||||
import de.bixilon.kutil.exception.Broken
|
|
||||||
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
||||||
import de.bixilon.minosoft.data.direction.Directions
|
import de.bixilon.minosoft.data.direction.Directions
|
||||||
import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN
|
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) {
|
override fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: Array<Chunk>, neighbours: Array<ChunkSection?>, mesh: WorldMesh) {
|
||||||
val random = Random(0L)
|
val random = Random(0L)
|
||||||
|
|
||||||
for (chunk in neighbourChunks) {
|
|
||||||
if (chunk == null || chunk.sections == null || chunk.light == null) {
|
|
||||||
Broken("null!!!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val randomBlockModels = profile.antiMoirePattern
|
val randomBlockModels = profile.antiMoirePattern
|
||||||
val isLowestSection = sectionHeight == chunk.minSection
|
val isLowestSection = sectionHeight == chunk.minSection
|
||||||
|
@ -14,12 +14,29 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.world.queue
|
package de.bixilon.minosoft.gui.rendering.world.queue
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
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 de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
data class QueuePosition(
|
class QueuePosition(
|
||||||
val position: ChunkPosition,
|
val position: ChunkPosition,
|
||||||
val sectionHeight: Int,
|
val sectionHeight: Int,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(mesh: WorldMesh) : this(mesh.chunkPosition, mesh.sectionHeight)
|
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
|
package de.bixilon.minosoft.gui.rendering.world.queue.meshing
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
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.lock.simple.SimpleLock
|
||||||
import de.bixilon.kutil.concurrent.pool.ThreadPool
|
import de.bixilon.kutil.concurrent.pool.ThreadPool
|
||||||
import de.bixilon.kutil.concurrent.pool.ThreadPoolRunnable
|
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.util.vec.vec3.Vec3iUtil.length2
|
||||||
import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem
|
import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem
|
||||||
import de.bixilon.minosoft.gui.rendering.world.WorldRenderer
|
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.MeshPrepareTask
|
||||||
import de.bixilon.minosoft.gui.rendering.world.queue.meshing.tasks.MeshPrepareTaskManager
|
import de.bixilon.minosoft.gui.rendering.world.queue.meshing.tasks.MeshPrepareTaskManager
|
||||||
import de.bixilon.minosoft.util.SystemInformation
|
import de.bixilon.minosoft.util.SystemInformation
|
||||||
@ -141,6 +143,15 @@ class ChunkMeshingQueue(
|
|||||||
if (lock) unlock()
|
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) {
|
fun queue(item: WorldQueueItem) {
|
||||||
lock()
|
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.util.vec.vec3.Vec3iUtil.toVec3
|
||||||
import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem
|
import de.bixilon.minosoft.gui.rendering.world.WorldQueueItem
|
||||||
import de.bixilon.minosoft.gui.rendering.world.WorldRenderer
|
import de.bixilon.minosoft.gui.rendering.world.WorldRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.world.queue.QueuePosition
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
|
||||||
class ChunkQueueMaster(
|
class ChunkQueueMaster(
|
||||||
private val renderer: WorldRenderer,
|
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) {
|
if (section.blocks.isEmpty) {
|
||||||
// TODO: unload
|
renderer.unload(QueuePosition(chunk.chunkPosition, section.sectionHeight))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,27 +50,27 @@ class ChunkQueueMaster(
|
|||||||
return false
|
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
|
if (!canQueue()) return
|
||||||
val chunk = chunk ?: section.chunk ?: return
|
val chunk = chunk ?: section.chunk ?: return
|
||||||
if (!chunk.isFullyLoaded) 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.sort()
|
||||||
renderer.meshingQueue.work()
|
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
|
val section = chunk[sectionHeight] ?: return
|
||||||
tryQueue(section, force, chunk, neighbours)
|
tryQueue(section, force, chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryQueue(chunk: Chunk, ignoreLoaded: Boolean = false, force: Boolean = false) {
|
fun tryQueue(chunk: Chunk, ignoreLoaded: Boolean = false, force: Boolean = false) {
|
||||||
if (!canQueue() || !chunk.isFullyLoaded) return
|
if (!canQueue() || !chunk.isFullyLoaded) return
|
||||||
val neighbours: Array<Chunk> = chunk.neighbours.get() ?: return
|
chunk.neighbours.get() ?: return
|
||||||
|
|
||||||
if (!ignoreLoaded && chunk.chunkPosition in renderer.loaded) {
|
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.
|
// 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
|
var changes = 0
|
||||||
for (sectionHeight in chunk.minSection..chunk.maxSection) { // TODO .. or until?
|
for (sectionHeight in chunk.minSection..chunk.maxSection) { // TODO .. or until?
|
||||||
val section = chunk[sectionHeight] ?: continue
|
val section = chunk[sectionHeight] ?: continue
|
||||||
if (queue(section, chunk, force, neighbours)) {
|
if (queue(section, chunk, force)) {
|
||||||
changes++
|
changes++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,13 @@ object WorldRendererChangeListener {
|
|||||||
val chunk = renderer.world[chunkPosition] ?: return@listen
|
val chunk = renderer.world[chunkPosition] ?: return@listen
|
||||||
val neighbours = chunk.neighbours.get() ?: return@listen
|
val neighbours = chunk.neighbours.get() ?: return@listen
|
||||||
|
|
||||||
master.tryQueue(chunk, sectionHeight, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight)
|
||||||
val inPosition = it.blockPosition.inChunkSectionPosition
|
val inPosition = it.blockPosition.inChunkSectionPosition
|
||||||
|
|
||||||
if (inPosition.y == 0) {
|
if (inPosition.y == 0) {
|
||||||
master.tryQueue(chunk, sectionHeight - 1, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight - 1)
|
||||||
} else if (inPosition.y == ProtocolDefinition.SECTION_MAX_Y) {
|
} else if (inPosition.y == ProtocolDefinition.SECTION_MAX_Y) {
|
||||||
master.tryQueue(chunk, sectionHeight + 1, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight + 1)
|
||||||
}
|
}
|
||||||
if (inPosition.z == 0) {
|
if (inPosition.z == 0) {
|
||||||
master.tryQueue(chunk = neighbours[3], sectionHeight)
|
master.tryQueue(chunk = neighbours[3], sectionHeight)
|
||||||
@ -92,13 +92,13 @@ object WorldRendererChangeListener {
|
|||||||
}
|
}
|
||||||
val neighbours = chunk.neighbours.get() ?: return@listen
|
val neighbours = chunk.neighbours.get() ?: return@listen
|
||||||
for ((sectionHeight, neighbourUpdates) in sectionHeights) {
|
for ((sectionHeight, neighbourUpdates) in sectionHeights) {
|
||||||
master.tryQueue(chunk, sectionHeight, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight)
|
||||||
|
|
||||||
if (neighbourUpdates[0]) {
|
if (neighbourUpdates[0]) {
|
||||||
master.tryQueue(chunk, sectionHeight - 1, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight - 1)
|
||||||
}
|
}
|
||||||
if (neighbourUpdates[1]) {
|
if (neighbourUpdates[1]) {
|
||||||
master.tryQueue(chunk, sectionHeight + 1, neighbours = neighbours)
|
master.tryQueue(chunk, sectionHeight + 1)
|
||||||
}
|
}
|
||||||
if (neighbourUpdates[2]) {
|
if (neighbourUpdates[2]) {
|
||||||
master.tryQueue(neighbours[3], sectionHeight)
|
master.tryQueue(neighbours[3], sectionHeight)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user