Circular aware chunk compilers
This commit is contained in:
parent
0657ee8ef7
commit
3647643351
@ -18,7 +18,6 @@ import ru.dbotthepony.kstarbound.world.*
|
|||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEf
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEf
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileAccess
|
|
||||||
import ru.dbotthepony.kstarbound.world.api.ITileChunk
|
import ru.dbotthepony.kstarbound.world.api.ITileChunk
|
||||||
import ru.dbotthepony.kstarbound.world.entities.Entity
|
import ru.dbotthepony.kstarbound.world.entities.Entity
|
||||||
import ru.dbotthepony.kvector.arrays.Matrix4fStack
|
import ru.dbotthepony.kvector.arrays.Matrix4fStack
|
||||||
@ -29,7 +28,6 @@ import ru.dbotthepony.kvector.vector.Vector2f
|
|||||||
import ru.dbotthepony.kvector.vector.Vector3f
|
import ru.dbotthepony.kvector.vector.Vector3f
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.function.IntSupplier
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Псевдо zPos у фоновых тайлов
|
* Псевдо zPos у фоновых тайлов
|
||||||
@ -43,14 +41,13 @@ const val Z_LEVEL_LIQUID = 10000
|
|||||||
class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, ClientChunk>(world, pos), Closeable {
|
class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, ClientChunk>(world, pos), Closeable {
|
||||||
val state: GLStateTracker get() = world.client.gl
|
val state: GLStateTracker get() = world.client.gl
|
||||||
|
|
||||||
private inner class TileLayerRenderer(private val view: () -> ITileChunk, private val isBackground: Boolean) : AutoCloseable {
|
private inner class TileLayerRenderer(private val view: ITileChunk, private val isBackground: Boolean) : AutoCloseable {
|
||||||
private val layers = TileLayerList()
|
private val layers = TileLayerList()
|
||||||
val bakedMeshes = LinkedList<Pair<ConfiguredStaticMesh, Int>>()
|
val bakedMeshes = LinkedList<Pair<ConfiguredStaticMesh, Int>>()
|
||||||
var isDirty = true
|
var isDirty = true
|
||||||
|
|
||||||
fun bake() {
|
fun bake() {
|
||||||
isDirty = false
|
isDirty = false
|
||||||
val view = view()
|
|
||||||
|
|
||||||
if (state.isSameThread()) {
|
if (state.isSameThread()) {
|
||||||
for (mesh in bakedMeshes) {
|
for (mesh in bakedMeshes) {
|
||||||
@ -63,6 +60,8 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
|
|||||||
layers.clear()
|
layers.clear()
|
||||||
|
|
||||||
for ((pos, tile) in view.iterateTiles()) {
|
for ((pos, tile) in view.iterateTiles()) {
|
||||||
|
if (!world.chunkMap.inBounds(this@ClientChunk.pos.firstTile + pos)) continue
|
||||||
|
|
||||||
val material = tile.material
|
val material = tile.material
|
||||||
|
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
@ -78,9 +77,9 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadRenderers() {
|
fun loadRenderers() {
|
||||||
val view = view()
|
for ((pos, tile) in view.iterateTiles()) {
|
||||||
|
if (!world.chunkMap.inBounds(this@ClientChunk.pos.firstTile + pos)) continue
|
||||||
|
|
||||||
for ((_, tile) in view.iterateTiles()) {
|
|
||||||
val material = tile.material
|
val material = tile.material
|
||||||
val modifier = tile.modifier
|
val modifier = tile.modifier
|
||||||
|
|
||||||
@ -154,8 +153,8 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
|
|||||||
val debugCollisions get() = world.client.settings.debugCollisions
|
val debugCollisions get() = world.client.settings.debugCollisions
|
||||||
val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd)
|
val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd)
|
||||||
|
|
||||||
private val foregroundRenderer = TileLayerRenderer({ world.getView(pos).foregroundView }, isBackground = false)
|
private val foregroundRenderer = TileLayerRenderer(localizedForegroundView, isBackground = false)
|
||||||
private val backgroundRenderer = TileLayerRenderer({ world.getView(pos).backgroundView }, isBackground = true)
|
private val backgroundRenderer = TileLayerRenderer(localizedBackgroundView, isBackground = true)
|
||||||
|
|
||||||
override fun foregroundChanges() {
|
override fun foregroundChanges() {
|
||||||
super.foregroundChanges()
|
super.foregroundChanges()
|
||||||
|
@ -8,11 +8,13 @@ import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
|
|||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
import ru.dbotthepony.kstarbound.world.api.BackgroundChunkView
|
import ru.dbotthepony.kstarbound.world.api.BackgroundChunkView
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.BackgroundLocalizedView
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
|
||||||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZEd
|
||||||
import ru.dbotthepony.kstarbound.world.api.ForegroundChunkView
|
import ru.dbotthepony.kstarbound.world.api.ForegroundChunkView
|
||||||
|
import ru.dbotthepony.kstarbound.world.api.ForegroundLocalizedView
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunk
|
import ru.dbotthepony.kstarbound.world.api.IChunk
|
||||||
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
import ru.dbotthepony.kstarbound.world.api.IChunkCell
|
||||||
import ru.dbotthepony.kstarbound.world.api.ILiquidState
|
import ru.dbotthepony.kstarbound.world.api.ILiquidState
|
||||||
@ -101,6 +103,9 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
val backgroundView = BackgroundChunkView(this)
|
val backgroundView = BackgroundChunkView(this)
|
||||||
val foregroundView = ForegroundChunkView(this)
|
val foregroundView = ForegroundChunkView(this)
|
||||||
|
|
||||||
|
val localizedBackgroundView = BackgroundLocalizedView(pos, world.chunkMap)
|
||||||
|
val localizedForegroundView = ForegroundLocalizedView(pos, world.chunkMap)
|
||||||
|
|
||||||
override fun getCell(x: Int, y: Int): IChunkCell {
|
override fun getCell(x: Int, y: Int): IChunkCell {
|
||||||
return cells[x, y]
|
return cells[x, y]
|
||||||
}
|
}
|
||||||
@ -250,7 +255,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val body = world.physics.createBody(BodyDef(
|
private val body = world.physics.createBody(BodyDef(
|
||||||
position = pos.firstBlock.toDoubleVector(),
|
position = pos.firstTile.toDoubleVector(),
|
||||||
userData = this
|
userData = this
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ private fun circulate(value: Int, bounds: Int): Int {
|
|||||||
class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
|
class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
|
||||||
constructor(pos: IStruct2i) : this(pos.component1(), pos.component2())
|
constructor(pos: IStruct2i) : this(pos.component1(), pos.component2())
|
||||||
|
|
||||||
val firstBlock get() = Vector2i(tileX, tileY)
|
val firstTile get() = Vector2i(tileX, tileY)
|
||||||
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SIZE_BITS) - 1, ((y + 1) shl CHUNK_SIZE_BITS) - 1)
|
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SIZE_BITS) - 1, ((y + 1) shl CHUNK_SIZE_BITS) - 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +41,8 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
abstract fun chunk(value: Int): Int
|
abstract fun chunk(value: Int): Int
|
||||||
abstract fun chunk(value: Double): Double
|
abstract fun chunk(value: Double): Double
|
||||||
|
|
||||||
|
abstract fun inBounds(value: Int): Boolean
|
||||||
|
|
||||||
protected fun positiveModulo(a: Int, b: Int): Int {
|
protected fun positiveModulo(a: Int, b: Int): Int {
|
||||||
val result = a % b
|
val result = a % b
|
||||||
return if (result < 0) result + b else result
|
return if (result < 0) result + b else result
|
||||||
@ -63,9 +65,15 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
override fun cell(value: Float): Float = value
|
override fun cell(value: Float): Float = value
|
||||||
override fun chunk(value: Int): Int = value
|
override fun chunk(value: Int): Int = value
|
||||||
override fun chunk(value: Double): Double = value
|
override fun chunk(value: Double): Double = value
|
||||||
|
|
||||||
|
override fun inBounds(value: Int) = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoordinatesWrapper(private val cell: Int, private val chunk: Int) : AbstractCoordinatesWrapper() {
|
class CoordinatesWrapper(private val cell: Int, private val chunk: Int) : AbstractCoordinatesWrapper() {
|
||||||
|
override fun inBounds(value: Int): Boolean {
|
||||||
|
return value in 0 until cell
|
||||||
|
}
|
||||||
|
|
||||||
override fun cell(value: Int): Int {
|
override fun cell(value: Int): Int {
|
||||||
return positiveModulo(value, cell)
|
return positiveModulo(value, cell)
|
||||||
}
|
}
|
||||||
@ -88,6 +96,10 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CoordinatesClamper(private val cell: Int, private val chunk: Int) : AbstractCoordinatesWrapper() {
|
class CoordinatesClamper(private val cell: Int, private val chunk: Int) : AbstractCoordinatesWrapper() {
|
||||||
|
override fun inBounds(value: Int): Boolean {
|
||||||
|
return value in 0 until cell
|
||||||
|
}
|
||||||
|
|
||||||
override fun cell(value: Int): Int {
|
override fun cell(value: Int): Int {
|
||||||
return value.coerceIn(0, cell - 1)
|
return value.coerceIn(0, cell - 1)
|
||||||
}
|
}
|
||||||
@ -113,6 +125,9 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
abstract val x: AbstractCoordinatesWrapper
|
abstract val x: AbstractCoordinatesWrapper
|
||||||
abstract val y: AbstractCoordinatesWrapper
|
abstract val y: AbstractCoordinatesWrapper
|
||||||
|
|
||||||
|
fun inBounds(x: Int, y: Int) = this.x.inBounds(x) && this.y.inBounds(y)
|
||||||
|
fun inBounds(value: IStruct2i) = this.x.inBounds(value.component1()) && this.y.inBounds(value.component2())
|
||||||
|
|
||||||
val backgroundView = BackgroundAccessView(this)
|
val backgroundView = BackgroundAccessView(this)
|
||||||
val foregroundView = ForegroundAccessView(this)
|
val foregroundView = ForegroundAccessView(this)
|
||||||
|
|
||||||
@ -196,8 +211,9 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getCell(x: Int, y: Int): IChunkCell {
|
override fun getCell(x: Int, y: Int): IChunkCell {
|
||||||
if (x < 0 || y < 0) return IChunkCell.Companion
|
val ix = this.x.cell(x)
|
||||||
return get(x ushr CHUNK_SIZE_BITS, y ushr CHUNK_SIZE_BITS)?.getCell(x and CHUNK_SIZE_MASK, y and CHUNK_SIZE_MASK) ?: IChunkCell.Companion
|
val iy = this.y.cell(y)
|
||||||
|
return get(ix ushr CHUNK_SIZE_BITS, iy ushr CHUNK_SIZE_BITS)?.getCell(ix and CHUNK_SIZE_MASK, iy and CHUNK_SIZE_MASK) ?: IChunkCell.Companion
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(x: Int, y: Int, chunk: ChunkType) {
|
override fun set(x: Int, y: Int, chunk: ChunkType) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.api
|
package ru.dbotthepony.kstarbound.world.api
|
||||||
|
|
||||||
|
import ru.dbotthepony.kstarbound.world.ChunkPos
|
||||||
import ru.dbotthepony.kvector.api.IStruct2i
|
import ru.dbotthepony.kvector.api.IStruct2i
|
||||||
|
|
||||||
// for getting tiles directly, avoiding manual layer specification
|
// for getting tiles directly, avoiding manual layer specification
|
||||||
@ -23,6 +24,18 @@ class BackgroundChunkView(private val parent: IChunk) : ITileChunk, IChunk by pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ForegroundLocalizedView(override val pos: ChunkPos, private val parent: ICellAccess) : ITileChunk, ICellAccess by parent {
|
||||||
|
override fun getTile(x: Int, y: Int): ITileState {
|
||||||
|
return parent.getCell(pos.tileX + x, pos.tileY + y).foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BackgroundLocalizedView(override val pos: ChunkPos, private val parent: ICellAccess) : ITileChunk, ICellAccess by parent {
|
||||||
|
override fun getTile(x: Int, y: Int): ITileState {
|
||||||
|
return parent.getCell(pos.tileX + x, pos.tileY + y).background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ForegroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent {
|
class ForegroundAccessView(private val parent: ICellAccess) : ITileAccess, ICellAccess by parent {
|
||||||
override fun getTile(x: Int, y: Int): ITileState {
|
override fun getTile(x: Int, y: Int): ITileState {
|
||||||
return parent.getCell(x, y).foreground
|
return parent.getCell(x, y).foreground
|
||||||
|
Loading…
Reference in New Issue
Block a user