mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 11:24:56 -04:00
section position
This commit is contained in:
parent
8f1247d4b1
commit
375bccca47
@ -27,6 +27,7 @@ import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
|||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.camera.Camera
|
import de.bixilon.minosoft.gui.rendering.camera.Camera
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
||||||
@ -80,9 +81,9 @@ class SolidSectionMesherTest {
|
|||||||
val mesher = SolidSectionMesher(context)
|
val mesher = SolidSectionMesher(context)
|
||||||
|
|
||||||
val chunk = world.chunks[0, 0]!!
|
val chunk = world.chunks[0, 0]!!
|
||||||
val meshes = ChunkMeshes(context, chunk.position, 0, true)
|
val meshes = ChunkMeshes(context, SectionPosition.of(chunk.position, 0), true)
|
||||||
|
|
||||||
mesher.mesh(chunk.position, 0, chunk, chunk.sections[0]!!, chunk.neighbours.neighbours, chunk.sections[0]!!.neighbours!!, meshes)
|
mesher.mesh(SectionPosition.of(chunk.position, 0), chunk, chunk.sections[0]!!, chunk.neighbours.neighbours, chunk.sections[0]!!.neighbours!!, meshes)
|
||||||
|
|
||||||
return meshes
|
return meshes
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import de.bixilon.minosoft.data.world.container.block.BlockSectionDataProvider
|
|||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
||||||
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
import de.bixilon.minosoft.protocol.network.session.play.PlaySession
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ import java.util.*
|
|||||||
* Collection of 16x16x16 blocks
|
* Collection of 16x16x16 blocks
|
||||||
*/
|
*/
|
||||||
class ChunkSection(
|
class ChunkSection(
|
||||||
val height: Int,
|
val height: SectionHeight,
|
||||||
val chunk: Chunk,
|
val chunk: Chunk,
|
||||||
) {
|
) {
|
||||||
val blocks = BlockSectionDataProvider(chunk.lock, this)
|
val blocks = BlockSectionDataProvider(chunk.lock, this)
|
||||||
|
@ -111,6 +111,7 @@ value class BlockPosition(
|
|||||||
inline val hash get() = generatePositionHash(x, y, z)
|
inline val hash get() = generatePositionHash(x, y, z)
|
||||||
inline val sectionHeight get() = y.sectionHeight
|
inline val sectionHeight get() = y.sectionHeight
|
||||||
inline val chunkPosition get() = ChunkPosition(x shr 4, z shr 4)
|
inline val chunkPosition get() = ChunkPosition(x shr 4, z shr 4)
|
||||||
|
inline val sectionPosition get() = SectionPosition(x shr 4, y shr 4, z shr 4)
|
||||||
inline val inChunkPosition get() = InChunkPosition(x and 0x0F, y, this.z and 0x0F)
|
inline val inChunkPosition get() = InChunkPosition(x and 0x0F, y, this.z and 0x0F)
|
||||||
inline val inSectionPosition get() = InSectionPosition(x and 0x0F, y.inSectionHeight, z and 0x0F)
|
inline val inSectionPosition get() = InSectionPosition(x and 0x0F, y.inSectionHeight, z and 0x0F)
|
||||||
|
|
||||||
@ -169,5 +170,13 @@ value class BlockPosition(
|
|||||||
chunk.z * ProtocolDefinition.SECTION_WIDTH_Z + inSection.z
|
chunk.z * ProtocolDefinition.SECTION_WIDTH_Z + inSection.z
|
||||||
) // ToDo: Confirm
|
) // ToDo: Confirm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun of(section: SectionPosition, inSection: InSectionPosition): BlockPosition {
|
||||||
|
return BlockPosition(
|
||||||
|
section.x * ProtocolDefinition.SECTION_WIDTH_X + inSection.x,
|
||||||
|
section.y * ProtocolDefinition.SECTION_HEIGHT_Y + inSection.y,
|
||||||
|
section.z * ProtocolDefinition.SECTION_WIDTH_Z + inSection.z
|
||||||
|
) // ToDo: Confirm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,8 @@ value class ChunkPosition(
|
|||||||
inline operator fun component1() = x
|
inline operator fun component1() = x
|
||||||
inline operator fun component2() = z
|
inline operator fun component2() = z
|
||||||
|
|
||||||
|
fun sectionPosition(y: SectionHeight) = SectionPosition(x, y, z)
|
||||||
|
|
||||||
override fun toText() = "(${this.x.format()} ${this.z.format()})"
|
override fun toText() = "(${this.x.format()} ${this.z.format()})"
|
||||||
override fun toString() = "c($x $z)"
|
override fun toString() = "c($x $z)"
|
||||||
|
|
||||||
@ -105,8 +107,8 @@ value class ChunkPosition(
|
|||||||
const val Z = 1L shl SHIFT_Z
|
const val Z = 1L shl SHIFT_Z
|
||||||
|
|
||||||
|
|
||||||
const val MAX_X = (BlockPosition.MAX_X shr 4) + 1
|
const val MAX_X = BlockPosition.MAX_X shr 4
|
||||||
const val MAX_Z = (BlockPosition.MAX_Z shr 4) + 1
|
const val MAX_Z = BlockPosition.MAX_Z shr 4
|
||||||
|
|
||||||
|
|
||||||
val EMPTY = ChunkPosition(0, 0)
|
val EMPTY = ChunkPosition(0, 0)
|
||||||
|
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.data.world.positions
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.direction.Directions
|
||||||
|
import de.bixilon.minosoft.data.text.formatting.TextFormattable
|
||||||
|
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.assertPosition
|
||||||
|
import de.bixilon.minosoft.util.KUtil.format
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class SectionPosition(
|
||||||
|
inline val raw: Long,
|
||||||
|
) : TextFormattable {
|
||||||
|
|
||||||
|
constructor() : this(0, 0, 0)
|
||||||
|
|
||||||
|
constructor(x: Int, y: SectionHeight, z: Int) : this(((y and MASK_Y).toLong() shl SHIFT_Y) or ((z and MASK_Z).toLong() shl SHIFT_Z) or ((x and MASK_X).toLong() shl SHIFT_X)) {
|
||||||
|
assertPosition(x, -MAX_X, MAX_X)
|
||||||
|
assertPosition(y, MIN_Y, MAX_Y)
|
||||||
|
assertPosition(z, -MAX_Z, MAX_Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val x: Int get() = (((raw ushr SHIFT_X).toInt() and MASK_X) shl (Int.SIZE_BITS - BITS_X)) shr (Int.SIZE_BITS - BITS_X)
|
||||||
|
inline val y: SectionHeight get() = (((raw ushr SHIFT_Y).toInt() and MASK_Y) shl (Int.SIZE_BITS - BITS_Y)) shr (Int.SIZE_BITS - BITS_Y)
|
||||||
|
inline val z: Int get() = (((raw ushr SHIFT_Z).toInt() and MASK_Z) shl (Int.SIZE_BITS - BITS_Z)) shr (Int.SIZE_BITS - BITS_Z)
|
||||||
|
|
||||||
|
inline fun plusX(): SectionPosition {
|
||||||
|
assertPosition(this.x < MAX_X)
|
||||||
|
return SectionPosition(raw + X * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun plusX(x: Int): SectionPosition {
|
||||||
|
assertPosition(this.x + x, -MAX_X, MAX_X)
|
||||||
|
return SectionPosition(raw + X * x)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun minusX(): SectionPosition {
|
||||||
|
assert(this.x > -MAX_X)
|
||||||
|
return SectionPosition(raw - X * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun plusY(): SectionPosition {
|
||||||
|
assertPosition(this.y < MAX_Y)
|
||||||
|
return SectionPosition(raw + Y * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun plusY(y: Int): SectionPosition {
|
||||||
|
assertPosition(this.y + y, MIN_Y, MAX_Y)
|
||||||
|
return SectionPosition(raw + Y * y)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun minusY(): SectionPosition {
|
||||||
|
assert(this.y > MIN_Y)
|
||||||
|
return SectionPosition(raw - Y * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun plusZ(): SectionPosition {
|
||||||
|
assert(this.z < MAX_Z)
|
||||||
|
return SectionPosition(raw + Z * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun plusZ(z: Int): SectionPosition {
|
||||||
|
assertPosition(this.z + z, -MAX_Z, MAX_Z)
|
||||||
|
return SectionPosition(raw + Z * z)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun minusZ(): SectionPosition {
|
||||||
|
assert(this.z > -MAX_Z)
|
||||||
|
return SectionPosition(raw - Z * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun with(x: Int = this.x, y: Int = this.y, z: Int = this.z) = SectionPosition(x, y, z)
|
||||||
|
|
||||||
|
inline operator fun plus(value: Int) = SectionPosition(this.x + value, this.y + value, this.z + value)
|
||||||
|
inline operator fun minus(value: Int) = SectionPosition(this.x - value, this.y - value, this.z - value)
|
||||||
|
inline operator fun times(value: Int) = SectionPosition(this.x * value, this.y * value, this.z * value)
|
||||||
|
inline operator fun div(value: Int) = SectionPosition(this.x / value, this.y * value, this.z / value)
|
||||||
|
|
||||||
|
inline operator fun plus(position: SectionPosition) = SectionPosition(this.x + position.x, this.y + position.y, this.z + position.z)
|
||||||
|
inline operator fun minus(position: SectionPosition) = SectionPosition(this.x - position.x, this.y - position.y, this.z - position.z)
|
||||||
|
|
||||||
|
inline operator fun plus(position: ChunkPosition) = SectionPosition(this.x + position.x, this.y, this.z + position.z)
|
||||||
|
inline operator fun minus(position: ChunkPosition) = SectionPosition(this.x - position.x, this.y, this.z - position.z)
|
||||||
|
|
||||||
|
inline operator fun plus(direction: Directions) = SectionPosition(this.x + direction.vector.x, this.y + direction.vector.y, this.z + direction.vector.z)
|
||||||
|
inline operator fun minus(direction: Directions) = SectionPosition(this.x - direction.vector.x, this.y - direction.vector.y, this.z - direction.vector.z)
|
||||||
|
|
||||||
|
inline operator fun unaryMinus() = SectionPosition(-this.x, -this.y, -this.z)
|
||||||
|
inline operator fun unaryPlus() = this
|
||||||
|
|
||||||
|
|
||||||
|
inline operator fun component1() = x
|
||||||
|
inline operator fun component2() = y
|
||||||
|
inline operator fun component3() = z
|
||||||
|
|
||||||
|
inline fun length2() = (x * x + y * y + z * z)
|
||||||
|
|
||||||
|
inline fun sectionIndex(minSection: SectionHeight): SectionIndex = this.y - minSection
|
||||||
|
inline val chunkPosition get() = ChunkPosition(x, z)
|
||||||
|
|
||||||
|
override fun toText() = "(${this.x.format()} ${this.y.format()} ${this.z.format()})"
|
||||||
|
override fun toString() = "c($x $y $z)"
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val BITS_X = 22
|
||||||
|
const val MASK_X = (1 shl BITS_X) - 1
|
||||||
|
const val SHIFT_X = 0
|
||||||
|
|
||||||
|
const val BITS_Z = 22
|
||||||
|
const val MASK_Z = (1 shl BITS_Z) - 1
|
||||||
|
const val SHIFT_Z = BITS_X
|
||||||
|
|
||||||
|
const val BITS_Y = 8
|
||||||
|
const val MASK_Y = (1 shl BITS_Y) - 1
|
||||||
|
const val SHIFT_Y = BITS_X + BITS_Z
|
||||||
|
|
||||||
|
const val X = 1L shl SHIFT_X
|
||||||
|
const val Z = 1L shl SHIFT_Z
|
||||||
|
const val Y = 1L shl SHIFT_Y
|
||||||
|
|
||||||
|
|
||||||
|
const val MAX_X = BlockPosition.MAX_X shr 4
|
||||||
|
const val MIN_Y = BlockPosition.MIN_Y shr 4
|
||||||
|
const val MAX_Y = BlockPosition.MAX_Y shr 4
|
||||||
|
const val MAX_Z = BlockPosition.MAX_Z shr 4
|
||||||
|
|
||||||
|
|
||||||
|
fun of(chunkPosition: ChunkPosition, sectionHeight: Int) = SectionPosition(chunkPosition.x, sectionHeight, chunkPosition.z)
|
||||||
|
fun of(chunkPosition: ChunkPosition, sectionIndex: SectionIndex, minSection: SectionHeight) = SectionPosition(chunkPosition.x, sectionIndex + minSection, chunkPosition.z)
|
||||||
|
|
||||||
|
|
||||||
|
val EMPTY = SectionPosition(0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
@ -138,7 +138,7 @@ class MatrixHandler(
|
|||||||
|
|
||||||
if (view.updateFrustum) {
|
if (view.updateFrustum) {
|
||||||
frustum.recalculate()
|
frustum.recalculate()
|
||||||
camera.visibilityGraph.updateCamera(cameraBlockPosition.chunkPosition, cameraBlockPosition.sectionHeight)
|
camera.visibilityGraph.updateCamera(cameraBlockPosition.sectionPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.events.fire(CameraPositionChangeEvent(context, useEyePosition))
|
session.events.fire(CameraPositionChangeEvent(context, useEyePosition))
|
||||||
|
@ -23,6 +23,7 @@ import de.bixilon.minosoft.config.key.KeyCodes
|
|||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
import de.bixilon.minosoft.data.world.World
|
import de.bixilon.minosoft.data.world.World
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderingStates
|
import de.bixilon.minosoft.gui.rendering.RenderingStates
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.VisibleMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.VisibleMeshes
|
||||||
@ -86,8 +87,7 @@ class ChunkRenderer(
|
|||||||
private var previousViewDistance = session.world.view.viewDistance
|
private var previousViewDistance = session.world.view.viewDistance
|
||||||
|
|
||||||
private var cameraPosition = Vec3.EMPTY
|
private var cameraPosition = Vec3.EMPTY
|
||||||
var cameraChunkPosition = ChunkPosition.EMPTY
|
var cameraSectionPosition = SectionPosition.EMPTY
|
||||||
var cameraSectionHeight = 0
|
|
||||||
|
|
||||||
var limitChunkTransferTime = true
|
var limitChunkTransferTime = true
|
||||||
|
|
||||||
@ -198,15 +198,15 @@ class ChunkRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun unload(item: WorldQueueItem) = unload(QueuePosition(item.chunkPosition, item.sectionHeight))
|
fun unload(item: WorldQueueItem) = unload(QueuePosition(item.position))
|
||||||
fun unload(position: QueuePosition) {
|
fun unload(position: QueuePosition) {
|
||||||
lock.lock()
|
lock.lock()
|
||||||
|
|
||||||
loaded.unload(position.position, position.sectionHeight, false)
|
loaded.unload(position.position, false)
|
||||||
culledQueue.remove(position.position, position.sectionHeight, false)
|
culledQueue.remove(position.position.chunkPosition, false)
|
||||||
meshingQueue.remove(position, false)
|
meshingQueue.remove(position, false)
|
||||||
loadingQueue.abort(position, false)
|
loadingQueue.abort(position, false)
|
||||||
meshingQueue.tasks.interrupt(position.position, position.sectionHeight)
|
meshingQueue.tasks.interrupt(position.position.chunkPosition)
|
||||||
|
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
}
|
}
|
||||||
@ -252,15 +252,10 @@ class ChunkRenderer(
|
|||||||
private fun onFrustumChange() {
|
private fun onFrustumChange() {
|
||||||
var sortQueue = false
|
var sortQueue = false
|
||||||
val cameraPosition = Vec3(session.player.renderInfo.eyePosition - context.camera.offset.offset)
|
val cameraPosition = Vec3(session.player.renderInfo.eyePosition - context.camera.offset.offset)
|
||||||
val cameraChunkPosition = cameraPosition.blockPosition.chunkPosition
|
val sectionPosition = cameraPosition.blockPosition.sectionPosition
|
||||||
val cameraSectionHeight = this.cameraSectionHeight
|
|
||||||
if (this.cameraPosition != cameraPosition) {
|
if (this.cameraPosition != cameraPosition) {
|
||||||
if (this.cameraChunkPosition != cameraChunkPosition) {
|
if (this.cameraSectionPosition != sectionPosition) {
|
||||||
this.cameraChunkPosition = cameraChunkPosition
|
this.cameraSectionPosition = sectionPosition
|
||||||
sortQueue = true
|
|
||||||
}
|
|
||||||
if (this.cameraSectionHeight != cameraSectionHeight) {
|
|
||||||
this.cameraSectionHeight = cameraSectionHeight
|
|
||||||
sortQueue = true
|
sortQueue = true
|
||||||
}
|
}
|
||||||
this.cameraPosition = cameraPosition
|
this.cameraPosition = cameraPosition
|
||||||
|
@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.chunk
|
|||||||
|
|
||||||
import de.bixilon.kutil.concurrent.lock.RWLock
|
import de.bixilon.kutil.concurrent.lock.RWLock
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.VisibleMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.VisibleMeshes
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
@ -67,17 +68,17 @@ class LoadedMeshes(
|
|||||||
if (lock) unlock()
|
if (lock) unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unload(position: ChunkPosition, sectionHeight: Int, lock: Boolean) {
|
fun unload(position: SectionPosition, lock: Boolean) {
|
||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
|
|
||||||
val meshes = this.meshes[position]
|
val meshes = this.meshes[position.chunkPosition]
|
||||||
|
|
||||||
if (meshes != null) {
|
if (meshes != null) {
|
||||||
meshes.remove(sectionHeight)?.let {
|
meshes.remove(position.y)?.let {
|
||||||
renderer.unloadingQueue.forceQueue(it, lock)
|
renderer.unloadingQueue.forceQueue(it, lock)
|
||||||
|
|
||||||
if (meshes.isEmpty()) {
|
if (meshes.isEmpty()) {
|
||||||
this.meshes.remove(position)
|
this.meshes.remove(position.chunkPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +107,7 @@ class LoadedMeshes(
|
|||||||
|
|
||||||
for (entry in meshes.int2ObjectEntrySet()) {
|
for (entry in meshes.int2ObjectEntrySet()) {
|
||||||
val mesh = entry.value
|
val mesh = entry.value
|
||||||
if (!renderer.visibilityGraph.isSectionVisible(chunkPosition, entry.intKey, mesh.minPosition, mesh.maxPosition, false)) {
|
if (!renderer.visibilityGraph.isSectionVisible(SectionPosition.of(chunkPosition, entry.intKey), mesh.minPosition, mesh.maxPosition, false)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
visible.addMesh(mesh)
|
visible.addMesh(mesh)
|
||||||
|
@ -14,22 +14,18 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.chunk
|
package de.bixilon.minosoft.gui.rendering.chunk
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3
|
import de.bixilon.kotlinglm.vec3.Vec3
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
|
||||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.queue.QueuePosition
|
import de.bixilon.minosoft.gui.rendering.chunk.queue.QueuePosition
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class WorldQueueItem(
|
class WorldQueueItem(
|
||||||
val chunkPosition: ChunkPosition,
|
val position: SectionPosition,
|
||||||
val sectionHeight: Int,
|
|
||||||
val chunk: Chunk,
|
val chunk: Chunk,
|
||||||
val section: ChunkSection,
|
val section: ChunkSection,
|
||||||
val center: Vec3,
|
val center: Vec3,
|
||||||
) {
|
) {
|
||||||
val sectionPosition = Vec3i(chunkPosition.x, sectionHeight, chunkPosition.z)
|
|
||||||
var mesh: ChunkMeshes? = null
|
var mesh: ChunkMeshes? = null
|
||||||
|
|
||||||
var distance = 0
|
var distance = 0
|
||||||
@ -37,15 +33,15 @@ class WorldQueueItem(
|
|||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other is WorldQueueItem) {
|
if (other is WorldQueueItem) {
|
||||||
return chunkPosition == other.chunkPosition && sectionHeight == other.sectionHeight
|
return position == other.position
|
||||||
}
|
}
|
||||||
if (other is QueuePosition) {
|
if (other is QueuePosition) {
|
||||||
return chunkPosition == other.position && sectionHeight == other.sectionHeight
|
return position == other.position
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return Objects.hash(chunkPosition, sectionHeight)
|
return position.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ import de.bixilon.kotlinglm.vec2.Vec2
|
|||||||
import de.bixilon.kotlinglm.vec3.Vec3
|
import de.bixilon.kotlinglm.vec3.Vec3
|
||||||
import de.bixilon.kutil.exception.Broken
|
import de.bixilon.kutil.exception.Broken
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
|
||||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
|
||||||
@ -29,11 +29,10 @@ import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
|||||||
|
|
||||||
class ChunkMeshes(
|
class ChunkMeshes(
|
||||||
context: RenderContext,
|
context: RenderContext,
|
||||||
val chunkPosition: ChunkPosition,
|
val position: SectionPosition,
|
||||||
val sectionHeight: Int,
|
|
||||||
smallMesh: Boolean = false,
|
smallMesh: Boolean = false,
|
||||||
) : BlockVertexConsumer {
|
) : BlockVertexConsumer {
|
||||||
val center: Vec3 = Vec3(BlockPosition.of(chunkPosition, sectionHeight, InSectionPosition(8, 8, 8)))
|
val center: Vec3 = Vec3(BlockPosition.of(position, InSectionPosition(8, 8, 8)))
|
||||||
var opaqueMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 8192 else 65536)
|
var opaqueMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 8192 else 65536)
|
||||||
var translucentMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 4096 else 16384)
|
var translucentMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 4096 else 16384)
|
||||||
var textMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 1024 else 4096)
|
var textMesh: ChunkMesh? = ChunkMesh(context, if (smallMesh) 1024 else 4096)
|
||||||
|
@ -38,12 +38,12 @@ class ChunkMesher(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours.neighbours, item.chunk, item.section.height)
|
val sectionNeighbours = ChunkUtil.getDirectNeighbours(neighbours.neighbours, item.chunk, item.section.height)
|
||||||
val mesh = ChunkMeshes(renderer.context, item.chunkPosition, item.sectionHeight, item.section.smallMesh)
|
val mesh = ChunkMeshes(renderer.context, item.position, item.section.smallMesh)
|
||||||
try {
|
try {
|
||||||
solid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, neighbours.neighbours, sectionNeighbours, mesh)
|
solid.mesh(item.position, item.chunk, item.section, neighbours.neighbours, sectionNeighbours, mesh)
|
||||||
|
|
||||||
if (item.section.blocks.hasFluid) {
|
if (item.section.blocks.hasFluid) {
|
||||||
fluid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, mesh)
|
fluid.mesh(item.position, item.chunk, item.section, mesh)
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
mesh.unload()
|
mesh.unload()
|
||||||
|
@ -30,9 +30,9 @@ import de.bixilon.minosoft.data.text.formatting.color.Colors
|
|||||||
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
|
||||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMesh
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMesh
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
||||||
@ -62,7 +62,7 @@ class FluidSectionMesher(
|
|||||||
|
|
||||||
|
|
||||||
// ToDo: Should this be combined with the solid renderer (but we'd need to render faces twice, because of cullface)
|
// ToDo: Should this be combined with the solid renderer (but we'd need to render faces twice, because of cullface)
|
||||||
fun mesh(chunkPosition: ChunkPosition, sectionHeight: Int, chunk: Chunk, section: ChunkSection, mesh: ChunkMeshes) {
|
fun mesh(sectionPosition: SectionPosition, chunk: Chunk, section: ChunkSection, mesh: ChunkMeshes) {
|
||||||
val blocks = section.blocks
|
val blocks = section.blocks
|
||||||
|
|
||||||
var position = BlockPosition()
|
var position = BlockPosition()
|
||||||
@ -70,9 +70,9 @@ class FluidSectionMesher(
|
|||||||
|
|
||||||
val cameraOffset = context.camera.offset.offset
|
val cameraOffset = context.camera.offset.offset
|
||||||
|
|
||||||
val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X
|
val offsetX = sectionPosition.x * ProtocolDefinition.SECTION_WIDTH_X
|
||||||
val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y
|
val offsetY = sectionPosition.y * ProtocolDefinition.SECTION_HEIGHT_Y
|
||||||
val offsetZ = chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z
|
val offsetZ = sectionPosition.z * ProtocolDefinition.SECTION_WIDTH_Z
|
||||||
|
|
||||||
for (y in blocks.minPosition.y..blocks.maxPosition.y) {
|
for (y in blocks.minPosition.y..blocks.maxPosition.y) {
|
||||||
for (z in blocks.minPosition.z..blocks.maxPosition.z) {
|
for (z in blocks.minPosition.z..blocks.maxPosition.z) {
|
||||||
|
@ -32,9 +32,9 @@ import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
|||||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbourArray
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
|
||||||
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
import de.bixilon.minosoft.data.world.positions.InChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
import de.bixilon.minosoft.data.world.positions.InSectionPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.RenderedBlockEntity
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.RenderedBlockEntity
|
||||||
@ -59,12 +59,12 @@ class SolidSectionMesher(
|
|||||||
profile.light::ambientOcclusion.observe(this, true) { this.ambientOcclusion = it }
|
profile.light::ambientOcclusion.observe(this, true) { this.ambientOcclusion = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mesh(chunkPosition: ChunkPosition, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbourChunks: ChunkNeighbourArray, neighbours: Array<ChunkSection?>, mesh: ChunkMeshes) {
|
fun mesh(sectionPosition: SectionPosition, chunk: Chunk, section: ChunkSection, neighbourChunks: ChunkNeighbourArray, neighbours: Array<ChunkSection?>, mesh: ChunkMeshes) {
|
||||||
val random = if (profile.antiMoirePattern) Random(0L) else null
|
val random = if (profile.antiMoirePattern) Random(0L) else null
|
||||||
|
|
||||||
|
|
||||||
val isLowestSection = sectionHeight == chunk.minSection
|
val isLowestSection = sectionPosition.y == chunk.minSection
|
||||||
val isHighestSection = sectionHeight == chunk.maxSection
|
val isHighestSection = sectionPosition.y == chunk.maxSection
|
||||||
val blocks = section.blocks
|
val blocks = section.blocks
|
||||||
val entities: ArrayList<BlockEntityRenderer<*>> = ArrayList(section.blockEntities.count)
|
val entities: ArrayList<BlockEntityRenderer<*>> = ArrayList(section.blockEntities.count)
|
||||||
|
|
||||||
@ -76,9 +76,9 @@ class SolidSectionMesher(
|
|||||||
|
|
||||||
val cameraOffset = context.camera.offset.offset
|
val cameraOffset = context.camera.offset.offset
|
||||||
|
|
||||||
val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X
|
val offsetX = sectionPosition.x * ProtocolDefinition.SECTION_WIDTH_X
|
||||||
val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y
|
val offsetY = sectionPosition.y * ProtocolDefinition.SECTION_HEIGHT_Y
|
||||||
val offsetZ = chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z
|
val offsetZ = sectionPosition.z * ProtocolDefinition.SECTION_WIDTH_Z
|
||||||
|
|
||||||
val floatOffset = FloatArray(3)
|
val floatOffset = FloatArray(3)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import de.bixilon.kutil.concurrent.lock.RWLock
|
|||||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ class CulledQueue(
|
|||||||
val heightIterator = sectionHeights.intIterator()
|
val heightIterator = sectionHeights.intIterator()
|
||||||
for (sectionHeight in heightIterator) {
|
for (sectionHeight in heightIterator) {
|
||||||
val section = chunk[sectionHeight] ?: continue
|
val section = chunk[sectionHeight] ?: continue
|
||||||
if (!renderer.visibilityGraph.isSectionVisible(chunkPosition, sectionHeight, section.blocks.minPosition, section.blocks.maxPosition, false)) {
|
if (!renderer.visibilityGraph.isSectionVisible(SectionPosition.Companion.of(chunkPosition, sectionHeight), section.blocks.minPosition, section.blocks.maxPosition, false)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
list += Pair(chunk, sectionHeight)
|
list += Pair(chunk, sectionHeight)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -13,30 +13,28 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.chunk.queue
|
package de.bixilon.minosoft.gui.rendering.chunk.queue
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class QueuePosition(
|
class QueuePosition(
|
||||||
val position: ChunkPosition,
|
val position: SectionPosition,
|
||||||
val sectionHeight: Int,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(mesh: ChunkMeshes) : this(mesh.chunkPosition, mesh.sectionHeight)
|
constructor(mesh: ChunkMeshes) : this(mesh.position)
|
||||||
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other is WorldQueueItem) {
|
if (other is WorldQueueItem) {
|
||||||
return position == other.chunkPosition && sectionHeight == other.sectionHeight
|
return position == other.position
|
||||||
}
|
}
|
||||||
if (other is QueuePosition) {
|
if (other is QueuePosition) {
|
||||||
return position == other.position && sectionHeight == other.sectionHeight
|
return position == other.position
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return Objects.hash(position, sectionHeight)
|
return position.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,18 +58,18 @@ class MeshLoadingQueue(
|
|||||||
|
|
||||||
mesh.load()
|
mesh.load()
|
||||||
|
|
||||||
if (position != mesh.chunkPosition) {
|
if (position != mesh.position.chunkPosition) {
|
||||||
meshes = renderer.loaded.meshes.getOrPut(mesh.chunkPosition) { Int2ObjectOpenHashMap() }
|
meshes = renderer.loaded.meshes.getOrPut(mesh.position.chunkPosition) { Int2ObjectOpenHashMap() }
|
||||||
position = mesh.chunkPosition
|
position = mesh.position.chunkPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
meshes.put(mesh.sectionHeight, mesh)?.let {
|
meshes.put(mesh.position.y, mesh)?.let {
|
||||||
renderer.visible.removeMesh(it)
|
renderer.visible.removeMesh(it)
|
||||||
it.unload()
|
it.unload()
|
||||||
}
|
}
|
||||||
|
|
||||||
val visible = renderer.visibilityGraph.isSectionVisible(mesh.chunkPosition, mesh.sectionHeight, mesh.minPosition, mesh.maxPosition, true)
|
val visible = renderer.visibilityGraph.isSectionVisible(mesh.position, mesh.minPosition, mesh.maxPosition, true)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
count++
|
count++
|
||||||
renderer.visible.addMesh(mesh)
|
renderer.visible.addMesh(mesh)
|
||||||
@ -91,7 +91,7 @@ class MeshLoadingQueue(
|
|||||||
// already inside, remove
|
// already inside, remove
|
||||||
meshes.remove(mesh)
|
meshes.remove(mesh)
|
||||||
}
|
}
|
||||||
if (mesh.chunkPosition == renderer.cameraChunkPosition) {
|
if (mesh.position.chunkPosition == renderer.cameraSectionPosition.chunkPosition) {
|
||||||
// still higher priority
|
// still higher priority
|
||||||
meshes.add(0, mesh)
|
meshes.add(0, mesh)
|
||||||
} else {
|
} else {
|
||||||
@ -104,20 +104,20 @@ class MeshLoadingQueue(
|
|||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
val positions: MutableSet<QueuePosition> = mutableSetOf()
|
val positions: MutableSet<QueuePosition> = mutableSetOf()
|
||||||
this.positions.removeAll {
|
this.positions.removeAll {
|
||||||
if (it.position != position) {
|
if (it.position.chunkPosition != position) {
|
||||||
return@removeAll false
|
return@removeAll false
|
||||||
}
|
}
|
||||||
positions += it
|
positions += it
|
||||||
return@removeAll true
|
return@removeAll true
|
||||||
}
|
}
|
||||||
this.meshes.removeAll { QueuePosition(it.chunkPosition, it.sectionHeight) in positions }
|
this.meshes.removeAll { QueuePosition(it.position) in positions }
|
||||||
if (lock) unlock()
|
if (lock) unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun abort(position: QueuePosition, lock: Boolean = true) {
|
fun abort(position: QueuePosition, lock: Boolean = true) {
|
||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
if (this.positions.remove(position)) {
|
if (this.positions.remove(position)) {
|
||||||
this.meshes.removeAll { it.chunkPosition == position.position && it.sectionHeight == position.sectionHeight }
|
this.meshes.removeAll { it.position == position.position }
|
||||||
}
|
}
|
||||||
if (lock) unlock()
|
if (lock) unlock()
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ class MeshLoadingQueue(
|
|||||||
|
|
||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
this.positions.removeAll {
|
this.positions.removeAll {
|
||||||
if (renderer.visibilityGraph.isChunkVisible(it.position)) {
|
if (renderer.visibilityGraph.isChunkVisible(it.position.chunkPosition)) {
|
||||||
return@removeAll false
|
return@removeAll false
|
||||||
}
|
}
|
||||||
remove += it
|
remove += it
|
||||||
|
@ -60,7 +60,7 @@ class MeshUnloadingQueue(
|
|||||||
fun forceQueue(mesh: ChunkMeshes, lock: Boolean = true) {
|
fun forceQueue(mesh: ChunkMeshes, lock: Boolean = true) {
|
||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
|
|
||||||
if (mesh.chunkPosition == renderer.session.camera.entity.physics.positionInfo.chunkPosition) {
|
if (mesh.position.chunkPosition == renderer.session.camera.entity.physics.positionInfo.chunkPosition) {
|
||||||
this.meshes.add(0, mesh)
|
this.meshes.add(0, mesh)
|
||||||
} else {
|
} else {
|
||||||
this.meshes += mesh
|
this.meshes += mesh
|
||||||
|
@ -72,11 +72,11 @@ class ChunkMeshingQueue(
|
|||||||
items += item
|
items += item
|
||||||
}
|
}
|
||||||
unlock()
|
unlock()
|
||||||
val camera = renderer.cameraChunkPosition
|
val camera = renderer.cameraSectionPosition
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
val distance = abs(item.chunkPosition.x - camera.x) + abs(item.chunkPosition.z - camera.z)
|
val distance = abs(item.position.x - camera.x) + abs(item.position.z - camera.z) // TODO: Check y?
|
||||||
val runnable = HeavyPoolRunnable(if (distance < 1) ThreadPool.HIGH else ThreadPool.LOW, interruptable = true)
|
val runnable = HeavyPoolRunnable(if (distance < 1) ThreadPool.HIGH else ThreadPool.LOW, interruptable = true)
|
||||||
val task = MeshPrepareTask(item.chunkPosition, item.sectionHeight, runnable)
|
val task = MeshPrepareTask(item.position, runnable)
|
||||||
task.runnable.runnable = Runnable { renderer.mesher.tryMesh(item, task, task.runnable) }
|
task.runnable.runnable = Runnable { renderer.mesher.tryMesh(item, task, task.runnable) }
|
||||||
tasks += task
|
tasks += task
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ class ChunkMeshingQueue(
|
|||||||
fun remove(chunkPosition: ChunkPosition) {
|
fun remove(chunkPosition: ChunkPosition) {
|
||||||
val remove: MutableSet<WorldQueueItem> = mutableSetOf()
|
val remove: MutableSet<WorldQueueItem> = mutableSetOf()
|
||||||
queue.removeAll {
|
queue.removeAll {
|
||||||
if (it.chunkPosition != chunkPosition) {
|
if (it.position.chunkPosition != chunkPosition) {
|
||||||
return@removeAll false
|
return@removeAll false
|
||||||
}
|
}
|
||||||
remove += it
|
remove += it
|
||||||
@ -100,7 +100,7 @@ class ChunkMeshingQueue(
|
|||||||
if (lock) lock()
|
if (lock) lock()
|
||||||
val remove: MutableSet<WorldQueueItem> = mutableSetOf()
|
val remove: MutableSet<WorldQueueItem> = mutableSetOf()
|
||||||
queue.removeAll {
|
queue.removeAll {
|
||||||
if (renderer.visibilityGraph.isChunkVisible(it.chunkPosition)) {
|
if (renderer.visibilityGraph.isChunkVisible(it.position.chunkPosition)) {
|
||||||
return@removeAll false
|
return@removeAll false
|
||||||
}
|
}
|
||||||
remove += it
|
remove += it
|
||||||
@ -153,7 +153,7 @@ class ChunkMeshingQueue(
|
|||||||
if (set.remove(item)) {
|
if (set.remove(item)) {
|
||||||
queue -= item
|
queue -= item
|
||||||
}
|
}
|
||||||
if (item.chunkPosition == renderer.cameraChunkPosition) {
|
if (item.position.chunkPosition == renderer.cameraSectionPosition.chunkPosition) {
|
||||||
queue.add(0, item)
|
queue.add(0, item)
|
||||||
} else {
|
} else {
|
||||||
queue += item
|
queue += item
|
||||||
|
@ -13,31 +13,26 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.chunk.queue.meshing
|
package de.bixilon.minosoft.gui.rendering.chunk.queue.meshing
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
||||||
|
|
||||||
class ChunkQueueComparator : Comparator<WorldQueueItem> {
|
class ChunkQueueComparator : Comparator<WorldQueueItem> {
|
||||||
private var sort = 1
|
private var sort = 1
|
||||||
private var position: ChunkPosition = ChunkPosition.EMPTY
|
private var position = SectionPosition()
|
||||||
private var height = 0
|
|
||||||
|
|
||||||
|
|
||||||
fun update(renderer: ChunkRenderer) {
|
fun update(renderer: ChunkRenderer) {
|
||||||
if (this.position == renderer.cameraChunkPosition && this.height == renderer.cameraSectionHeight) return
|
if (this.position == renderer.cameraSectionPosition) return
|
||||||
this.position = renderer.cameraChunkPosition
|
this.position = renderer.cameraSectionPosition
|
||||||
this.height = renderer.cameraSectionHeight
|
|
||||||
sort++
|
sort++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDistance(item: WorldQueueItem): Int {
|
private fun getDistance(item: WorldQueueItem): Int {
|
||||||
if (item.sort == this.sort) return item.distance
|
if (item.sort == this.sort) return item.distance
|
||||||
|
|
||||||
val array = item.sectionPosition.array
|
val position = item.position
|
||||||
val x = array[0] - position.x
|
val distance = (position - this.position).length2()
|
||||||
val y = array[1] - height
|
|
||||||
val z = array[2] - position.z
|
|
||||||
val distance = (x * x + y * y + z * z)
|
|
||||||
|
|
||||||
item.distance = distance
|
item.distance = distance
|
||||||
item.sort = sort
|
item.sort = sort
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.chunk.queue.meshing.tasks
|
package de.bixilon.minosoft.gui.rendering.chunk.queue.meshing.tasks
|
||||||
|
|
||||||
import de.bixilon.kutil.concurrent.pool.runnable.HeavyPoolRunnable
|
import de.bixilon.kutil.concurrent.pool.runnable.HeavyPoolRunnable
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
|
|
||||||
class MeshPrepareTask(
|
class MeshPrepareTask(
|
||||||
val chunkPosition: ChunkPosition,
|
val position: SectionPosition,
|
||||||
val sectionHeight: Int,
|
|
||||||
val runnable: HeavyPoolRunnable,
|
val runnable: HeavyPoolRunnable,
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.queue.meshing.tasks
|
|||||||
import de.bixilon.kutil.concurrent.lock.RWLock
|
import de.bixilon.kutil.concurrent.lock.RWLock
|
||||||
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
|
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
|
||||||
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
import de.bixilon.minosoft.data.world.positions.ChunkPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
||||||
|
|
||||||
class MeshPrepareTaskManager(
|
class MeshPrepareTaskManager(
|
||||||
@ -58,17 +58,17 @@ class MeshPrepareTaskManager(
|
|||||||
fun interrupt(position: ChunkPosition) {
|
fun interrupt(position: ChunkPosition) {
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
for (task in tasks) {
|
for (task in tasks) {
|
||||||
if (task.chunkPosition == position) {
|
if (task.position.chunkPosition == position) {
|
||||||
task.runnable.interrupt()
|
task.runnable.interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock.release()
|
lock.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun interrupt(position: ChunkPosition, height: SectionHeight) {
|
fun interrupt(position: SectionPosition) {
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
for (task in tasks) {
|
for (task in tasks) {
|
||||||
if (task.chunkPosition == position && task.sectionHeight == height) {
|
if (task.position == position) {
|
||||||
task.runnable.interrupt()
|
task.runnable.interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ class MeshPrepareTaskManager(
|
|||||||
fun cleanup() {
|
fun cleanup() {
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
for (task in tasks) {
|
for (task in tasks) {
|
||||||
if (!renderer.visibilityGraph.isChunkVisible(task.chunkPosition)) {
|
if (!renderer.visibilityGraph.isChunkVisible(task.position.chunkPosition)) {
|
||||||
task.runnable.interrupt()
|
task.runnable.interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
|||||||
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
import de.bixilon.minosoft.data.world.positions.SectionHeight
|
||||||
|
import de.bixilon.minosoft.data.world.positions.SectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderingStates
|
import de.bixilon.minosoft.gui.rendering.RenderingStates
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.ChunkRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
import de.bixilon.minosoft.gui.rendering.chunk.WorldQueueItem
|
||||||
@ -32,15 +33,16 @@ class ChunkQueueMaster(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
private fun queue(section: ChunkSection, chunk: Chunk, force: Boolean): Boolean {
|
private fun queue(section: ChunkSection, chunk: Chunk, force: Boolean): Boolean {
|
||||||
|
val position = SectionPosition.of(chunk.position, section.height)
|
||||||
if (section.blocks.isEmpty) {
|
if (section.blocks.isEmpty) {
|
||||||
renderer.unload(QueuePosition(chunk.position, section.height))
|
renderer.unload(QueuePosition(position))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val visible = force || renderer.visibilityGraph.isSectionVisible(chunk.position, section.height, section.blocks.minPosition, section.blocks.maxPosition, true)
|
val visible = force || renderer.visibilityGraph.isSectionVisible(position, section.blocks.minPosition, section.blocks.maxPosition, true)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
val center = CHUNK_CENTER + BlockPosition.of(chunk.position, section.height)
|
val center = CHUNK_CENTER + BlockPosition.of(chunk.position, section.height)
|
||||||
val item = WorldQueueItem(chunk.position, section.height, chunk, section, center)
|
val item = WorldQueueItem(position, chunk, section, center)
|
||||||
renderer.meshingQueue.queue(item)
|
renderer.meshingQueue.queue(item)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,8 @@ class BlockPositionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `correct negative y large`() {
|
fun `correct negative y large`() {
|
||||||
val position = BlockPosition(-2048, 0xF, 0xF)
|
val position = BlockPosition(1234, -2048, 0xF)
|
||||||
assertEquals(position.x, -2048)
|
assertEquals(position.y, -2048)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.data.world.positions
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class SectionPositionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `init correct min`() {
|
||||||
|
val position = SectionPosition(-1875000, -128, -1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `init correct max`() {
|
||||||
|
val position = SectionPosition(1875000, 127, 1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `init badly`() {
|
||||||
|
assertThrows<AssertionError> { SectionPosition(-1875001, 128, -1875001) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive x`() {
|
||||||
|
val position = SectionPosition(2, 0xF, 0xF)
|
||||||
|
assertEquals(position.x, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive x large`() {
|
||||||
|
val position = SectionPosition(1875000, 0xF, 0xF)
|
||||||
|
assertEquals(position.x, 1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative x`() {
|
||||||
|
val position = SectionPosition(-2, 0xF, 0xF)
|
||||||
|
assertEquals(position.x, -2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative x large`() {
|
||||||
|
val position = SectionPosition(-1875000, 0xF, 0xF)
|
||||||
|
assertEquals(position.x, -1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus x`() {
|
||||||
|
val position = SectionPosition(2, 0xF, 0xF)
|
||||||
|
assertEquals(position.plusX().x, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus 2 x`() {
|
||||||
|
val position = SectionPosition(2, 0xF, 0xF)
|
||||||
|
assertEquals(position.plusX(2).x, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct minus x`() {
|
||||||
|
val position = SectionPosition(2, 0xF, 0xF)
|
||||||
|
assertEquals(position.minusX().x, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative y`() {
|
||||||
|
val position = SectionPosition(0xF, -4, 0xF)
|
||||||
|
assertEquals(position.y, -4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative y large`() {
|
||||||
|
val position = SectionPosition(123, -128, 0xF)
|
||||||
|
assertEquals(position.y, -128)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive y`() {
|
||||||
|
val position = SectionPosition(0xF, 100, 0xF)
|
||||||
|
assertEquals(position.y, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive y large`() {
|
||||||
|
val position = SectionPosition(0xF, 127, 0xF)
|
||||||
|
assertEquals(position.y, 127)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus y`() {
|
||||||
|
val position = SectionPosition(0xF, 2, 0xF)
|
||||||
|
assertEquals(position.plusY().y, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus 2 y`() {
|
||||||
|
val position = SectionPosition(0xF, 2, 0xF)
|
||||||
|
assertEquals(position.plusY(2).y, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct minus y`() {
|
||||||
|
val position = SectionPosition(0xF, 2, 0xF)
|
||||||
|
assertEquals(position.minusY().y, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive z`() {
|
||||||
|
val position = SectionPosition(0xF, 0xF, 4)
|
||||||
|
assertEquals(position.z, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct positive z large`() {
|
||||||
|
val position = SectionPosition(0, 0, 1875000)
|
||||||
|
assertEquals(position.z, 1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative z`() {
|
||||||
|
val position = SectionPosition(0xF, 0xF, -4)
|
||||||
|
assertEquals(position.z, -4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct negative z large`() {
|
||||||
|
val position = SectionPosition(0, 0, -1875000)
|
||||||
|
assertEquals(position.z, -1875000)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus z`() {
|
||||||
|
val position = SectionPosition(0xF, 0xF, 2)
|
||||||
|
assertEquals(position.plusZ().z, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct plus 2 z`() {
|
||||||
|
val position = SectionPosition(0xF, 0xF, 2)
|
||||||
|
assertEquals(position.plusZ(2).z, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correct minus z`() {
|
||||||
|
val position = SectionPosition(0xF, 0xF, 2)
|
||||||
|
assertEquals(position.minusZ().z, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unary minus`() {
|
||||||
|
val position = -SectionPosition(2, 2, 2)
|
||||||
|
assertEquals(position.x, -2)
|
||||||
|
assertEquals(position.y, -2)
|
||||||
|
assertEquals(position.z, -2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unary plus`() {
|
||||||
|
val position = +SectionPosition(2, 2, 2)
|
||||||
|
assertEquals(position.x, 2)
|
||||||
|
assertEquals(position.y, 2)
|
||||||
|
assertEquals(position.z, 2)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user