cavegen after the oregen

This commit is contained in:
minjaesong
2023-11-04 00:54:15 +09:00
parent 1128fb7f0e
commit 6ae39d38e3
6 changed files with 188 additions and 113 deletions

Binary file not shown.

View File

@@ -23,6 +23,9 @@ open class FancyWorldReadLoadScreen(screenToBeLoaded: IngameInstance, private va
CommonResourcePool.addToLoadingList("basegame-gui-loadscrlayer02") {
Texture(ModMgr.getGdxFile("basegame", "gui/loadscr_layer02.png"))
}
CommonResourcePool.addToLoadingList("basegame-gui-loadscrlayer03") {
Texture(ModMgr.getGdxFile("basegame", "gui/loadscr_layer03.png"))
}
CommonResourcePool.loadAll()
App.disposables.add(this)
@@ -44,6 +47,7 @@ open class FancyWorldReadLoadScreen(screenToBeLoaded: IngameInstance, private va
val baseTileTex = arrayOf(
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer01"),
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer02"),
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer03"),
)
val drawWidth = Toolkit.drawWidth
@@ -88,7 +92,7 @@ open class FancyWorldReadLoadScreen(screenToBeLoaded: IngameInstance, private va
}
protected open fun getStage(): Int {
return 2 // fixed value for Read screen
return 3 // fixed value for Read screen
}
protected val batchColour = Color(-1) // create new Color instance just for the progress bar

View File

@@ -0,0 +1,169 @@
package net.torvald.terrarum.modulebasegame.worldgenerator
import com.sudoplay.joise.Joise
import com.sudoplay.joise.module.*
import net.torvald.random.XXHash32
import net.torvald.terrarum.App
import net.torvald.terrarum.LoadScreenBase
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.concurrent.sliceEvenly
import net.torvald.terrarum.gameworld.GameWorld
import kotlin.math.cos
import kotlin.math.sin
/**
* Created by minjaesong on 2023-11-04.
*/
class Cavegen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, seed: Long, params: Any) : Gen(world, seed, params) {
companion object {
const val YHEIGHT_MAGIC = 2800.0 / 3.0
const val YHEIGHT_DIVISOR = 2.0 / 7.0
}
override fun getDone(loadscreen: LoadScreenBase) {
loadscreen.stageValue += 1
loadscreen.progress.set(0L)
Worldgen.threadExecutor.renew()
(0 until world.width).sliceEvenly(Worldgen.genSlices).mapIndexed { i, xs ->
Worldgen.threadExecutor.submit {
val localJoise = getGenerator(seed, params as TerragenParams)
for (x in xs) {
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
val sampleOffset = world.width / 8.0
draw(x, localJoise, sampleTheta, sampleOffset)
}
loadscreen.progress.addAndGet((xs.last - xs.first + 1).toLong())
}
}
Worldgen.threadExecutor.join()
App.printdbg(this, "Waking up Worldgen")
}
//private fun draw(x: Int, y: Int, width: Int, height: Int, noiseValue: List<Double>, world: GameWorld) {
private fun draw(x: Int, noises: List<Joise>, st: Double, soff: Double) {
for (y in 0 until world.height) {
val sx = sin(st) * soff + soff // plus sampleOffset to make only
val sz = cos(st) * soff + soff // positive points are to be sampled
val sy = y - (world.height - YHEIGHT_MAGIC) * YHEIGHT_DIVISOR // Q&D offsetting to make ratio of sky:ground to be constant
// DEBUG NOTE: it is the OFFSET FROM THE IDEAL VALUE (observed land height - (HEIGHT * DIVISOR)) that must be constant
val noiseValue = noises.map { it.get(sx, sy, sz) }
val cave = if (noiseValue[0] < 0.5) 0 else 1
if (cave == 0) {
world.setTileTerrain(x, y, Block.AIR, true)
}
}
}
private fun getGenerator(seed: Long, params: TerragenParams): List<Joise> {
val caveMagic: Long = 0x00215741CDF // Urist McDF
val cavePerturbMagic: Long = 0xA2410C // Armok
val caveBlockageMagic: Long = 0xD15A57E5 // Disaster
/* caves */
val caveShape = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(1)
it.setFrequency(params.caveShapeFreq) // adjust the "density" of the caves
it.seed = seed shake caveMagic
}
val caveAttenuateBias = ModuleBias().also {
it.setSource(highlandLowlandSelectCache)
it.setBias(params.caveAttenuateBias) // (0.5+) adjust the "concentration" of the cave gen. Lower = larger voids
}
val caveShapeAttenuate = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.MULT)
it.setSource(0, caveShape)
it.setSource(1, caveAttenuateBias)
}
val cavePerturbFractal = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.FBM)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(6)
it.setFrequency(params.caveShapeFreq * 3.0 / 4.0)
it.seed = seed shake cavePerturbMagic
}
val cavePerturbScale = ModuleScaleOffset().also {
it.setSource(cavePerturbFractal)
it.setScale(0.45)
it.setOffset(0.0)
}
val cavePerturb = ModuleTranslateDomain().also {
it.setSource(caveShapeAttenuate)
it.setAxisXSource(cavePerturbScale)
}
val caveSelect = ModuleSelect().also {
it.setLowSource(1.0)
it.setHighSource(0.0)
it.setControlSource(cavePerturb)
it.setThreshold(params.caveSelectThre) // also adjust this if you've touched the bias value. Number can be greater than 1.0
it.setFalloff(0.0)
}
val caveBlockageFractal = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(2)
it.setFrequency(params.caveBlockageFractalFreq) // same as caveShape frequency?
it.seed = seed shake caveBlockageMagic
}
// will only close-up deeper caves. Shallow caves will be less likely to be closed up
val caveBlockageAttenuate = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.MULT)
it.setSource(0, caveBlockageFractal)
it.setSource(1, caveAttenuateBias)
}
val caveBlockageSelect = ModuleSelect().also {
it.setLowSource(0.0)
it.setHighSource(1.0)
it.setControlSource(caveBlockageAttenuate)
it.setThreshold(params.caveBlockageSelectThre) // adjust cave cloing-up strength. Larger = more closing
it.setFalloff(0.0)
}
// note: gradient-multiply DOESN'T generate "naturally cramped" cave entrance
val caveInMix = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.ADD)
it.setSource(0, caveSelect)
it.setSource(1, caveBlockageSelect)
}
val caveClamp = ModuleClamp().also {
it.setRange(0.0, 1.0)
it.setSource(caveInMix)
}
val caveScaling = ModuleScaleDomain().also {
it.setScaleX(1.0 / params.featureSize) // adjust this value to change features size
it.setScaleY(1.0 / params.featureSize)
it.setScaleZ(1.0 / params.featureSize)
it.setSource(caveClamp)
}
return listOf(
Joise(caveScaling)
)
}
}

