mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 19:14:05 +09:00
Update WorldgenLoadScreen.kt, Terragen.kt, and WorldgenNoiseSandbox.kt
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ScreenAdapter
|
||||||
|
import net.torvald.terrarum.AppLoader
|
||||||
|
import net.torvald.terrarum.IngameInstance
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.util.HistoryArray
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* World loading screen with minecraft 1.14-style preview
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2019-11-09.
|
||||||
|
*/
|
||||||
|
class WorldgenLoadScreen(private var world: GameWorld, private var screenToLoad: IngameInstance) : ScreenAdapter() {
|
||||||
|
|
||||||
|
// a Class impl is chosen to make resize-handling easier, there's not much benefit making this a singleton anyway
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val WIDTH_RATIO = 0.6
|
||||||
|
}
|
||||||
|
|
||||||
|
private val previewWidth = (AppLoader.screenW * WIDTH_RATIO).roundToInt()
|
||||||
|
private val previewHeight = (AppLoader.screenW * WIDTH_RATIO * world.height / world.width).roundToInt()
|
||||||
|
|
||||||
|
private lateinit var screenLoadingThread: Thread
|
||||||
|
|
||||||
|
|
||||||
|
private val messages = HistoryArray<String>(20)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,9 +5,11 @@ import com.sudoplay.joise.module.*
|
|||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.LoadScreen
|
import net.torvald.terrarum.LoadScreen
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
|
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
import net.torvald.terrarum.concurrent.ThreadParallel
|
||||||
import net.torvald.terrarum.concurrent.mapToThreadPoolDirectly
|
import net.torvald.terrarum.concurrent.mapToThreadPoolDirectly
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import java.util.concurrent.Future
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
@@ -16,17 +18,21 @@ import kotlin.math.sin
|
|||||||
*/
|
*/
|
||||||
class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, params) {
|
class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, params) {
|
||||||
|
|
||||||
|
private var genFuture: Future<*>? = null
|
||||||
override var generationStarted: Boolean = false
|
override var generationStarted: Boolean = false
|
||||||
override val generationDone: Boolean
|
override val generationDone: Boolean
|
||||||
get() = generationStarted && ThreadParallel.allFinished()
|
get() = generationStarted && genFuture?.isDone ?: false
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
val joise = getGenerator(seed, params as TerragenParams)
|
val joise = getGenerator(seed, params as TerragenParams)
|
||||||
|
|
||||||
(0 until world.width).mapToThreadPoolDirectly(this.javaClass.simpleName) { range ->
|
generationStarted = true
|
||||||
for (y in 0 until world.height) {
|
|
||||||
printdbg(this, "Tile draw for y=$y")
|
// single-threaded impl because I couldn't resolve multithread memory corruption issue...
|
||||||
for (x in range) {
|
genFuture = ThreadExecutor.submit {
|
||||||
|
for (x in 0 until world.width) {
|
||||||
|
//printdbg(this, "Tile draw for y=$y")
|
||||||
|
for (y in 0 until world.height) {
|
||||||
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
|
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
|
||||||
val sampleOffset = world.width / 8.0
|
val sampleOffset = world.width / 8.0
|
||||||
val sampleX = sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
|
val sampleX = sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
|
||||||
@@ -39,8 +45,6 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generationStarted = true
|
|
||||||
ThreadParallel.startAllWaitForDie()
|
|
||||||
printdbg(this, "Waking up Worldgen")
|
printdbg(this, "Waking up Worldgen")
|
||||||
//Worldgen.wake()
|
//Worldgen.wake()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
import com.sudoplay.joise.Joise
|
import com.sudoplay.joise.Joise
|
||||||
import com.sudoplay.joise.module.*
|
import com.sudoplay.joise.module.*
|
||||||
|
import net.torvald.UnsafeHelper
|
||||||
|
import net.torvald.UnsafePtr
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.concurrent.*
|
import net.torvald.terrarum.concurrent.*
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
@@ -21,12 +23,14 @@ import net.torvald.terrarum.inUse
|
|||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.BiomegenParams
|
import net.torvald.terrarum.modulebasegame.worldgenerator.BiomegenParams
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.TerragenParams
|
import net.torvald.terrarum.modulebasegame.worldgenerator.TerragenParams
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
||||||
|
import net.torvald.terrarum.worlddrawer.toRGBA
|
||||||
import java.util.concurrent.Future
|
import java.util.concurrent.Future
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
const val WIDTH = 1536
|
const val WIDTH = 768
|
||||||
const val HEIGHT = 1024
|
const val HEIGHT = 512
|
||||||
const val TWO_PI = Math.PI * 2
|
const val TWO_PI = Math.PI * 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,6 +108,19 @@ class WorldgenNoiseSandbox : ApplicationAdapter() {
|
|||||||
generationTime = time / 1000000000f
|
generationTime = time / 1000000000f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (threadExecFinished) {
|
||||||
|
threadingBuffer.forEachIndexed { index, ptr ->
|
||||||
|
val xs = xSlices[index]
|
||||||
|
for (x in xs) {
|
||||||
|
for (y in 0 until HEIGHT) {
|
||||||
|
val n = ptr[(y * (xs.last - xs.first + 1)) + (x - xs.first).toLong()]
|
||||||
|
|
||||||
|
testTex.drawPixel(x, y, if (n == 0.toByte()) 0xff else -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// draw timer
|
// draw timer
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
if (!generationTimeInMeasure) {
|
if (!generationTimeInMeasure) {
|
||||||
@@ -129,6 +146,41 @@ class WorldgenNoiseSandbox : ApplicationAdapter() {
|
|||||||
private val threadExecFinished: Boolean
|
private val threadExecFinished: Boolean
|
||||||
get() = threadExecFuture.fold(true) { acc, future -> acc && (future?.isDone ?: true) }
|
get() = threadExecFuture.fold(true) { acc, future -> acc && (future?.isDone ?: true) }
|
||||||
|
|
||||||
|
private val testColSet = arrayOf(
|
||||||
|
Color(0xff0000ff.toInt()),
|
||||||
|
Color(0xffff00ff.toInt()),
|
||||||
|
Color(0x00ff00ff.toInt()),
|
||||||
|
Color(0x00ffffff.toInt()),
|
||||||
|
Color(0x0000ffff.toInt()),
|
||||||
|
Color(0xff00ffff.toInt()),
|
||||||
|
Color(0xffffffff.toInt()),
|
||||||
|
Color(0xff)
|
||||||
|
)
|
||||||
|
private val testColSet2 = arrayOf(
|
||||||
|
0xff0000ff.toInt(),
|
||||||
|
0xffff00ff.toInt(),
|
||||||
|
0x00ff00ff.toInt(),
|
||||||
|
0x00ffffff.toInt(),
|
||||||
|
0x0000ffff.toInt(),
|
||||||
|
0xff00ffff.toInt(),
|
||||||
|
0xffffffff.toInt(),
|
||||||
|
0xff
|
||||||
|
)
|
||||||
|
|
||||||
|
fun <T> Array<T>.shuffle() {
|
||||||
|
val rng = Random(System.nanoTime())
|
||||||
|
for (k in this.size - 1 downTo 1) {
|
||||||
|
val r = rng.nextInt(k + 1)
|
||||||
|
|
||||||
|
val t = this[r]
|
||||||
|
this[r] = this[k]
|
||||||
|
this[k] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val xSlices = (0 until WIDTH).sliceEvenly(ThreadExecutor.threadCount)
|
||||||
|
private val threadingBuffer = xSlices.map { UnsafeHelper.allocate(1L * HEIGHT * (it.last - it.first + 1) ) }
|
||||||
|
|
||||||
private fun renderNoise() {
|
private fun renderNoise() {
|
||||||
generationStartTime = System.nanoTime()
|
generationStartTime = System.nanoTime()
|
||||||
generationTimeInMeasure = true
|
generationTimeInMeasure = true
|
||||||
@@ -137,19 +189,30 @@ class WorldgenNoiseSandbox : ApplicationAdapter() {
|
|||||||
testTex.setColor(colourNull)
|
testTex.setColor(colourNull)
|
||||||
testTex.fill()
|
testTex.fill()
|
||||||
|
|
||||||
// render noisemap to pixmap
|
testColSet.shuffle()
|
||||||
val runnables: List<RunnableFun> = (0 until WIDTH).sliceEvenly(ThreadExecutor.threadCount).map { range ->
|
testColSet2.shuffle()
|
||||||
{
|
|
||||||
for (y in 0 until HEIGHT) {
|
|
||||||
for (x in range) {
|
|
||||||
val sampleTheta = (x.toDouble() / WIDTH) * TWO_PI
|
|
||||||
val sampleX = sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
|
|
||||||
val sampleZ = cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
|
|
||||||
val sampleY = y.toDouble()
|
|
||||||
|
|
||||||
//synchronized(testTex) {
|
// render noisemap to pixmap
|
||||||
NOISE_MAKER.draw(x, y, joise.map { it.get(sampleX, sampleY, sampleZ) }, testTex)
|
val runnables: List<RunnableFun> = xSlices.mapIndexed { index, range ->
|
||||||
//}
|
{
|
||||||
|
for (x in range) {
|
||||||
|
for (y in 0 until HEIGHT) {
|
||||||
|
synchronized(threadingBuffer[index]) {
|
||||||
|
val sampleTheta = (x.toDouble() / WIDTH) * TWO_PI
|
||||||
|
val sampleX = sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
|
||||||
|
val sampleZ = cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
|
||||||
|
val sampleY = y.toDouble()
|
||||||
|
|
||||||
|
|
||||||
|
//NOISE_MAKER.draw(x, y, joise.map { it.get(sampleX, sampleY, sampleZ) }, testTex)
|
||||||
|
NOISE_MAKER.draw(range, x, y, listOf(joise[0].get(sampleX, sampleY, sampleZ)), threadingBuffer[index])
|
||||||
|
|
||||||
|
//joise.map { it.get(sampleX, sampleY, sampleZ) }
|
||||||
|
//testTex.drawPixel(x, y, testColSet2[index])
|
||||||
|
|
||||||
|
//testTex.setColor(testColSet2[index])
|
||||||
|
//testTex.drawPixel(x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,6 +224,12 @@ class WorldgenNoiseSandbox : ApplicationAdapter() {
|
|||||||
|
|
||||||
generationDone = true
|
generationDone = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
testTex.dispose()
|
||||||
|
tempTex.dispose()
|
||||||
|
threadingBuffer.forEach { it.destroy() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
@@ -179,19 +248,20 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface NoiseMaker {
|
interface NoiseMaker {
|
||||||
fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: Pixmap)
|
fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: UnsafePtr)
|
||||||
fun getGenerator(seed: Long, params: Any): List<Joise>
|
fun getGenerator(seed: Long, params: Any): List<Joise>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val locklock = java.lang.Object()
|
||||||
|
|
||||||
object BiomeMaker : NoiseMaker {
|
object BiomeMaker : NoiseMaker {
|
||||||
|
|
||||||
override fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: Pixmap) {
|
override fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: UnsafePtr) {
|
||||||
val colPal = biomeColors
|
val colPal = biomeColors
|
||||||
val control = noiseValue[0].times(colPal.size).minus(0.00001f).toInt().fmod(colPal.size)
|
val control = noiseValue[0].times(colPal.size).minus(0.00001f).toInt().fmod(colPal.size)
|
||||||
|
|
||||||
outTex.setColor(colPal[control])
|
//outTex.setColor(colPal[control])
|
||||||
//testTex.setColor(RNG.nextFloat(), RNG.nextFloat(), RNG.nextFloat(), 1f)
|
//outTex.drawPixel(x, y)
|
||||||
outTex.drawPixel(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getGenerator(seed: Long, params: Any): List<Joise> {
|
override fun getGenerator(seed: Long, params: Any): List<Joise> {
|
||||||
@@ -233,7 +303,7 @@ object BiomeMaker : NoiseMaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// http://accidentalnoise.sourceforge.net/minecraftworlds.html
|
// http://accidentalnoise.sourceforge.net/minecraftworlds.html
|
||||||
object AccidentalCave : NoiseMaker {
|
object AccidentalCave {
|
||||||
|
|
||||||
private infix fun Color.mul(other: Color) = this.mul(other)
|
private infix fun Color.mul(other: Color) = this.mul(other)
|
||||||
|
|
||||||
@@ -246,7 +316,7 @@ object AccidentalCave : NoiseMaker {
|
|||||||
Color(0.97f, 0.6f, 0.56f, 1f)
|
Color(0.97f, 0.6f, 0.56f, 1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: Pixmap) {
|
fun draw(xs: IntProgression, x: Int, y: Int, noiseValue: List<Double>, outTex: UnsafePtr) {
|
||||||
// simple one-source draw
|
// simple one-source draw
|
||||||
/*val c = noiseValue[0].toFloat()
|
/*val c = noiseValue[0].toFloat()
|
||||||
val selector = c.minus(0.0001).floorInt() fmod notationColours.size
|
val selector = c.minus(0.0001).floorInt() fmod notationColours.size
|
||||||
@@ -273,17 +343,19 @@ object AccidentalCave : NoiseMaker {
|
|||||||
Color(.6f, .6f, .6f, 1f)
|
Color(.6f, .6f, .6f, 1f)
|
||||||
)
|
)
|
||||||
val n1 = noiseValue[0].tiered(.0, .5, .88)
|
val n1 = noiseValue[0].tiered(.0, .5, .88)
|
||||||
var n2 = noiseValue[1].toFloat()
|
//var n2 = noiseValue[1].toFloat()
|
||||||
if (n2 != 1f) n2 = 0.5f
|
//if (n2 != 1f) n2 = 0.5f
|
||||||
val c1 = groundDepthCol[n1]
|
val c1 = groundDepthCol[n1]
|
||||||
val c2 = Color(n2, n2, n2, 1f)
|
//val c2 = Color(n2, n2, n2, 1f)
|
||||||
val cout = c1 mul c2
|
//val cout = c1 mul c23
|
||||||
|
val cout = c1
|
||||||
|
|
||||||
outTex.setColor(cout)
|
//outTex.drawPixel(x, y, cout.toRGBA())
|
||||||
outTex.drawPixel(x, y)
|
|
||||||
|
outTex[(y * (xs.last - xs.first + 1)) + (x - xs.first).toLong()] = n1.toByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getGenerator(seed: Long, params: Any): List<Joise> {
|
fun getGenerator(seed: Long, params: Any): List<Joise> {
|
||||||
val params = params as TerragenParams
|
val params = params as TerragenParams
|
||||||
|
|
||||||
val lowlandMagic: Long = 0x41A21A114DBE56 // Maria Lindberg
|
val lowlandMagic: Long = 0x41A21A114DBE56 // Maria Lindberg
|
||||||
|
|||||||
Reference in New Issue
Block a user