Optimize cell view

This commit is contained in:
DBotThePony 2023-09-03 17:40:31 +07:00
parent e459db83b2
commit e436864e12
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 54 additions and 52 deletions

View File

@ -2,10 +2,10 @@ package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.world.api.BackgroundView import ru.dbotthepony.kstarbound.world.api.BackgroundView
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.ForegroundView import ru.dbotthepony.kstarbound.world.api.ForegroundView
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.kvector.arrays.Object2DArray
/** /**
* Предоставляет доступ к чанку и его соседям * Предоставляет доступ к чанку и его соседям
@ -16,54 +16,56 @@ import ru.dbotthepony.kstarbound.world.api.IChunkCell
*/ */
class CellView( class CellView(
override val pos: ChunkPos, override val pos: ChunkPos,
val center: IChunk?,
val right: IChunk?,
val top: IChunk?,
val topRight: IChunk?,
val topLeft: IChunk?,
val left: IChunk?, val left: IChunk?,
val bottom: IChunk?, val center: IChunk?,
val right: IChunk?,
val topRight: IChunk?,
val top: IChunk?,
val topLeft: IChunk?,
val bottomLeft: IChunk?, val bottomLeft: IChunk?,
val bottom: IChunk?,
val bottomRight: IChunk?, val bottomRight: IChunk?,
) : IChunk { ) : IChunk {
val backgroundView = BackgroundView(this) val backgroundView = BackgroundView(this)
val foregroundView = ForegroundView(this) val foregroundView = ForegroundView(this)
override fun getCell(x: Int, y: Int): IChunkCell { override fun getCell(x: Int, y: Int): IChunkCell {
if (x in 0 ..CHUNK_SIZE_FF) { val ix = x + CHUNK_SIZE
if (y in 0 ..CHUNK_SIZE_FF) { val iy = y + CHUNK_SIZE
return center?.getCell(x, y) ?: IChunkCell.Companion
}
if (y < 0) { if (ix in 0 until CHUNK_SIZE * 3 - 1 && iy in 0 until CHUNK_SIZE * 3 - 1) {
return bottom?.getCell(x, y + CHUNK_SIZE) ?: IChunkCell.Companion return indices[ix, iy].invoke(this) ?: IChunkCell.Companion
} else { } else {
return top?.getCell(x, y - CHUNK_SIZE) ?: IChunkCell.Companion return IChunkCell.Companion
}
}
companion object {
private val indices = Object2DArray.nulls<(CellView) -> IChunkCell?>(CHUNK_SIZE * 3, CHUNK_SIZE * 3) as Object2DArray<(CellView) -> IChunkCell?>
private fun put(half: (CellView) -> IChunk?, x: Int, y: Int) {
for (ix in 0 until CHUNK_SIZE) {
for (iy in 0 until CHUNK_SIZE) {
indices[x + ix, y + iy] = { half(it)?.getCell(ix, iy) }
}
} }
} }
if (x < 0) { init {
if (y in 0 ..CHUNK_SIZE_FF) { put(CellView::bottomLeft, 0, 0)
return left?.getCell(x + CHUNK_SIZE, y) ?: IChunkCell.Companion put(CellView::bottom, CHUNK_SIZE, 0)
} put(CellView::bottomRight, CHUNK_SIZE * 2, 0)
if (y < 0) { put(CellView::left, 0, CHUNK_SIZE)
return bottomLeft?.getCell(x + CHUNK_SIZE, y + CHUNK_SIZE) ?: IChunkCell.Companion put(CellView::center, CHUNK_SIZE, CHUNK_SIZE)
} else { put(CellView::right, CHUNK_SIZE * 2, CHUNK_SIZE)
return topLeft?.getCell(x + CHUNK_SIZE, y - CHUNK_SIZE) ?: IChunkCell.Companion
}
} else {
if (y in 0 ..CHUNK_SIZE_FF) {
return right?.getCell(x - CHUNK_SIZE, y) ?: IChunkCell.Companion
}
if (y < 0) { put(CellView::topLeft, 0, CHUNK_SIZE * 2)
return bottomRight?.getCell(x - CHUNK_SIZE, y + CHUNK_SIZE) ?: IChunkCell.Companion put(CellView::top, CHUNK_SIZE, CHUNK_SIZE * 2)
} else { put(CellView::topRight, CHUNK_SIZE * 2, CHUNK_SIZE * 2)
return topRight?.getCell(x - CHUNK_SIZE, y - CHUNK_SIZE) ?: IChunkCell.Companion
}
} }
} }
} }

View File