View File

@@ -74,7 +74,6 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
val noiseValue = noises.map { it.get(sx, sy, sz) }
val terr = noiseValue[0].tiered(.0, .5, .88, 1.88)
val cave = if (noiseValue[1] < 0.5) 0 else 1
// mark off the position where the transition occurred
if (dirtStoneTransition == 0 && terr == 2)
@@ -83,7 +82,7 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
stoneSlateTransition = y
val wallBlock = groundDepthBlock[terr]
val terrBlock = if (cave == 0) Block.AIR else wallBlock
val terrBlock = wallBlock
world.setTileTerrain(x, y, terrBlock, true)
world.setTileWall(x, y, wallBlock, true)
@@ -103,14 +102,14 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
val y = pos + dirtStoneTransition - (dirtStoneDitherSize * 2) + 1
if (y >= world.height) break
val hash = XXHash32.hashGeoCoord(x, y).and(0x7FFFFFFF) / 2147483647.0
val fore = world.getTileFromTerrain(x, y)
val back = world.getTileFromWall(x, y)
// val fore = world.getTileFromTerrain(x, y)
// val back = world.getTileFromWall(x, y)
val newTile = if (pos < dirtStoneDitherSize)
if (hash < pos.toDouble() / dirtStoneDitherSize) Block.STONE_QUARRIED else Block.DIRT
else // don't +1 to pos.toDouble(); I've suffered
if (hash >= (pos.toDouble() - dirtStoneDitherSize) / dirtStoneDitherSize) Block.STONE_QUARRIED else Block.STONE
if (fore != Block.AIR)
// if (fore != Block.AIR)
world.setTileTerrain(x, y, newTile, true)
world.setTileWall(x, y, newTile, true)
@@ -125,11 +124,11 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
val y = pos + stoneSlateTransition - stoneSlateDitherSize + 1
if (y >= world.height) break
val hash = XXHash32.hashGeoCoord(x, y).and(0x7FFFFFFF) / 2147483647.0
val fore = world.getTileFromTerrain(x, y)
val back = world.getTileFromWall(x, y)
// val fore = world.getTileFromTerrain(x, y)
// val back = world.getTileFromWall(x, y)
val newTile = if (hash < pos.toDouble() / stoneSlateDitherSize) Block.STONE_SLATE else Block.STONE
if (fore != Block.AIR)
// if (fore != Block.AIR)
world.setTileTerrain(x, y, newTile, true)
world.setTileWall(x, y, newTile, true)
@@ -138,92 +137,6 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
private fun getGenerator(seed: Long, params: TerragenParams): List<Joise> {
val caveMagic: Long = 0x00215741CDF // Urist McDF
val cavePerturbMagic: Long = 0xA2410C // Armok
val caveBlockageMagic: Long = 0xD15A57E5 // Disaster
/* caves */
val caveShape = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(1)
it.setFrequency(params.caveShapeFreq) // adjust the "density" of the caves
it.seed = seed shake caveMagic
}
val caveAttenuateBias = ModuleBias().also {
it.setSource(highlandLowlandSelectCache)
it.setBias(params.caveAttenuateBias) // (0.5+) adjust the "concentration" of the cave gen. Lower = larger voids
}
val caveShapeAttenuate = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.MULT)
it.setSource(0, caveShape)
it.setSource(1, caveAttenuateBias)
}
val cavePerturbFractal = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.FBM)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(6)
it.setFrequency(params.caveShapeFreq * 3.0 / 4.0)
it.seed = seed shake cavePerturbMagic
}
val cavePerturbScale = ModuleScaleOffset().also {
it.setSource(cavePerturbFractal)
it.setScale(0.45)
it.setOffset(0.0)
}
val cavePerturb = ModuleTranslateDomain().also {
it.setSource(caveShapeAttenuate)
it.setAxisXSource(cavePerturbScale)
}
val caveSelect = ModuleSelect().also {
it.setLowSource(1.0)
it.setHighSource(0.0)
it.setControlSource(cavePerturb)
it.setThreshold(params.caveSelectThre) // also adjust this if you've touched the bias value. Number can be greater than 1.0
it.setFalloff(0.0)
}
val caveBlockageFractal = ModuleFractal().also {
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
it.setNumOctaves(2)
it.setFrequency(params.caveBlockageFractalFreq) // same as caveShape frequency?
it.seed = seed shake caveBlockageMagic
}
// will only close-up deeper caves. Shallow caves will be less likely to be closed up
val caveBlockageAttenuate = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.MULT)
it.setSource(0, caveBlockageFractal)
it.setSource(1, caveAttenuateBias)
}
val caveBlockageSelect = ModuleSelect().also {
it.setLowSource(0.0)
it.setHighSource(1.0)
it.setControlSource(caveBlockageAttenuate)
it.setThreshold(params.caveBlockageSelectThre) // adjust cave cloing-up strength. Larger = more closing
it.setFalloff(0.0)
}
// note: gradient-multiply DOESN'T generate "naturally cramped" cave entrance
val caveInMix = ModuleCombiner().also {
it.setType(ModuleCombiner.CombinerType.ADD)
it.setSource(0, caveSelect)
it.setSource(1, caveBlockageSelect)
}
// this noise tree WILL generate noise value greater than 1.0
// they should be treated properly when you actually generate the world out of the noisemap
// for the visualisation, no treatment will be done in this demo app.
@@ -240,23 +153,8 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se
it.setSource(groundClamp)
}
val caveClamp = ModuleClamp().also {
it.setRange(0.0, 1.0)
it.setSource(caveInMix)
}
val caveScaling = ModuleScaleDomain().also {
it.setScaleX(1.0 / params.featureSize) // adjust this value to change features size
it.setScaleY(1.0 / params.featureSize)
it.setScaleZ(1.0 / params.featureSize)
it.setSource(caveClamp)
}
//return Joise(caveInMix)
return listOf(
Joise(groundScaling),
Joise(caveScaling)
Joise(groundScaling)
)
}
}

View File

@@ -60,6 +60,7 @@ object Worldgen {
Work("Reticulating Splines", Terragen(world, highlandLowlandSelectCache, params.seed, params.terragenParams), listOf("TERRAIN")),
Work("Adding Rocks", Oregen(world, caveAttenuateBiasScaled, params.seed, oreRegistry), listOf("ORES")),
Work("Positioning Rocks", OregenAutotiling(world, params.seed, oreTilingModes), listOf("ORES")),
Work("Carving", Cavegen(world, highlandLowlandSelectCache, params.seed, params.terragenParams), listOf("TERRAIN", "CAVE")),
Work("Adding Vegetations", Biomegen(world, params.seed, params.biomegenParams), listOf("BIOME")),
).filter(tagFilter)
}