-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Supports sparse infinite tilemaps with BVH for spatial finding (#1080)
* Moved BVH to KDS to be able to use it at the KDS layer * Created a new IStackedIntArray2 interface to support additional interfaces * Creates a SparseChunkedStackedIntArray2 implementation supporting chunked arrays implemented the interface * Make TileMap to support the new IStackedIntArray2 interface, and adjust bounds to use startX, startY, endX, endY * Updated TiledMap to use SparseChunkedStackedIntArray2 on infinite maps
- Loading branch information
Showing
12 changed files
with
366 additions
and
87 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
kds/src/commonMain/kotlin/com/soywiz/kds/SparseChunkedStackedIntArray2.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package com.soywiz.kds | ||
|
||
import com.soywiz.kds.ds.* | ||
import com.soywiz.kds.iterators.* | ||
import kotlin.math.* | ||
|
||
class SparseChunkedStackedIntArray2(override var empty: Int = -1) : IStackedIntArray2 { | ||
var minX = 0 | ||
var minY = 0 | ||
var maxX = 0 | ||
var maxY = 0 | ||
override var maxLevel: Int = 0 | ||
|
||
val bvh = BVH<IStackedIntArray2>(dimensions = 2) | ||
var first: IStackedIntArray2? = null | ||
var last: IStackedIntArray2? = null | ||
|
||
fun putChunk(chunk: IStackedIntArray2) { | ||
if (first == null) { | ||
first = chunk | ||
empty = chunk.empty | ||
minX = Int.MAX_VALUE | ||
minY = Int.MAX_VALUE | ||
maxX = Int.MIN_VALUE | ||
maxY = Int.MIN_VALUE | ||
} | ||
last = chunk | ||
bvh.insertOrUpdate( | ||
BVHIntervals(chunk.startX, chunk.width, chunk.startY, chunk.height), | ||
chunk | ||
) | ||
minX = min(minX, chunk.startX) | ||
minY = min(minY, chunk.startY) | ||
maxX = max(maxX, chunk.endX) | ||
maxY = max(maxY, chunk.endY) | ||
maxLevel = max(maxLevel, chunk.maxLevel) | ||
} | ||
|
||
override val startX: Int get() = minX | ||
override val startY: Int get() = minY | ||
override val width: Int get() = maxX - minX | ||
override val height: Int get() = maxY - minY | ||
|
||
fun findAllChunks(): List<IStackedIntArray2> = bvh.findAllValues() | ||
|
||
private var lastSearchChunk: IStackedIntArray2? = null | ||
|
||
private fun IStackedIntArray2.chunkX(x: Int): Int = x - this.startX | ||
private fun IStackedIntArray2.chunkY(y: Int): Int = y - this.startY | ||
private fun IStackedIntArray2.containsChunk(x: Int, y: Int): Boolean { | ||
return x in startX until endX && y in startY until endY | ||
} | ||
|
||
fun getChunkAt(x: Int, y: Int): IStackedIntArray2? { | ||
// Cache to be much faster while iterating rows | ||
lastSearchChunk?.let { | ||
if (it.containsChunk(x, y)) return it | ||
} | ||
lastSearchChunk = bvh.searchValues(BVHIntervals(x, 1, y, 1)).firstOrNull() | ||
return lastSearchChunk | ||
} | ||
|
||
override fun set(x: Int, y: Int, level: Int, value: Int) { | ||
getChunkAt(x, y)?.let { chunk -> | ||
chunk[chunk.chunkX(x), chunk.chunkY(y), level] = value | ||
} | ||
} | ||
|
||
override fun get(x: Int, y: Int, level: Int): Int { | ||
getChunkAt(x, y)?.let { chunk -> | ||
return chunk[chunk.chunkX(x), chunk.chunkY(y), level] | ||
} | ||
return empty | ||
} | ||
|
||
override fun getStackLevel(x: Int, y: Int): Int { | ||
getChunkAt(x, y)?.let { chunk -> | ||
return chunk.getStackLevel(chunk.chunkX(x), chunk.chunkY(y)) | ||
} | ||
return 0 | ||
} | ||
|
||
override fun push(x: Int, y: Int, value: Int) { | ||
getChunkAt(x, y)?.let { chunk -> | ||
chunk.push(chunk.chunkX(x), chunk.chunkY(y), value) | ||
} | ||
} | ||
|
||
override fun removeLast(x: Int, y: Int) { | ||
getChunkAt(x, y)?.let { chunk -> | ||
chunk.removeLast(chunk.chunkX(x), chunk.chunkY(y)) | ||
} | ||
} | ||
|
||
override fun clone(): SparseChunkedStackedIntArray2 = SparseChunkedStackedIntArray2(empty).also { sparse -> | ||
findAllChunks().fastForEach { | ||
sparse.putChunk(it.clone()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../kotlin/com/soywiz/korma/geom/ds/CSBVH.kt → ...monMain/kotlin/com/soywiz/kds/ds/CSBVH.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.