mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-08 04:41:51 +09:00
asynchronous lightmap update wip
This commit is contained in:
31
assets/mods/basegame/commands.csv
Normal file
31
assets/mods/basegame/commands.csv
Normal file
@@ -0,0 +1,31 @@
|
||||
CatStdout
|
||||
CheatWarnTest
|
||||
CodexEdictis
|
||||
ExportCodices
|
||||
ExportMap
|
||||
ForceGC
|
||||
GetAV
|
||||
GetFaction
|
||||
GetLocale
|
||||
GetTime
|
||||
ImportLayerData
|
||||
ImportWorld
|
||||
Inventory
|
||||
KillActor
|
||||
LangTest
|
||||
MoneyDisp
|
||||
MusicTest
|
||||
Possess
|
||||
PrintWorld
|
||||
Save
|
||||
Seed
|
||||
SetAV
|
||||
SetBulletin
|
||||
SetScale
|
||||
SetTime
|
||||
SetTimeDelta
|
||||
SpawnPhysTestBall
|
||||
StreamerMode
|
||||
Teleport
|
||||
ToggleNoClip
|
||||
Zoom
|
||||
|
@@ -18,6 +18,8 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
|
||||
|
||||
private inline fun toAddr(x: Int, y: Int) = 16L * (y * width + x)
|
||||
|
||||
fun isDestroyed() = array.destroyed
|
||||
|
||||
init {
|
||||
zerofill()
|
||||
}
|
||||
|
||||
@@ -33,8 +33,11 @@ internal object Authenticator : ConsoleCommand {
|
||||
val pwd = args[1]
|
||||
val hashedPwd = DigestUtils.sha256Hex(pwd)
|
||||
|
||||
if ("65b9aa150332ed7096134efb20220e5ebec04d4dbe1c537ff3816f68c2391c1c".equals(hashedPwd, ignoreCase = true)) {
|
||||
// aryll
|
||||
println("auth passwd: '$pwd'")
|
||||
println("hash: $hashedPwd")
|
||||
|
||||
if ("09ccf5067db6f58265b004829e33e715e819ba0984f1e1fcef49c36fcd5f745f".equals(hashedPwd, ignoreCase = true)) {
|
||||
// beedle
|
||||
val msg = if (a) "Locked" else "Authenticated"
|
||||
Echo(msg)
|
||||
println("[Authenticator] " + msg)
|
||||
|
||||
@@ -13,15 +13,42 @@ object CommandDict {
|
||||
|
||||
internal val dict = hashMapOf<String, ConsoleCommand>()
|
||||
|
||||
private val engineCommandList = listOf(
|
||||
"ActorsList",
|
||||
"Authenticator",
|
||||
"AVTracker",
|
||||
"Batch",
|
||||
"Echo",
|
||||
"EchoConsole",
|
||||
"EchoError",
|
||||
"Pause",
|
||||
"QuitApp",
|
||||
"ResizeScreen",
|
||||
"ScreencapNogui",
|
||||
"SetGlobalLightOverride",
|
||||
"SetLocale",
|
||||
"TakeScreenshot",
|
||||
"Unpause",
|
||||
"Version"
|
||||
)
|
||||
|
||||
init {
|
||||
printdbg(this, ModMgr.loadOrder.reversed())
|
||||
printdbg(this, ModMgr.loadOrder.reversed().map { ModMgr.moduleInfo[it]?.packageName })
|
||||
|
||||
(listOf("net.torvald.terrarum") + ModMgr.loadOrder.reversed().mapNotNull { ModMgr.moduleInfo[it]?.packageName }).forEach { packageRoot ->
|
||||
printdbg(this, packageRoot)
|
||||
((listOf("$" to "net.torvald.terrarum")) + ModMgr.loadOrder.reversed().map { it to ModMgr.moduleInfo[it]?.packageName }).forEach { (modName, packageRoot) ->
|
||||
val commandsList = if (modName == "$") engineCommandList else ModMgr.getFile(modName, "commands.csv").readLines()
|
||||
val packageConsole = "$packageRoot.console"
|
||||
|
||||
printdbg(this, "Loading console commands from '${packageConsole}'")
|
||||
|
||||
|
||||
// TODO load commands using commandsList
|
||||
|
||||
|
||||
val stream = ClassLoader.getSystemClassLoader().getResourceAsStream(packageConsole.replace('.', '/'))
|
||||
|
||||
|
||||
if (stream != null) { // not all modules have extra console commands
|
||||
|
||||
val reader = BufferedReader(InputStreamReader(stream))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.ccG
|
||||
import net.torvald.terrarum.ccW
|
||||
import net.torvald.terrarum.ccY
|
||||
@@ -32,8 +33,6 @@ internal object CommandInterpreter {
|
||||
internal fun execute(command: String) {
|
||||
val cmd: Array<CommandInput?> = parse(command)
|
||||
|
||||
val error = Error()
|
||||
|
||||
for (single_command in cmd) {
|
||||
|
||||
if (single_command == null || single_command.argsCount == 0) continue
|
||||
@@ -65,6 +64,7 @@ internal object CommandInterpreter {
|
||||
}
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
e.printStackTrace()
|
||||
echoUnknownCmd(single_command.name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.torvald.terrarum.blockproperties.BlockPropUtil
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
@@ -22,6 +23,7 @@ import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.ui.UINSMenu
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import net.torvald.util.CircularArray
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2018-07-06.
|
||||
@@ -385,10 +387,21 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
BlockPropUtil.dynamicLumFuncTickClock()
|
||||
}
|
||||
|
||||
private val particles = CircularArray<ParticleBase>(16, true)
|
||||
|
||||
private fun renderGame() {
|
||||
_testMarkerDrawCalls = 0L
|
||||
|
||||
IngameRenderer.invoke(false, actorsRenderOverlay = if (showSelection) actorsRenderOverlay + essentialOverlays else essentialOverlays, uiContainer = uiContainer)
|
||||
IngameRenderer.invoke(false,
|
||||
1f,
|
||||
listOf(),
|
||||
listOf(),
|
||||
listOf(),
|
||||
listOf(),
|
||||
if (showSelection) actorsRenderOverlay + essentialOverlays else essentialOverlays,
|
||||
particles,
|
||||
uiContainer = uiContainer
|
||||
)
|
||||
|
||||
App.setDebugTime("Test.MarkerDrawCalls", _testMarkerDrawCalls)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.measureDebugTime
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
@@ -196,22 +197,20 @@ object IngameRenderer : Disposable {
|
||||
operator fun invoke(
|
||||
gamePaused: Boolean,
|
||||
zoom: Float = 1f,
|
||||
actorsRenderBehind : List<ActorWithBody>? = null,
|
||||
actorsRenderMiddle : List<ActorWithBody>? = null,
|
||||
actorsRenderMidTop : List<ActorWithBody>? = null,
|
||||
actorsRenderFront : List<ActorWithBody>? = null,
|
||||
actorsRenderOverlay: List<ActorWithBody>? = null,
|
||||
particlesContainer : CircularArray<ParticleBase>? = null,
|
||||
actorsRenderBehind : List<ActorWithBody>,
|
||||
actorsRenderMiddle : List<ActorWithBody>,
|
||||
actorsRenderMidTop : List<ActorWithBody>,
|
||||
actorsRenderFront : List<ActorWithBody>,
|
||||
actorsRenderOverlay: List<ActorWithBody>,
|
||||
particlesContainer : CircularArray<ParticleBase>,
|
||||
player: ActorWithBody? = null,
|
||||
uiContainer: UIContainer? = null
|
||||
) {
|
||||
renderingActorsCount = (actorsRenderBehind?.size ?: 0) +
|
||||
(actorsRenderMiddle?.size ?: 0) +
|
||||
(actorsRenderMidTop?.size ?: 0) +
|
||||
(actorsRenderFront?.size ?: 0) +
|
||||
(actorsRenderOverlay?.size ?: 0)
|
||||
//renderingParticleCount = particlesContainer?.size ?: 0
|
||||
//renderingParticleCount = (particlesContainer?.buffer?.map { (!it.flagDespawn).toInt() } ?: listOf(0)).sum()
|
||||
renderingActorsCount = (actorsRenderBehind.size) +
|
||||
(actorsRenderMiddle.size) +
|
||||
(actorsRenderMidTop.size) +
|
||||
(actorsRenderFront.size) +
|
||||
(actorsRenderOverlay.size)
|
||||
renderingUIsCount = uiContainer?.countVisible() ?: 0
|
||||
|
||||
invokeInit()
|
||||
@@ -225,8 +224,9 @@ object IngameRenderer : Disposable {
|
||||
if (!gamePaused || newWorldLoadedLatch) {
|
||||
measureDebugTime("Renderer.LightRun*") {
|
||||
// recalculate for even frames, or if the sign of the cam-x changed
|
||||
if (App.GLOBAL_RENDER_TIMER % 3 == 0 || Math.abs(WorldCamera.x - oldCamX) >= world.width * 0.85f * TILE_SIZEF || newWorldLoadedLatch) {
|
||||
LightmapRenderer.fireRecalculateEvent(actorsRenderBehind, actorsRenderFront, actorsRenderMidTop, actorsRenderMiddle, actorsRenderOverlay)
|
||||
if (App.GLOBAL_RENDER_TIMER % 80 == 0 || Math.abs(WorldCamera.x - oldCamX) >= world.width * 0.85f * TILE_SIZEF || newWorldLoadedLatch) {
|
||||
printdbg(this, "LightmapRenderer requestRecalculation")
|
||||
LightmapRenderer.requestRecalculation { actorsRenderBehind + actorsRenderFront + actorsRenderMidTop + actorsRenderMiddle + actorsRenderOverlay }
|
||||
}
|
||||
oldCamX = WorldCamera.x
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.torvald.terrarum.console.CommandDict
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gameactors.ai.ActorAI
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
@@ -31,6 +32,7 @@ import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import net.torvald.util.CircularArray
|
||||
import java.io.IOException
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
@@ -285,6 +287,8 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
uiContainer.forEach { it?.update(delta) }
|
||||
}
|
||||
|
||||
private val particles = CircularArray<ParticleBase>(16, true)
|
||||
|
||||
fun renderScreen() {
|
||||
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
|
||||
|
||||
@@ -296,7 +300,17 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
if (!demoWorld.layerTerrain.ptr.destroyed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
|
||||
IngameRenderer.invoke(gamePaused = false, uiContainer = uiContainer)
|
||||
IngameRenderer.invoke(
|
||||
false,
|
||||
1f,
|
||||
listOf(),
|
||||
listOf(),
|
||||
listOf(),
|
||||
listOf(),
|
||||
listOf(),
|
||||
particles,
|
||||
uiContainer = uiContainer
|
||||
)
|
||||
}
|
||||
else {
|
||||
printdbgerr(this, "Demoworld is already been destroyed")
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import net.torvald.terrarum.console.ConsoleAlias
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
//import net.torvald.terrarum.swingapp.IMStringReader
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-02-05.
|
||||
*/
|
||||
|
||||
@ConsoleAlias("imtest")
|
||||
internal object JavaIMTest : ConsoleCommand {
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
/*IMStringReader(
|
||||
{ Echo("[JavaIMTest -> IMStringReader] $it") }, // send input to Echo
|
||||
"JavaIMTest"
|
||||
)*/
|
||||
val inputListener = object : Input.TextInputListener {
|
||||
override fun input(text: String?) {
|
||||
Echo("[TextInputText] $text")
|
||||
}
|
||||
override fun canceled() {
|
||||
Echo("[TextInputText] (input canceled)")
|
||||
}
|
||||
}
|
||||
Gdx.input.getTextInput(inputListener, "TextInputTest", "", "type anything!")
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("Tests Swing input window to get non-English text input")
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import net.torvald.terrarum.console.ConsoleAlias
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-07-04.
|
||||
*/
|
||||
@ConsoleAlias("tips")
|
||||
internal object PrintRandomTips : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
Echo("Nope.")
|
||||
//Echo(Lang["GAME_TIPS_${Random().nextInt(Lang.TIPS_COUNT) + 1}"])
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("Prints random tips for game.")
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.PhysTestLuarLander
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2018-01-18.
|
||||
*/
|
||||
internal object SpawnPhysTestLunarLander : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
val mouseX = Terrarum.mouseX
|
||||
val mouseY = Terrarum.mouseY
|
||||
val lander = PhysTestLuarLander()
|
||||
|
||||
lander.setPosition(mouseX, mouseY)
|
||||
|
||||
INGAME.queueActorAddition(lander)
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("control it with arrow keys")
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.DecodeTapestry
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-01-14.
|
||||
*/
|
||||
internal object SpawnTapestry : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
if (args.size < 2) {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
val tapestry = DecodeTapestry(File(args[1]))
|
||||
INGAME.queueActorAddition(tapestry)
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("Usage: spawntapestry <tapestry_file>")
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.ConsoleNoExport
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-12-17.
|
||||
*/
|
||||
@ConsoleNoExport
|
||||
internal object SpawnTikiTorch : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
val torch = FixtureTikiTorch()
|
||||
torch.setPosition(Terrarum.mouseX, Terrarum.mouseY)
|
||||
|
||||
INGAME.queueActorAddition(torch)
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("Usage: spawntorch")
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ package net.torvald.terrarum.worlddrawer
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.UnsafeHelper
|
||||
import net.torvald.gdx.graphics.Cvec
|
||||
import net.torvald.gdx.graphics.UnsafeCvecArray
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.measureDebugTime
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
@@ -19,6 +21,8 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.ui.abs
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -50,6 +54,7 @@ object LightmapRenderer {
|
||||
printdbg(this, "World change detected -- old world: ${this.world.hashCode()}, new world: ${world.hashCode()}")
|
||||
|
||||
lightmap.zerofill()
|
||||
_lightmap.zerofill()
|
||||
_mapLightLevelThis.zerofill()
|
||||
_mapThisTileOpacity.zerofill()
|
||||
_mapThisTileOpacity2.zerofill()
|
||||
@@ -60,8 +65,6 @@ object LightmapRenderer {
|
||||
}
|
||||
finally {
|
||||
this.world = world
|
||||
|
||||
//fireRecalculateEvent()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,15 +85,11 @@ object LightmapRenderer {
|
||||
*/
|
||||
// it utilises alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light)
|
||||
private var lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
private var _lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
private var _mapLightLevelThis = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
private var _mapThisTileOpacity = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
private var _mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
|
||||
init {
|
||||
LightmapHDRMap.invoke()
|
||||
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
|
||||
}
|
||||
|
||||
private const val AIR = Block.AIR
|
||||
|
||||
const val DRAW_TILE_SIZE: Float = TILE_SIZE / IngameRenderer.lightmapDownsample
|
||||
@@ -141,7 +140,67 @@ object LightmapRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
fun fireRecalculateEvent(vararg actorContainers: List<ActorWithBody>?) {
|
||||
|
||||
internal var rendererStatus = AtomicInteger(2) // 0: processing queued, 1: processing, 2: done
|
||||
private var lightmapPrepared = AtomicBoolean(false)
|
||||
|
||||
private val runnerLock = java.lang.Object()
|
||||
private val runner = Runnable { while (!Thread.interrupted()) {
|
||||
if (rendererStatus.get() == 0) {
|
||||
measureDebugTime("Renderer.LightCalcThread") {
|
||||
rendererStatus.incrementAndGet() // 0 -> 1
|
||||
|
||||
val unlock = lightmapPrepared.get()
|
||||
|
||||
if (unlock) {
|
||||
try {
|
||||
printdbg(this, "Recalculate!") // should recalculate once on request, not every f'ing frame
|
||||
recalculate(actorsGetter(), _lightmap)
|
||||
|
||||
// dispatch _lightmap to lightmap
|
||||
UnsafeHelper.memcpy(_lightmap.ptr, lightmap.ptr, lightmap.TOTAL_SIZE_IN_BYTES)
|
||||
// visuals being "jittery" means you're not dispatching the lightmap correctly
|
||||
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("NPE; lightmapPrepared = $unlock")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
rendererStatus.incrementAndGet() // 1 -> 2
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Thread.sleep(1L)
|
||||
synchronized(runnerLock) { runnerLock.wait() }
|
||||
}
|
||||
} }
|
||||
|
||||
private val lightCalcThread = Thread(runner, "LightCalcThread")
|
||||
|
||||
init {
|
||||
LightmapHDRMap.invoke()
|
||||
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
|
||||
lightCalcThread.start()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request recalculation of the light. When it's not a tick to recalculate, or recalculation is ongoing,
|
||||
* the request will be silently disregarded.
|
||||
*/
|
||||
fun requestRecalculation(actorContainers: () -> List<ActorWithBody>) {
|
||||
if (rendererStatus.get() == 2) {
|
||||
actorsGetter = actorContainers
|
||||
rendererStatus.set(0)
|
||||
synchronized(runnerLock) { runnerLock.notifyAll() }
|
||||
}
|
||||
}
|
||||
|
||||
private var actorsGetter: () -> List<ActorWithBody> = { listOf() }
|
||||
|
||||
private fun recalculate(actorContainers: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
|
||||
try {
|
||||
world.getTileFromTerrain(0, 0) // test inquiry
|
||||
}
|
||||
@@ -149,7 +208,7 @@ object LightmapRenderer {
|
||||
return // quit prematurely
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("[LightmapRendererNew.fireRecalculateEvent] Attempted to refer destroyed unsafe array " +
|
||||
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
||||
"(${world.layerTerrain.ptr})")
|
||||
e.printStackTrace()
|
||||
return // something's wrong but we'll ignore it like a trustful AK
|
||||
@@ -205,27 +264,29 @@ object LightmapRenderer {
|
||||
|
||||
// 'NEWLIGHT2' LIGHT SWIPER
|
||||
// O((8*2)n) where n is a size of the map.
|
||||
/* - */fun r1() {
|
||||
/* - */fun r1(lightmap: UnsafeCvecArray) {
|
||||
swipeDiag = false
|
||||
for (line in 1 until LIGHTMAP_HEIGHT - 1) {
|
||||
swipeLight(
|
||||
1, line,
|
||||
LIGHTMAP_WIDTH - 2, line,
|
||||
1, 0
|
||||
1, 0,
|
||||
lightmap
|
||||
)
|
||||
}
|
||||
}
|
||||
/* | */fun r2() {
|
||||
/* | */fun r2(lightmap: UnsafeCvecArray) {
|
||||
swipeDiag = false
|
||||
for (line in 1 until LIGHTMAP_WIDTH - 1) {
|
||||
swipeLight(
|
||||
line, 1,
|
||||
line, LIGHTMAP_HEIGHT - 2,
|
||||
0, 1
|
||||
0, 1,
|
||||
lightmap
|
||||
)
|
||||
}
|
||||
}
|
||||
/* \ */fun r3() {
|
||||
/* \ */fun r3(lightmap: UnsafeCvecArray) {
|
||||
swipeDiag = true
|
||||
/* construct indices such that:
|
||||
56789ABC
|
||||
@@ -258,11 +319,12 @@ object LightmapRenderer {
|
||||
swipeLight(
|
||||
maxOf(1, i - LIGHTMAP_HEIGHT + 4), maxOf(1, LIGHTMAP_HEIGHT - 2 - i),
|
||||
minOf(LIGHTMAP_WIDTH - 2, i + 1), minOf(LIGHTMAP_HEIGHT - 2, (LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT - 5) - i),
|
||||
1, 1
|
||||
1, 1,
|
||||
lightmap
|
||||
)
|
||||
}
|
||||
}
|
||||
/* / */fun r4() {
|
||||
/* / */fun r4(lightmap: UnsafeCvecArray) {
|
||||
swipeDiag = true
|
||||
/*
|
||||
1 w-2
|
||||
@@ -291,7 +353,8 @@ object LightmapRenderer {
|
||||
swipeLight(
|
||||
maxOf(1, i - LIGHTMAP_HEIGHT + 4), minOf(LIGHTMAP_HEIGHT - 2, i + 1),
|
||||
minOf(LIGHTMAP_WIDTH - 2, i + 1), maxOf(1, (LIGHTMAP_HEIGHT - 2) - (LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT - 6) + i),
|
||||
1, -1
|
||||
1, -1,
|
||||
lightmap
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -313,34 +376,33 @@ object LightmapRenderer {
|
||||
// why dark spots appear in the first place)
|
||||
// - Multithreading? I have absolutely no idea.
|
||||
// - If you naively slice the screen (job area) to multithread, the seam will appear.
|
||||
|
||||
r1();r2();r3();r4()
|
||||
r1();r2();r3();r4() // two looks better than one
|
||||
r1(lightmap);r2(lightmap);r3(lightmap);r4(lightmap)
|
||||
r1(lightmap);r2(lightmap);r3(lightmap);r4(lightmap) // two looks better than one
|
||||
// no rendering trickery will eliminate the need of 2nd pass, even the "decay out"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun buildLanternmap(actorContainers: Array<out List<ActorWithBody>?>) {
|
||||
private fun buildLanternmap(actorContainer: List<ActorWithBody>) {
|
||||
lanternMap.clear()
|
||||
actorContainers.forEach { actorContainer ->
|
||||
actorContainer?.forEach {
|
||||
if (it is Luminous) {
|
||||
// put lanterns to the area the luminantBox is occupying
|
||||
for (lightBox in it.lightBoxList) {
|
||||
val lightBoxX = it.hitbox.startX + lightBox.startX
|
||||
val lightBoxY = it.hitbox.startY + lightBox.startY
|
||||
val lightBoxW = lightBox.width
|
||||
val lightBoxH = lightBox.height
|
||||
for (y in lightBoxY.div(TILE_SIZE).floorInt()
|
||||
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
|
||||
for (x in lightBoxX.div(TILE_SIZE).floorInt()
|
||||
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
|
||||
actorContainer.forEach {
|
||||
if (it is Luminous) {
|
||||
val lightBoxCopy = it.lightBoxList.subList(0, it.lightBoxList.size) // make copy to prevent ConcurrentModificationException
|
||||
|
||||
val normalisedCvec = it.color//.cpy().mul(DIV_FLOAT)
|
||||
// put lanterns to the area the luminantBox is occupying
|
||||
for (lightBox in lightBoxCopy) {
|
||||
val lightBoxX = it.hitbox.startX + lightBox.startX
|
||||
val lightBoxY = it.hitbox.startY + lightBox.startY
|
||||
val lightBoxW = lightBox.width
|
||||
val lightBoxH = lightBox.height
|
||||
for (y in lightBoxY.div(TILE_SIZE).floorInt()
|
||||
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
|
||||
for (x in lightBoxX.div(TILE_SIZE).floorInt()
|
||||
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
|
||||
|
||||
lanternMap[LandUtil.getBlockAddr(world, x, y)] = normalisedCvec
|
||||
}
|
||||
val normalisedCvec = it.color//.cpy().mul(DIV_FLOAT)
|
||||
|
||||
lanternMap[LandUtil.getBlockAddr(world, x, y)] = normalisedCvec
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -522,7 +584,7 @@ object LightmapRenderer {
|
||||
private var swipeX = -1
|
||||
private var swipeY = -1
|
||||
private var swipeDiag = false
|
||||
private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int) {
|
||||
private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int, lightmap: UnsafeCvecArray) {
|
||||
if (x2 < 0 || y2 < 0 || x2 >= LIGHTMAP_WIDTH || y2 >= LIGHTMAP_HEIGHT) return
|
||||
|
||||
_ambientAccumulator.r = _mapLightLevelThis.getR(x, y)
|
||||
@@ -535,25 +597,25 @@ object LightmapRenderer {
|
||||
_thisTileOpacity.g = _mapThisTileOpacity.getG(x, y)
|
||||
_thisTileOpacity.b = _mapThisTileOpacity.getB(x, y)
|
||||
_thisTileOpacity.a = _mapThisTileOpacity.getA(x, y)
|
||||
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity))
|
||||
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity, lightmap))
|
||||
}
|
||||
else {
|
||||
_thisTileOpacity2.r = _mapThisTileOpacity2.getR(x, y)
|
||||
_thisTileOpacity2.g = _mapThisTileOpacity2.getG(x, y)
|
||||
_thisTileOpacity2.b = _mapThisTileOpacity2.getB(x, y)
|
||||
_thisTileOpacity2.a = _mapThisTileOpacity2.getA(x, y)
|
||||
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2))
|
||||
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2, lightmap))
|
||||
}
|
||||
|
||||
_mapLightLevelThis.setVec(x, y, _ambientAccumulator)
|
||||
lightmap.setVec(x, y, _ambientAccumulator)
|
||||
}
|
||||
private fun swipeLight(sx: Int, sy: Int, ex: Int, ey: Int, dx: Int, dy: Int) {
|
||||
private fun swipeLight(sx: Int, sy: Int, ex: Int, ey: Int, dx: Int, dy: Int, lightmap: UnsafeCvecArray) {
|
||||
swipeX = sx; swipeY = sy
|
||||
while (swipeX*dx <= ex*dx && swipeY*dy <= ey*dy) {
|
||||
// conduct the task #1
|
||||
// spread towards the end
|
||||
_swipeTask(swipeX, swipeY, swipeX-dx, swipeY-dy)
|
||||
_swipeTask(swipeX, swipeY, swipeX-dx, swipeY-dy, lightmap)
|
||||
|
||||
swipeX += dx
|
||||
swipeY += dy
|
||||
@@ -563,7 +625,7 @@ object LightmapRenderer {
|
||||
while (swipeX*dx >= sx*dx && swipeY*dy >= sy*dy) {
|
||||
// conduct the task #2
|
||||
// spread towards the start
|
||||
_swipeTask(swipeX, swipeY, swipeX+dx, swipeY+dy)
|
||||
_swipeTask(swipeX, swipeY, swipeX+dx, swipeY+dy, lightmap)
|
||||
|
||||
swipeX -= dx
|
||||
swipeY -= dy
|
||||
@@ -662,10 +724,14 @@ object LightmapRenderer {
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
lightCalcThread.interrupt()
|
||||
|
||||
LightmapHDRMap.dispose()
|
||||
_lightBufferAsTex.dispose()
|
||||
lightBuffer.dispose()
|
||||
|
||||
lightmapPrepared.set(false)
|
||||
|
||||
lightmap.destroy()
|
||||
_mapLightLevelThis.destroy()
|
||||
_mapThisTileOpacity.destroy()
|
||||
@@ -682,7 +748,7 @@ object LightmapRenderer {
|
||||
* @param darken (0-255) per channel
|
||||
* @return darkened data (0-255) per channel
|
||||
*/
|
||||
fun darkenColoured(x: Int, y: Int, darken: Cvec): Cvec {
|
||||
internal fun darkenColoured(x: Int, y: Int, darken: Cvec, lightmap: UnsafeCvecArray): Cvec {
|
||||
// use equation with magic number 8.0
|
||||
// this function, when done recursively (A_x = darken(A_x-1, C)), draws exponential curve. (R^2 = 1)
|
||||
|
||||
@@ -736,10 +802,13 @@ object LightmapRenderer {
|
||||
private var _init = false
|
||||
|
||||
fun resize(screenW: Int, screenH: Int) {
|
||||
lightmapPrepared.set(false)
|
||||
/*
|
||||
// make sure the BlocksDrawer is resized first!
|
||||
|
||||
// copied from BlocksDrawer, duh!
|
||||
// FIXME 'lightBuffer' is not zoomable in this way
|
||||
|
||||
val tilesInHorizontal = (App.scr.wf / TILE_SIZE).ceilInt() + 1 + LIGHTMAP_OVERRENDER * 2
|
||||
val tilesInVertical = (App.scr.hf / TILE_SIZE).ceilInt() + 1 + LIGHTMAP_OVERRENDER * 2
|
||||
|
||||
@@ -754,14 +823,19 @@ object LightmapRenderer {
|
||||
}
|
||||
lightBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888)
|
||||
|
||||
|
||||
lightmap.destroy()
|
||||
_lightmap.destroy()
|
||||
_mapLightLevelThis.destroy()
|
||||
_mapThisTileOpacity.destroy()
|
||||
_mapThisTileOpacity2.destroy()
|
||||
lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
_lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
_mapLightLevelThis = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
_mapThisTileOpacity = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
_mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
|
||||
_mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)*/
|
||||
|
||||
lightmapPrepared.set(true)
|
||||
|
||||
printdbg(this, "Resize event")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user