randomised torch flicker

This commit is contained in:
minjaesong
2020-02-24 01:00:11 +09:00
parent 6c7fe9cf2b
commit 73c827b77f
10 changed files with 153 additions and 85 deletions

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.blockproperties
import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.AppLoader.printmsg
import net.torvald.terrarum.ReferencingRanges
import net.torvald.terrarum.gameworld.FluidType
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.utils.CSVFetcher
@@ -18,16 +19,25 @@ object BlockCodex {
private var blockProps = HashMap<Int, BlockProp>()
val dynamicLights = SortedArrayList<Int>()
val dynamicLights = SortedArrayList<Int>() // does not include virtual ones
/** 4096 */
const val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
private val nullProp = BlockProp()
var highestNumber = -1
var highestNumber = -1 // does not include virtual ones
private set
// fake props for "randomised" dynamic lights
const val DYNAMIC_RANDOM_CASES = 64
var virtualPropsCount = 0
private set
/** always points to the HIGHEST prop ID. <Original ID, Virtual ID> */
val dynamicToVirtualPropMapping = ArrayList<Pair<Int, Int>>()
/** for random access dont iterate over this */
val dynamicToVirtualMap = hashMapOf<Int, Int>()
/**
* Later entry (possible from other modules) will replace older ones
*/
@@ -48,8 +58,18 @@ object BlockCodex {
val id = intVal(it, "id")
setProp(id, it)
// register tiles with dynamic light
if ((blockProps[id]?.dynamicLuminosityFunction ?: 0) != 0) {
dynamicLights.add(id)
// add virtual props for dynamic lights
val virtualIDMax = ReferencingRanges.VIRTUAL_TILES.first - virtualPropsCount
dynamicToVirtualPropMapping.add(id to virtualIDMax)
dynamicToVirtualMap[id] = virtualIDMax
repeat(DYNAMIC_RANDOM_CASES) { i ->
setProp(virtualIDMax - i, it)
virtualPropsCount += 1
}
}
if (id > highestNumber)

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.blockproperties
import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.gameworld.fmod
/**
* Created by minjaesong on 2016-02-16.
@@ -49,11 +50,17 @@ class BlockProp {
internal var baseLumColB = 0f // base value used to calculate dynamic luminosity
internal var baseLumColA = 0f // base value used to calculate dynamic luminosity
internal val baseLumCol = Cvec(0)
var lumColR = 0f // memoised value of dynamic luminosity
var lumColG = 0f // memoised value of dynamic luminosity
var lumColB = 0f // memoised value of dynamic luminosity
var lumColA = 0f // memoised value of dynamic luminosity
var lumCol = Cvec(0)
//var lumColR = 0f // memoised value of dynamic luminosity
//var lumColG = 0f // memoised value of dynamic luminosity
//var lumColB = 0f // memoised value of dynamic luminosity
//var lumColA = 0f // memoised value of dynamic luminosity
internal val _lumCol = Cvec(0)
fun getLumCol(x: Int, y: Int) = if (dynamicLuminosityFunction == 0) {
baseLumCol
} else {
val offset = (x * 214013 + 2531011).ushr(16).fmod(BlockCodex.DYNAMIC_RANDOM_CASES)
BlockCodex[BlockCodex.dynamicToVirtualMap[id]!! - offset]._lumCol
}
/**
* @param luminosity
@@ -61,7 +68,7 @@ class BlockProp {
//inline val luminosity: Cvec
// get() = BlockPropUtil.getDynamicLumFunc(internalLumCol, dynamicLuminosityFunction)
fun getLum(channel: Int) = lumCol.getElem(channel)
//fun getLum(channel: Int) = lumCol.getElem(channel)
var drop: Int = 0
@@ -72,4 +79,8 @@ class BlockProp {
var dynamicLuminosityFunction: Int = 0
var material: String = ""
var rngBase0 = Math.random().toFloat() // initial cycle phase (xxxxFuncX)
var rngBase1 = Math.random().toFloat() // flicker P0, etc
var rngBase2 = Math.random().toFloat() // flicker P1, etc
}

View File

@@ -14,81 +14,50 @@ import net.torvald.terrarum.worlddrawer.LightmapRenderer
* Created by minjaesong on 2016-06-16.
*/
object BlockPropUtil {
var flickerFuncX: Second = 0f // saves current status (time) of func
//var flickerFuncX: Second = 0f // saves current status (time) of func
val flickerFuncDomain: Second = 0.08f // time between two noise sample
val flickerFuncRange = 0.012f // intensity [0, 1]
var breathFuncX = 0f
//var breathFuncX = 0f
val breathRange = 0.02f
val breathCycleDuration: Second = 2f
var pulsateFuncX = 0f
//var pulsateFuncX = 0f
val pulsateRange = 0.034f
val pulsateCycleDuration: Second = 0.5f
val random = HQRNG()
var flickerP0 = getNewRandom()
var flickerP1 = getNewRandom()
//var flickerP0 = getNewRandom()
//var flickerP1 = getNewRandom()
init {
}
private fun getTorchFlicker(baseLum: Cvec): Cvec {
val funcY = FastMath.interpolateLinear(flickerFuncX / flickerFuncDomain, flickerP0, flickerP1)
return alterBrightnessUniform(baseLum, funcY)
private fun getTorchFlicker(prop: BlockProp): Cvec {
val funcY = FastMath.interpolateLinear(prop.rngBase0 / flickerFuncDomain, prop.rngBase1, prop.rngBase2)
return alterBrightnessUniform(prop.baseLumCol, funcY)
}
private fun getTorchFlicker(baseLum: Float): Float {
return baseLum + FastMath.interpolateLinear(flickerFuncX / flickerFuncDomain, flickerP0, flickerP1)
private fun getSlowBreath(prop: BlockProp): Cvec {
val funcY = FastMath.sin(FastMath.PI * prop.rngBase0 / breathCycleDuration) * breathRange
return alterBrightnessUniform(prop.baseLumCol, funcY)
}
private fun getSlowBreath(baseLum: Cvec): Cvec {
val funcY = FastMath.sin(FastMath.PI * breathFuncX / breathCycleDuration) * breathRange
return alterBrightnessUniform(baseLum, funcY)
private fun getPulsate(prop: BlockProp): Cvec {
val funcY = FastMath.sin(FastMath.PI * prop.rngBase0 / pulsateCycleDuration) * pulsateRange
return alterBrightnessUniform(prop.baseLumCol, funcY)
}
private fun getSlowBreath(baseLum: Float): Float {
return baseLum + FastMath.sin(FastMath.PI * breathFuncX / breathCycleDuration) * breathRange
}
private fun getPulsate(baseLum: Cvec): Cvec {
val funcY = FastMath.sin(FastMath.PI * pulsateFuncX / pulsateCycleDuration) * pulsateRange
return alterBrightnessUniform(baseLum, funcY)
}
private fun getPulsate(baseLum: Float): Float {
return baseLum + FastMath.sin(FastMath.PI * pulsateFuncX / pulsateCycleDuration) * pulsateRange
}
/**
* Using our own timer so that they flickers for same duration regardless of game's FPS
*/
internal fun dynamicLumFuncTickClock() {
// FPS-time compensation
if (Gdx.graphics.framesPerSecond > 0) {
flickerFuncX += Gdx.graphics.rawDeltaTime
breathFuncX += Gdx.graphics.rawDeltaTime
pulsateFuncX += Gdx.graphics.rawDeltaTime
}
// flicker-related vars
if (flickerFuncX > flickerFuncDomain) {
flickerFuncX -= flickerFuncDomain
flickerP0 = flickerP1
flickerP1 = getNewRandom()
}
// breath-related vars
if (breathFuncX > breathCycleDuration) breathFuncX -= breathCycleDuration
// pulsate-related vars
if (pulsateFuncX > pulsateCycleDuration) pulsateFuncX -= pulsateCycleDuration
// update the memoised values in props
for (key in BlockCodex.dynamicLights) {
/*for (key in BlockCodex.dynamicLights) {
try {
val prop = BlockCodex[key]
if (prop.dynamicLuminosityFunction != 0) {
@@ -100,6 +69,38 @@ object BlockPropUtil {
}
}
catch (skip: NullPointerException) {}
}*/
// update randomised virtual props instead
for (keyMax in BlockCodex.dynamicToVirtualPropMapping) {
repeat(BlockCodex.DYNAMIC_RANDOM_CASES) {
val prop = BlockCodex[keyMax.second - it]
val domain = when (prop.dynamicLuminosityFunction) {
1 -> flickerFuncDomain
4 -> breathCycleDuration
5 -> pulsateCycleDuration
else -> 0f
}
// FPS-time compensation
if (Gdx.graphics.framesPerSecond > 0) {
prop.rngBase0 += Gdx.graphics.rawDeltaTime
}
// reset timer
if (prop.rngBase0 > domain) {
prop.rngBase0 -= domain
// flicker related
prop.rngBase1 = prop.rngBase2
prop.rngBase2 = getNewRandom()
}
prop._lumCol.set(getDynamicLumFunc(prop))
//prop.lumColR = prop.lumCol.r
//prop.lumColG = prop.lumCol.g
//prop.lumColB = prop.lumCol.b
//prop.lumColA = prop.lumCol.a
}
}
}
@@ -107,21 +108,21 @@ object BlockPropUtil {
private fun linearInterpolation1D(a: Float, b: Float, x: Float) = a * (1 - x) + b * x
private fun getDynamicLumFunc(baseLum: Cvec, type: Int): Cvec {
return when (type) {
1 -> getTorchFlicker(baseLum)
private fun getDynamicLumFunc(prop: BlockProp): Cvec {
return when (prop.dynamicLuminosityFunction) {
1 -> getTorchFlicker(prop)
2 -> (Terrarum.ingame!!.world).globalLight.cpy().mul(LightmapRenderer.DIV_FLOAT) // current global light
3 -> WeatherMixer.getGlobalLightOfTime(Terrarum.ingame!!.world, WorldTime.DAY_LENGTH / 2).cpy().mul(LightmapRenderer.DIV_FLOAT) // daylight at noon
4 -> getSlowBreath(baseLum)
5 -> getPulsate(baseLum)
else -> baseLum
4 -> getSlowBreath(prop)
5 -> getPulsate(prop)
else -> prop.baseLumCol
}
}
/**
* @param chan 0 for R, 1 for G, 2 for B, 3 for A
*/
private fun getDynamicLumFuncByChan(baseLum: Float, type: Int, chan: Int): Float {
/*private fun getDynamicLumFuncByChan(baseLum: Float, type: Int, chan: Int): Float {
return when (type) {
1 -> getTorchFlicker(baseLum)
2 -> (Terrarum.ingame!!.world).globalLight.cpy().mul(LightmapRenderer.DIV_FLOAT).getElem(chan) // current global light
@@ -130,7 +131,7 @@ object BlockPropUtil {
5 -> getPulsate(baseLum)
else -> baseLum
}
}
}*/
/**
* Darken or brighten colour by 'brighten' argument