@ -8,7 +8,7 @@ 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.BackgroundView import ru.dbotthepony.kstarbound.world.api.BackgroundView
import ru.dbotthepony.kstarbound.world.api.CHUNK_SHIFT 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
@ -261,7 +261,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
for (y in 0 .. CHUNK_SIZE_FF) { for (y in 0 .. CHUNK_SIZE_FF) {
for (x in 0..CHUNK_SIZE_FF) { for (x in 0..CHUNK_SIZE_FF) {
if (!seen[x or (y shl CHUNK_SHIFT)] && cells[x, y].foreground.material != null) { if (!seen[x or (y shl CHUNK_SIZE_BITS)] && cells[x, y].foreground.material != null) {
val depthFirst = RectTileFlooderDepthFirst(cells, seen, x, y) val depthFirst = RectTileFlooderDepthFirst(cells, seen, x, y)
val sizeFirst = RectTileFlooderSizeFirst(cells, seen, x, y) val sizeFirst = RectTileFlooderSizeFirst(cells, seen, x, y)
val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue
import ru.dbotthepony.kstarbound.world.api.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
import ru.dbotthepony.kvector.api.IStruct2d import ru.dbotthepony.kvector.api.IStruct2d
import ru.dbotthepony.kvector.api.IStruct2i import ru.dbotthepony.kvector.api.IStruct2i
@ -32,17 +32,17 @@ 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 firstBlock get() = Vector2i(tileX, tileY)
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SHIFT) - 1, ((y + 1) shl CHUNK_SHIFT) - 1) val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SIZE_BITS) - 1, ((y + 1) shl CHUNK_SIZE_BITS) - 1)
/** /**
* Координата тайла на 0 позиции по оси X внутри чанка в мире * Координата тайла на 0 позиции по оси X внутри чанка в мире
*/ */
val tileX: Int get() = x shl CHUNK_SHIFT val tileX: Int get() = x shl CHUNK_SIZE_BITS
/** /**
* Координата тайла на 0 позиции по оси Y внутри чанка в мире * Координата тайла на 0 позиции по оси Y внутри чанка в мире
*/ */
val tileY: Int get() = y shl CHUNK_SHIFT val tileY: Int get() = y shl CHUNK_SIZE_BITS
val top: ChunkPos val top: ChunkPos
get() { get() {
@ -184,10 +184,10 @@ class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
fun tileToChunkComponent(comp: Int): Int { fun tileToChunkComponent(comp: Int): Int {
if (comp < 0) { if (comp < 0) {
return -(comp.absoluteValue shr CHUNK_SHIFT) - 1 return -(comp.absoluteValue shr CHUNK_SIZE_BITS) - 1
} }
return comp shr CHUNK_SHIFT return comp shr CHUNK_SIZE_BITS
} }
} }
} }

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.world.api package ru.dbotthepony.kstarbound.world.api
const val CHUNK_SHIFT = 5 const val CHUNK_SIZE_BITS = 5
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 32 const val CHUNK_SIZE = 1 shl CHUNK_SIZE_BITS // 32
const val CHUNK_SIZE_FF = CHUNK_SIZE - 1 const val CHUNK_SIZE_FF = CHUNK_SIZE - 1
const val CHUNK_SIZEf = CHUNK_SIZE.toFloat() const val CHUNK_SIZEf = CHUNK_SIZE.toFloat()
const val CHUNK_SIZEd = CHUNK_SIZE.toDouble() const val CHUNK_SIZEd = CHUNK_SIZE.toDouble()

View File

@ -17,7 +17,7 @@ interface IChunk {
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции * Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
*/ */
fun randomLongFor(x: Int, y: Int): Long { fun randomLongFor(x: Int, y: Int): Long {
var long = (x or (pos.x shl CHUNK_SHIFT)) * 738548L + (y or (pos.y shl CHUNK_SHIFT)) * 2191293543L var long = (x or (pos.x shl CHUNK_SIZE_BITS)) * 738548L + (y or (pos.y shl CHUNK_SIZE_BITS)) * 2191293543L
long = long xor 8339437585692L long = long xor 8339437585692L
long = (long ushr 4) or (long shl 52) long = (long ushr 4) or (long shl 52)
long *= 7848344324L long *= 7848344324L

View File

@ -1,6 +1,6 @@
package ru.dbotthepony.kstarbound.world.phys package ru.dbotthepony.kstarbound.world.phys
import ru.dbotthepony.kstarbound.world.api.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.api.IChunkCell import ru.dbotthepony.kstarbound.world.api.IChunkCell
import ru.dbotthepony.kvector.arrays.Object2DArray import ru.dbotthepony.kvector.arrays.Object2DArray
@ -24,7 +24,7 @@ class RectTileFlooderDepthFirst(
return false return false
} }
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x, y].foreground.material != null return !seen[x or (y shl CHUNK_SIZE_BITS)] && tiles[x, y].foreground.material != null
} }
init { init {
@ -169,7 +169,7 @@ class RectTileFlooderDepthFirst(
fun markSeen() { fun markSeen() {
for (x in mins.x .. maxs.x) { for (x in mins.x .. maxs.x) {
for (y in mins.y .. maxs.y) { for (y in mins.y .. maxs.y) {
seen[x or (y shl CHUNK_SHIFT)] = true seen[x or (y shl CHUNK_SIZE_BITS)] = true
} }
} }
} }

View File

@ -1,6 +1,6 @@
package ru.dbotthepony.kstarbound.world.phys package ru.dbotthepony.kstarbound.world.phys
import ru.dbotthepony.kstarbound.world.api.CHUNK_SHIFT import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.api.IChunkCell import ru.dbotthepony.kstarbound.world.api.IChunkCell
import ru.dbotthepony.kvector.arrays.Object2DArray import ru.dbotthepony.kvector.arrays.Object2DArray
@ -24,7 +24,7 @@ class RectTileFlooderSizeFirst(
return false return false
} }
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x, y].foreground.material != null return !seen[x or (y shl CHUNK_SIZE_BITS)] && tiles[x, y].foreground.material != null
} }
private var widthPositive = 0 private var widthPositive = 0
@ -138,7 +138,7 @@ class RectTileFlooderSizeFirst(
fun markSeen() { fun markSeen() {
for (x in mins.x .. maxs.x) { for (x in mins.x .. maxs.x) {
for (y in mins.y .. maxs.y) { for (y in mins.y .. maxs.y) {
seen[x or (y shl CHUNK_SHIFT)] = true seen[x or (y shl CHUNK_SIZE_BITS)] = true
} }
} }
} }