Browse Source

fix some lighting glitches & edge cases

master
James Fenn 2 weeks ago
parent
commit
f4b46a46ac
6 changed files with 90 additions and 24 deletions
  1. +8
    -4
      dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/Dungeon.kt
  2. +1
    -1
      dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/env/Config.kt
  3. +11
    -11
      dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/graphics/GraphicsManager.kt
  4. +9
    -7
      dungeon/src/commonMain/kotlin/me/jfenn/dungeon/core/graphics/Luminance.kt
  5. +60
    -0
      dungeon/src/commonMain/kotlin/me/jfenn/dungeon/core/vector/area/LineArea.kt
  6. +1
    -1
      example-swing/src/main/java/me/jfenn/example/dungeonswing/snake/Background.kt

+ 8
- 4
dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/Dungeon.kt View File

@@ -3,12 +3,10 @@ package me.jfenn.dungeon.api
import me.jfenn.dungeon.api.env.Config
import me.jfenn.dungeon.api.env.PlatformConfig
import me.jfenn.dungeon.api.timing.currentTimeMillis
import me.jfenn.dungeon.api.timing.fixedRateTimer
import me.jfenn.dungeon.api.view.DungeonView
import me.jfenn.dungeon.api.view.DungeonViewImpl
import kotlinx.coroutines.*
import me.jfenn.dungeon.api.graphics.GraphicsManager
import kotlin.time.measureTime

