cloud stage has more depth

This commit is contained in:
minjaesong
2023-09-06 18:01:33 +09:00
parent 7259ca616c
commit 6c97a9d5ab
13 changed files with 93 additions and 48 deletions

View File

@@ -29,18 +29,26 @@ data class BaseModularWeather(
val cloudGamma: Vector2,
val cloudGammaVariance: Vector2,
var clouds: List<CloudProps>, // sorted by CloudProps.probability
val shaderVibrancy: FloatArray,
val mixFrom: String? = null,
val mixPercentage: Double? = null,
) {
/**
* @param rnd random number between -1 and +1
*/
fun getRandomWindSpeed(old: Float, rnd: Float): Float {
val v = 1f + rnd.absoluteValue * windSpeedVariance
val r = if (rnd < 0) windSpeed / v else windSpeed * v
return FastMath.interpolateLinear(windSpeedDamping, old, r)
return FastMath.interpolateLinear(1f - windSpeedDamping, old, r)
}
fun getRandomWindSpeed(rnd: Float): Float {
val v = 1f + rnd.absoluteValue * windSpeedVariance
val r = if (rnd < 0) windSpeed / v else windSpeed * v
return r
}
fun getRandomCloudGamma(rnd1: Float, rnd2: Float): Vector2 {

View File

@@ -64,7 +64,8 @@ internal object WeatherMixer : RNGConsumer {
0f,
Vector2(1f, 1f),
Vector2(0f, 0f),
listOf()
listOf(),
floatArrayOf(1f, 1f)
)
override val RNG = HQRNG()
@@ -169,7 +170,7 @@ internal object WeatherMixer : RNGConsumer {
weatherDB[weather.classification]!!.add(weather)
}
weatherDict["titlescreen"] = weatherDB[WEATHER_GENERIC]!![0].copy(windSpeed = 1f)
weatherDict["titlescreen"] = weatherDB[WEATHER_GENERIC]!![0].copy(identifier = "titlescreen", windSpeed = 1f)
}
/**
@@ -459,7 +460,8 @@ internal object WeatherMixer : RNGConsumer {
}
private fun initClouds(currentWeather: BaseModularWeather) {
val hCloudSize = 1024f
clouds.clear()
cloudsSpawned = 0
// multiplier is an empirical value that depends on the 'rZ'
// it does converge at ~6, but having it as an initial state does not make it stay converged
repeat((currentWeather.cloudChance * 1.333f).ceilToInt()) {
@@ -731,13 +733,6 @@ internal object WeatherMixer : RNGConsumer {
val skyboxInJson = JSON.getString("skyboxGradColourMap")
val lightbox = JSON.getString("daylightClut")
val skybox = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}"))
val daylight = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}"))
val identifier = JSON.getString("identifier")
val classification = JSON.getString("classification")
val cloudsMap = ArrayList<CloudProps>()
val clouds = JSON["clouds"]
clouds.forEachSiblings { name, json ->
@@ -755,13 +750,12 @@ internal object WeatherMixer : RNGConsumer {
return BaseModularWeather(
identifier = identifier,
identifier = JSON.getString("identifier"),
json = JSON,
skyboxGradColourMap = skybox,
daylightClut = daylight,
classification = classification,
skyboxGradColourMap = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}")),
daylightClut = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}")),
classification = JSON.getString("classification"),
cloudChance = JSON.getFloat("cloudChance"),
windSpeed = JSON.getFloat("windSpeed"),
windSpeedVariance = JSON.getFloat("windSpeedVariance"),
@@ -769,6 +763,7 @@ internal object WeatherMixer : RNGConsumer {
cloudGamma = JSON["cloudGamma"].asFloatArray().let { Vector2(it[0], it[1]) },
cloudGammaVariance = JSON["cloudGammaVariance"].asFloatArray().let { Vector2(it[0], it[1]) },
clouds = cloudsMap,
shaderVibrancy = JSON["shaderVibrancy"].asFloatArray()
)
}

View File

@@ -5,12 +5,11 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.math.Vector3
import com.jme3.math.FastMath
import com.jme3.math.FastMath.PI
import com.jme3.math.FastMath.sin
import net.torvald.terrarum.App
import net.torvald.terrarum.gameworld.GameWorld
import kotlin.math.absoluteValue
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.sign
import kotlin.math.*
/**
* Created by minjaesong on 2023-08-21.
@@ -47,7 +46,7 @@ class WeatherObjectCloud(
scl(world.worldTime.timeDelta.toFloat())
)
eigenAlpha = if (posZ < 1f) posZ.pow(0.5f) else -((posZ - 1f) / ALPHA_ROLLOFF_Z) + 1f
eigenAlpha = if (posZ < 1f) posZ.pow(0.5f) else cosh((posZ - CLOUD_STAGE_DEPTH) / (0.75636f * CLOUD_STAGE_DEPTH)) - 1f //-((posZ - 1f) / CLOUD_STAGE_DEPTH) + 1f
val alphaMult = if (life < NEWBORN_GROWTH_TIME)
life / NEWBORN_GROWTH_TIME
@@ -60,13 +59,13 @@ class WeatherObjectCloud(
val lrCoord = screenCoordBottomLRforDespawnCalculation
if (lrCoord.x > WeatherMixer.oobMarginR || lrCoord.z < WeatherMixer.oobMarginL || posZ !in 0.0001f..ALPHA_ROLLOFF_Z + 1f || alpha < 0f) {
if (lrCoord.x > WeatherMixer.oobMarginR || lrCoord.z < WeatherMixer.oobMarginL || posZ !in 0.0001f..CLOUD_STAGE_DEPTH + 1f || alpha < 0f) {
flagToDespawn = true
despawnCode = if (lrCoord.x > WeatherMixer.oobMarginR) "OUT_OF_SCREEN_RIGHT"
else if (lrCoord.z < WeatherMixer.oobMarginL) "OUT_OF_SCREEN_LEFT"
else if (posZ < 0.0001f) "OUT_OF_SCREEN_TOO_CLOSE"
else if (posZ > ALPHA_ROLLOFF_Z + 1f) "OUT_OF_SCREEN_TOO_FAR"
else if (posZ > CLOUD_STAGE_DEPTH + 1f) "OUT_OF_SCREEN_TOO_FAR"
else if (life >= lifespan + OLD_AGE_DECAY) "OLD_AGE"
else if (alpha < 0f) "ALPHA_BELOW_ZERO"
else "UNKNOWN"
@@ -180,6 +179,7 @@ class WeatherObjectCloud(
fun worldYtoWorldZforScreenYof0(y: Float) = 1f - (y / H) // rearrange screenCoord equations to derive this eq :p
const val ALPHA_ROLLOFF_Z = 64f
const val CLOUD_STAGE_DEPTH = 256f
const val OLD_AGE_DECAY = 5000f
const val NEWBORN_GROWTH_TIME = 1000f

View File

@@ -1,12 +1,11 @@
package net.torvald.terrarum.weather
import com.badlogic.gdx.math.Vector2
import com.jme3.math.FastMath
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.floorToInt
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod
import org.apache.commons.math3.analysis.UnivariateFunction
import org.apache.commons.math3.analysis.interpolation.NevilleInterpolator
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator
import java.util.*
data class WeatherSchedule(val weather: BaseModularWeather = WeatherMixer.DEFAULT_WEATHER, val duration: Long = 3600)
@@ -37,25 +36,37 @@ class Weatherbox {
val windDir = WeatherDirBox() // 0 .. 1.0
val windSpeed = WeatherStateBox() // 0 .. arbitrarily large number
val weatherSchedule: MutableList<WeatherSchedule> = mutableListOf<WeatherSchedule>()
val currentWeather: BaseModularWeather
val weatherSchedule = ArrayList<WeatherSchedule>()
val oldWeather: BaseModularWeather
get() = weatherSchedule[0].weather
val currentWeatherDuration: Long
val currentWeather: BaseModularWeather
get() = weatherSchedule[1].weather
// val nextWeather: BaseModularWeather
// get() = weatherSchedule[2].weather
val oldWeatherDuration: Long
get() = weatherSchedule[0].duration
val currentWeatherDuration: Long
get() = weatherSchedule[1].duration
@Transient val currentVibrancy = Vector2(1f, 1f)
val weatherBlend: Float
get() = updateAkku.toFloat() / currentWeatherDuration
fun initWith(initWeather: BaseModularWeather, duration: Long) {
weatherSchedule.clear()
weatherSchedule.add(WeatherSchedule(initWeather, duration))
weatherSchedule.add(WeatherSchedule(initWeather, duration))
}
var updateAkku = 0L; private set
fun update(world: GameWorld) {
updateShaderParams()
updateWind(world)
if (updateAkku >= currentWeatherDuration) {
// TODO add more random weathers
if (weatherSchedule.size == 1) {
while (weatherSchedule.size < 3) {
val newName = if (currentWeather.identifier == "generic01") "overcast01" else "generic01"
val newDuration = 7200L
weatherSchedule.add(WeatherSchedule(WeatherMixer.weatherDict[newName]!!, newDuration))
@@ -64,7 +75,10 @@ class Weatherbox {
}
// subtract akku by old currentWeatherDuration
updateAkku -= weatherSchedule.removeAt(0).duration
// printdbg(this, "Dequeueing a weather")
weatherSchedule.removeAt(0)
updateAkku -= oldWeatherDuration
}
updateAkku += world.worldTime.timeDelta
@@ -76,6 +90,15 @@ class Weatherbox {
}
windDir.update( world.worldTime.timeDelta / WIND_DIR_TIME_UNIT) { RNG.nextFloat() * 4f }
}
private fun updateShaderParams() {
val (co, cg) = oldWeather.shaderVibrancy
val (no, ng) = currentWeather.shaderVibrancy
currentVibrancy.set(
FastMath.interpolateLinear(weatherBlend * 2, co, no),
FastMath.interpolateLinear(weatherBlend * 2, cg, ng),
)
}
}