mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
strata implemented
This commit is contained in:
@@ -16,10 +16,24 @@ import kotlin.math.sin
|
||||
/**
|
||||
* Created by minjaesong on 2019-07-23.
|
||||
*/
|
||||
class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: ModuleCache, seed: Long, params: Any) : Gen(world, isFinal, seed, params) {
|
||||
class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: ModuleCache, val landBlock: ModuleCache, seed: Long, params: Any) : Gen(world, isFinal, seed, params) {
|
||||
|
||||
private val isAlpha2 = ((params as TerragenParams).versionSince >= 0x0000_000004_000004)
|
||||
|
||||
private lateinit var strataCache: Array<List<StratumObj>>
|
||||
private lateinit var groundDepthBlocksCache: Array<List<ItemID>>
|
||||
private lateinit var terragenTiersCache: Array<List<Double>>
|
||||
|
||||
private val terragenYscaling =
|
||||
if (isAlpha2)
|
||||
1.0
|
||||
else
|
||||
(world.height / 2400.0).pow(0.75)
|
||||
|
||||
init {
|
||||
populateCaches(seed)
|
||||
}
|
||||
|
||||
override fun getDone(loadscreen: LoadScreenBase?) {
|
||||
loadscreen?.let {
|
||||
it.stageValue += 1
|
||||
@@ -31,6 +45,18 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu
|
||||
Worldgen.threadExecutor.join()
|
||||
}
|
||||
|
||||
private fun populateCaches(seed: Long) {
|
||||
val params = params as TerragenParams
|
||||
strataCache = Array(params.LANDBLOCK_VAR_COUNTS) {
|
||||
params.getStrataForMode(seed, it)
|
||||
}
|
||||
groundDepthBlocksCache = Array(params.LANDBLOCK_VAR_COUNTS) {
|
||||
strataCache[it].map { it.tiles }
|
||||
}
|
||||
terragenTiersCache = Array(params.LANDBLOCK_VAR_COUNTS) {
|
||||
strataCache[it].map { it.yheight * terragenYscaling }
|
||||
}
|
||||
}
|
||||
|
||||
private fun Double.tiered(tiers: List<Double>): Int {
|
||||
tiers.reversed().forEachIndexed { index, it ->
|
||||
@@ -39,22 +65,9 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu
|
||||
return tiers.lastIndex
|
||||
}
|
||||
|
||||
private val terragenYscaling =
|
||||
if (isAlpha2)
|
||||
1.0
|
||||
else
|
||||
(world.height / 2400.0).pow(0.75)
|
||||
|
||||
//private fun draw(x: Int, y: Int, width: Int, height: Int, noiseValue: List<Double>, world: GameWorld) {
|
||||
override fun draw(xStart: Int, yStart: Int, noises: List<Joise>, soff: Double) {
|
||||
val strataMode = if (!isAlpha2)
|
||||
0
|
||||
else
|
||||
1// TODO
|
||||
|
||||
val strata = (params as TerragenParams).getStrataForMode(seed, strataMode)
|
||||
val groundDepthBlock = strata.map { it.tiles }
|
||||
val terragenTiers = strata.map { it.yheight * terragenYscaling }
|
||||
val params = params as TerragenParams
|
||||
|
||||
for (x in xStart until xStart + CHUNK_W) {
|
||||
val st = (x.toDouble() / world.width) * TWO_PI
|
||||
@@ -66,69 +79,21 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu
|
||||
// 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 terr = noiseValue[0].tiered(terragenTiers)
|
||||
val strataMode = if (!isAlpha2)
|
||||
0
|
||||
else
|
||||
noiseValue[1].times(params.LANDBLOCK_VAR_COUNTS).toInt().coerceIn(0, params.LANDBLOCK_VAR_COUNTS - 1)
|
||||
|
||||
val terrTier = noiseValue[0].tiered(terragenTiersCache[strataMode])
|
||||
|
||||
val isMarble = if (!isAlpha2) noiseValue[1] > 0.5 else false
|
||||
|
||||
val wallBlock = if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr]
|
||||
val terrBlock = if (isMarble) Block.STONE_MARBLE else wallBlock
|
||||
val block = if (isMarble) Block.STONE_MARBLE else groundDepthBlocksCache[strataMode][terrTier]
|
||||
//groundDepthBlocksCache[strataMode][terr]
|
||||
|
||||
world.setTileTerrain(x, y, terrBlock, true)
|
||||
world.setTileWall(x, y, wallBlock, true)
|
||||
world.setTileTerrain(x, y, block, true)
|
||||
world.setTileWall(x, y, block, true)
|
||||
}
|
||||
|
||||
|
||||
// dither shits
|
||||
/*
|
||||
#
|
||||
# - dirt-to-cobble transition, height = dirtStoneDitherSize
|
||||
#
|
||||
%
|
||||
% - cobble-to-rock transition, height = dirtStoneDitherSize
|
||||
%
|
||||
* - where the stone layer actually begins
|
||||
*/
|
||||
/*if (dirtStoneTransition >= 0) {
|
||||
for (pos in 0 until dirtStoneDitherSize * 2) {
|
||||
val y = pos + dirtStoneTransition - (dirtStoneDitherSize * 2) + 1
|
||||
if (y >= world.height) break
|
||||
val hash = XXHash32.hashGeoCoord(x, y).and(0xFFFFFF) / 16777216.0
|
||||
// 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 (y in yStart until yStart + CHUNK_H) {
|
||||
world.setTileTerrain(x, y, newTile, true)
|
||||
world.setTileWall(x, y, newTile, true)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
#
|
||||
# - stone-to-slate transition, height = stoneSlateDitherSize
|
||||
#
|
||||
*/
|
||||
/*if (stoneSlateTransition >= 0) {
|
||||
for (pos in 0 until stoneSlateDitherSize) {
|
||||
val y = pos + stoneSlateTransition - stoneSlateDitherSize + 1
|
||||
if (y >= world.height) break
|
||||
val hash = XXHash32.hashGeoCoord(x, y).and(0xFFFFFF) / 16777216.0
|
||||
// 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 (y in yStart until yStart + CHUNK_H) {
|
||||
// if (fore != Block.AIR)
|
||||
world.setTileTerrain(x, y, newTile, true)
|
||||
world.setTileWall(x, y, newTile, true)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +116,10 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu
|
||||
)
|
||||
}
|
||||
else
|
||||
listOf(Joise(groundScalingCached))
|
||||
listOf(
|
||||
Joise(groundScalingCached),
|
||||
Joise(landBlock),
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateRockLayer(ground: Module, seed: Long, params: TerragenParams, thicknessAndRange: List<Pair<Double, Double>>): Module {
|
||||
|
||||
@@ -59,6 +59,7 @@ object Worldgen {
|
||||
params = genParams
|
||||
|
||||
highlandLowlandSelectCache = getHighlandLowlandSelectCache(params.terragenParams, params.seed)
|
||||
landBlock = getLandBlock(params.terragenParams, params.seed)
|
||||
caveAttenuateBiasScaledForOresCache = getCaveAttenuateBiasScaled(highlandLowlandSelectCache, params.terragenParams)
|
||||
groundScalingCached = getGroundScalingCached(highlandLowlandSelectCache, params.terragenParams)
|
||||
biomeMap = HashMap()
|
||||
@@ -67,6 +68,7 @@ object Worldgen {
|
||||
}
|
||||
|
||||
internal lateinit var groundScalingCached: ModuleCache
|
||||
internal lateinit var landBlock: ModuleCache
|
||||
internal lateinit var highlandLowlandSelectCache: ModuleCache
|
||||
internal lateinit var caveAttenuateBiasScaledForOresCache: ModuleCache
|
||||
internal lateinit var biomeMap: HashMap<BlockAddress, Byte>
|
||||
@@ -95,7 +97,7 @@ object Worldgen {
|
||||
else { work: Work -> (work.tags union tags).isNotEmpty() }
|
||||
|
||||
return listOf(
|
||||
Work(Lang["MENU_IO_WORLDGEN_RETICULATING_SPLINES"], Terragen(world, false, groundScalingCached, params.seed, params.terragenParams), listOf("TERRAIN")), // also generates marble veins
|
||||
Work(Lang["MENU_IO_WORLDGEN_RETICULATING_SPLINES"], Terragen(world, false, groundScalingCached, landBlock, params.seed, params.terragenParams), listOf("TERRAIN")), // also generates marble veins
|
||||
Work(Lang["MENU_IO_WORLDGEN_CARVING_EARTH"], Cavegen(world, false, highlandLowlandSelectCache, params.seed, params.terragenParams), listOf("TERRAIN", "CAVE")),
|
||||
Work(Lang["MENU_IO_WORLDGEN_FLOODING_UNDERGROUND"], Aquagen(world, false, groundScalingCached, params.seed, params.terragenParams), listOf("WATER")),
|
||||
Work(Lang["MENU_IO_WORLDGEN_GROWING_MINERALS"], Oregen(world, false, caveAttenuateBiasScaledForOresCache, params.seed, oreRegistry, params.terragenParams), listOf("ORES")),
|
||||
@@ -208,6 +210,16 @@ object Worldgen {
|
||||
private val rockScoreMin = 40
|
||||
private val treeScoreMin = 25
|
||||
|
||||
private fun Int.inChunk() = (this / CHUNK_W) % 2 == 0
|
||||
|
||||
private fun getRandomX(): Int {
|
||||
var posX = (Math.random() * world.width).toInt()
|
||||
while (!posX.inChunk())
|
||||
posX = (Math.random() * world.width).toInt()
|
||||
|
||||
return posX
|
||||
}
|
||||
|
||||
private fun tryForSpawnPoint(world: GameWorld): Point2i {
|
||||
val yInit = getChunkGenStrip(world).first
|
||||
val tallies = ArrayList<Pair<Point2i, Vector3f>>() // xypos, score (0..1+)
|
||||
@@ -215,7 +227,7 @@ object Worldgen {
|
||||
var found = false
|
||||
val ySearchRadius = 30
|
||||
while (tries < 99) {
|
||||
val posX = (Math.random() * world.width).toInt()
|
||||
val posX = getRandomX()
|
||||
var posY = yInit * CHUNK_H
|
||||
// go up?
|
||||
if (BlockCodex[world.getTileFromTerrain(posX, posY)].isSolid) {
|
||||
@@ -441,6 +453,55 @@ object Worldgen {
|
||||
return highlandLowlandSelectCache
|
||||
}
|
||||
|
||||
private fun getLandBlock(params: TerragenParams, seed: Long): ModuleCache {
|
||||
val landBlock = ModuleScaleDomain().also {
|
||||
it.setSource(ModuleFractal().also {
|
||||
it.setType(ModuleFractal.FractalType.DECARPENTIERSWISS)
|
||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||
it.setNumOctaves(2)
|
||||
it.setFrequency(params.landBlockScale / params.featureSize)
|
||||
it.seed = seed shake "LandBlock"
|
||||
})
|
||||
it.setScaleX(1.0 / 4.0)
|
||||
it.setScaleZ(1.0 / 4.0)
|
||||
it.setScaleY(1.0 / 18.0)
|
||||
}
|
||||
|
||||
val landBlockPerturbFractal = ModuleScaleOffset().also {
|
||||
it.setSource(ModuleFractal().also {
|
||||
it.setType(ModuleFractal.FractalType.FBM)
|
||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||
it.setNumOctaves(6)
|
||||
it.setFrequency((params.landBlockScale * 3.0) / params.featureSize)
|
||||
it.seed = seed shake "MassiveMassif"
|
||||
})
|
||||
it.setScale(24.0)
|
||||
}
|
||||
|
||||
val landBlockPerturb = ModuleTranslateDomain().also {
|
||||
it.setSource(landBlock)
|
||||
it.setAxisXSource(landBlockPerturbFractal)
|
||||
it.setAxisZSource(landBlockPerturbFractal)
|
||||
}
|
||||
|
||||
val landBlockClamp = ModuleClamp().also {
|
||||
it.setSource(ModuleScaleOffset().also {
|
||||
it.setSource(landBlockPerturb)
|
||||
it.setScale(1.0)
|
||||
it.setOffset(-1.0)
|
||||
})
|
||||
it.setRange(0.0, 1.0)
|
||||
}
|
||||
|
||||
val landBlockCache = ModuleCache().also {
|
||||
it.setSource(landBlockClamp)
|
||||
}
|
||||
|
||||
return landBlockCache
|
||||
}
|
||||
|
||||
private fun getCaveAttenuateBiasScaled(highlandLowlandSelectCache: ModuleCache, params: TerragenParams): ModuleCache {
|
||||
val caveAttenuateBias1 = ModuleCache().also { it.setSource(ModuleBias().also {
|
||||
it.setSource(highlandLowlandSelectCache)
|
||||
|
||||
Reference in New Issue
Block a user