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.CHUNK_SIZE
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_FF
import ru.dbotthepony.kstarbound.world.api.ForegroundView
import ru.dbotthepony.kstarbound.world.api.IChunk
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(
override val pos: ChunkPos,
val center: IChunk?,
val right: IChunk?,
val top: IChunk?,
val topRight: IChunk?,
val topLeft: 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 bottom: IChunk?,
val bottomRight: IChunk?,
) : IChunk {
val backgroundView = BackgroundView(this)
val foregroundView = ForegroundView(this)
override fun getCell(x: Int, y: Int): IChunkCell {
if (x in 0 ..CHUNK_SIZE_FF) {
if (y in 0 ..CHUNK_SIZE_FF) {
return center?.getCell(x, y) ?: IChunkCell.Companion
}
val ix = x + CHUNK_SIZE
val iy = y + CHUNK_SIZE
if (y < 0) {
return bottom?.getCell(x, y + CHUNK_SIZE) ?: IChunkCell.Companion
} else {
return top?.getCell(x, y - CHUNK_SIZE) ?: IChunkCell.Companion
if (ix in 0 until CHUNK_SIZE * 3 - 1 && iy in 0 until CHUNK_SIZE * 3 - 1) {
return indices[ix, iy].invoke(this) ?: IChunkCell.Companion
} else {
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) {
if (y in 0 ..CHUNK_SIZE_FF) {
return left?.getCell(x + CHUNK_SIZE, y) ?: IChunkCell.Companion
}
init {
put(CellView::bottomLeft, 0, 0)
put(CellView::bottom, CHUNK_SIZE, 0)
put(CellView::bottomRight, CHUNK_SIZE * 2, 0)
if (y < 0) {
return bottomLeft?.getCell(x + CHUNK_SIZE, y + CHUNK_SIZE) ?: IChunkCell.Companion
} else {
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
}
put(CellView::left, 0, CHUNK_SIZE)
put(CellView::center, CHUNK_SIZE, CHUNK_SIZE)
put(CellView::right, CHUNK_SIZE * 2, CHUNK_SIZE)
if (y < 0) {
return bottomRight?.getCell(x - CHUNK_SIZE, y + CHUNK_SIZE) ?: IChunkCell.Companion
} else {
return topRight?.getCell(x - CHUNK_SIZE, y - CHUNK_SIZE) ?: IChunkCell.Companion
}
put(CellView::topLeft, 0, CHUNK_SIZE * 2)
put(CellView::top, CHUNK_SIZE, CHUNK_SIZE * 2)
put(CellView::topRight, CHUNK_SIZE * 2, CHUNK_SIZE * 2)
}
}
}

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.TileDefinition
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_FF
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 (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 sizeFirst = RectTileFlooderSizeFirst(cells, seen, x, y)
val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.world
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.kvector.api.IStruct2d
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())
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 внутри чанка в мире
*/
val tileX: Int get() = x shl CHUNK_SHIFT
val tileX: Int get() = x shl CHUNK_SIZE_BITS
/**
* Координата тайла на 0 позиции по оси Y внутри чанка в мире
*/
val tileY: Int get() = y shl CHUNK_SHIFT
val tileY: Int get() = y shl CHUNK_SIZE_BITS
val top: ChunkPos
get() {
@ -184,10 +184,10 @@ class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
fun tileToChunkComponent(comp: Int): Int {
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
const val CHUNK_SHIFT = 5
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 32
const val CHUNK_SIZE_BITS = 5
const val CHUNK_SIZE = 1 shl CHUNK_SIZE_BITS // 32
const val CHUNK_SIZE_FF = CHUNK_SIZE - 1
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 {
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 ushr 4) or (long shl 52)
long *= 7848344324L

View File

@ -1,6 +1,6 @@
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.IChunkCell
import ru.dbotthepony.kvector.arrays.Object2DArray
@ -24,7 +24,7 @@ class RectTileFlooderDepthFirst(
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 {
@ -169,7 +169,7 @@ class RectTileFlooderDepthFirst(
fun markSeen() {
for (x in mins.x .. maxs.x) {
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
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.IChunkCell
import ru.dbotthepony.kvector.arrays.Object2DArray
@ -24,7 +24,7 @@ class RectTileFlooderSizeFirst(
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
@ -138,7 +138,7 @@ class RectTileFlooderSizeFirst(
fun markSeen() {
for (x in mins.x .. maxs.x) {
for (y in mins.y .. maxs.y) {
seen[x or (y shl CHUNK_SHIFT)] = true
seen[x or (y shl CHUNK_SIZE_BITS)] = true
}
}
}