fun dungeon(block: DungeonOpts.() -> Unit) : Dungeon {
val opts = DungeonOpts()
@@ -39,10 +37,12 @@ class Dungeon(
val manager: GraphicsManager
) {

suspend fun start() : GraphicsManager {
private lateinit var job: Job

fun start() : GraphicsManager {
val frameInterval = 1000L / env.fps

env.scope.launch {
job = env.scope.launch {
while (true) {
val startTime = currentTimeMillis()

@@ -60,4 +60,8 @@ class Dungeon(
return manager
}

fun stop() {
job.cancel()
}

}

+ 1
- 1
dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/env/Config.kt View File

@@ -10,7 +10,7 @@ import me.jfenn.dungeon.core.vector.IntVector
import kotlin.math.min
import kotlin.math.roundToInt

const val CHUNK_SIZE = 16
const val CHUNK_SIZE = 8

class Config {



+ 11
- 11
dungeon/src/commonMain/kotlin/me/jfenn/dungeon/api/graphics/GraphicsManager.kt View File

@@ -25,21 +25,21 @@ class GraphicsManager(
val env: Config
) {

val sprites = ArrayList<Sprite>()
private val sprites = ArrayList<Sprite>()

var assembledPixels = SpatialMapChunked<Pixel>()
var assembledPixelsOld = SpatialMapChunked<Pixel>()
private var assembledPixels = SpatialMapChunked<Pixel>()
private var assembledPixelsOld = SpatialMapChunked<Pixel>()

var assembledLights = SpatialMapFast<Luminance>()
var assembledLightsOld = SpatialMapFast<Luminance>()
private var assembledLights = SpatialMapFast<Luminance>()
private var assembledLightsOld = SpatialMapFast<Luminance>()

val updatedChunks: SpatialMap<Boolean> = SpatialMap()
val deferred = ArrayList<Deferred<Unit>>()
val lightMap: SpatialMapFast<Color> = SpatialMapFast()
val lightMapMutex = Mutex()
private val updatedChunks: SpatialMap<Boolean> = SpatialMap()
private val deferred = ArrayList<Deferred<Unit>>()
private val lightMap: SpatialMapFast<Color> = SpatialMapFast()
private val lightMapMutex = Mutex()

var renderedPixels = SpatialMapFast<Color>()
var renderedZ = SpatialMapFast<Int>()
private var renderedPixels = SpatialMapFast<Color>()
private var renderedZ = SpatialMapFast<Int>()

fun addSprite(sprite: Sprite) {
sprite.onCreate(env)


+ 9
- 7
dungeon/src/commonMain/kotlin/me/jfenn/dungeon/core/graphics/Luminance.kt View File

@@ -25,7 +25,7 @@ data class Luminance(
return ceil(1.0 / degredation).toFloat()
}

val lightMap: SpatialCollection<Color> = SpatialMapChunked()
val lightMap: SpatialCollection<Color> = SpatialMapFast()

val updatedChunks: SpatialCollection<Boolean> = SpatialMapFast()
val visited: SpatialCollection<Boolean> = SpatialMapFast()
@@ -36,12 +36,12 @@ data class Luminance(
}

fun updateChunk(position: FastIntVector, update: FastIntVector) {
if (updatedChunks[update] != false)
return

val chunkPosition = position.vdiv(CHUNK_SIZE)
val distance = update.vsub(chunkPosition)

if (updatedChunks[update] == true || ceil(getAffectedRadius() / CHUNK_SIZE) < update.distanceTo(chunkPosition))
return

// if a drawn chunk is "behind" the updated chunk, invalidate it
updatedChunks.forEach { iPos, isUpdated ->
if (isUpdated) return@forEach
@@ -95,9 +95,11 @@ data class Luminance(
intensity *= (1 - pixel.color.alpha)
}

if (intensity > 0.01f && visited[pixelPos] != true) {
val color = getColor(position.distanceTo(pixelPos).toFloat())
lightMap[pixelPos] = color.set(alpha = color.alpha * intensity)
if (visited[pixelPos] != true) {
if (intensity > 0.01f) {
val color = getColor(position.distanceTo(pixelPos).toFloat())
lightMap[pixelPos] = color.set(alpha = color.alpha * intensity)
} else lightMap[pixelPos] = null
}

visited[pixelPos] = true


+ 60
- 0
dungeon/src/commonMain/kotlin/me/jfenn/dungeon/core/vector/area/LineArea.kt View File

@@ -27,6 +27,66 @@ class LineIterator(
(end.z - start.z) / distance
)

private var current = 0
private var nextOverlap: FastIntVector? = null

override fun hasNext(): Boolean {
return current < distance
}

override fun next(): FastIntVector {
nextOverlap?.let {
nextOverlap = null
return it
}

val position = vectorOf(
start.x + (delta.x * current).toInt(),
start.y + (delta.y * current).toInt(),
start.z + (delta.z * current).toInt()
)

val positionOverlap = vectorOf(
start.x + (delta.x * (current + 0.9f)).toInt(),
start.y + (delta.y * (current + 0.9f)).toInt(),
start.z + (delta.z * (current + 0.9f)).toInt()
)

if (position != positionOverlap) {
// found overlapping pixel; use in next iteration
nextOverlap = positionOverlap
}

current++
return position
}

}

class FastLineIterator(
private val start: FastIntVector,
end: FastIntVector
) : Iterator<FastIntVector> {

private val diff = vectorOf(
abs(start.x - end.x),
abs(start.y - end.y),
abs(start.z - end.z)
)

private val distance = when {
diff.x > diff.y -> diff.x.toFloat()
diff.y > diff.z -> diff.y.toFloat()
diff.z != 0 -> diff.z.toFloat()
else -> start.distanceTo(end).toFloat() * LineArea.SQUARE_MULTIPLIER
}

private val delta = MutableFloatVector(
(end.x - start.x) / distance,
(end.y - start.y) / distance,
(end.z - start.z) / distance
)

private var current = 0

override fun hasNext(): Boolean {


+ 1
- 1
example-swing/src/main/java/me/jfenn/example/dungeonswing/snake/Background.kt View File

@@ -21,7 +21,7 @@ class Background : Sprite() {
for (x in (0..canvas.width)) for (y in (0..canvas.height)) {
canvas.draw(Pixel(
colorString("#0FFF")
), vectorOf(x, y, -(11 + sin((x + y).toDouble() / PI) * 10).toInt()))
), vectorOf(x, y, -(10 + sin((x + y).toDouble() / PI) * 10).toInt()))
}
}



Loading…
Cancel
Save