From f469772c86fa5ed0d035ed1e3fb6f31be992e15a Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 27 Apr 2020 03:05:19 +0900 Subject: [PATCH] reverting Unsafe usage of worldgennoisesandbox --- src/net/torvald/colourutil/CIESpectralUtil.kt | 70 +++++++++++++++++++ .../terrarum/tests/WorldgenNoiseSandbox.kt | 42 +++-------- 2 files changed, 81 insertions(+), 31 deletions(-) create mode 100644 src/net/torvald/colourutil/CIESpectralUtil.kt diff --git a/src/net/torvald/colourutil/CIESpectralUtil.kt b/src/net/torvald/colourutil/CIESpectralUtil.kt new file mode 100644 index 000000000..5112cf003 --- /dev/null +++ b/src/net/torvald/colourutil/CIESpectralUtil.kt @@ -0,0 +1,70 @@ +package net.torvald.colourutil + +import com.jme3.math.FastMath.exp +import kotlin.test.assertEquals +import kotlin.test.assertTrue + + +/** + * Using Analytic approximation by Wyman el al. + * + * https://www.ppsloan.org/publications/XYZJCGT.pdf + * + * Created by minjaesong on 2020-04-20. + */ + +/** + * @return resonable approximation of xbar(lambda) aka CIE XYZ Colour Matching Function + */ +fun getX(wave: Float): Float { + val xt1 = (wave - 442.0f) * if (wave < 442.0f) 0.0624f else 0.0374f + val xt2 = (wave - 599.8f) * if (wave < 599.8f) 0.0264f else 0.0323f + val xt3 = (wave - 501.1f) * if (wave < 501.1f) 0.0490f else 0.0382f + return 0.362f * exp(-0.5f * xt1 * xt1) + 1.056f * exp(-0.5f * xt2 * xt2) - 0.065f * exp(-0.5f * xt3 * xt3) +} + +/** + * @return resonable approximation of ybar(lambda) aka CIE XYZ Colour Matching Function + */ +fun getY(wave: Float): Float { + val yt1 = (wave - 568.8f) * if (wave < 568.8f) 0.0213f else 0.0247f + val yt2 = (wave - 530.9f) * if (wave < 530.9f) 0.0613f else 0.0322f + return 0.821f * exp(-0.5f * yt1 * yt1) + 0.286f * exp(-0.5f * yt2 * yt2) +} + +/** + * @return resonable approximation of zbar(lambda) aka CIE XYZ Colour Matching Function + */ +fun getZ(wave: Float): Float { + val zt1 = (wave - 437.0f) * if (wave < 437.0f) 0.0845f else 0.0278f + val zt2 = (wave - 459.0f) * if (wave < 459.0f) 0.0385f else 0.0725f + return 1.217f * exp(-0.5f * zt1 * zt1) + 0.681f * exp(-0.5f * zt2 * zt2) +} + +fun getXYZUsingIntegral(waves: FloatArray, samples: FloatArray): CIEXYZ { + assertTrue( + waves.size == samples.size, + "number of waves and number of samples must match! (${waves.size}, ${samples.size})" + ) + + val X = (0 until waves.size - 1).map { i -> + val delta = waves[i + 1] - waves[i] + val pThis = samples[i] * getX(waves[i]) + val pNext = samples[i + 1] * getX(waves[i + 1]) + pThis * delta + (pNext - pThis) * delta / 2f // linear interpolation + }.sum() + val Y = (0 until waves.size - 1).map { i -> + val delta = waves[i + 1] - waves[i] + val pThis = samples[i] * getY(waves[i]) + val pNext = samples[i + 1] * getY(waves[i + 1]) + pThis * delta + (pNext - pThis) * delta / 2f // linear interpolation + }.sum() + val Z = (0 until waves.size - 1).map { i -> + val delta = waves[i + 1] - waves[i] + val pThis = samples[i] * getZ(waves[i]) + val pNext = samples[i + 1] * getZ(waves[i + 1]) + pThis * delta + (pNext - pThis) * delta / 2f // linear interpolation + }.sum() + + return CIEXYZ(X, Y, Z) +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt index 8935ba1a5..1f7592d88 100644 --- a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt +++ b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt @@ -108,19 +108,6 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { 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 batch.inUse { if (!generationTimeInMeasure) { @@ -179,7 +166,6 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { } 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() { generationStartTime = System.nanoTime() @@ -197,22 +183,19 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { { 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() + 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]) + NOISE_MAKER.draw(range, x, y, joise.map { it.get(sampleX, sampleY, sampleZ) }, testTex) - //joise.map { it.get(sampleX, sampleY, sampleZ) } - //testTex.drawPixel(x, y, testColSet2[index]) + //joise.map { it.get(sampleX, sampleY, sampleZ) } + //testTex.drawPixel(x, y, testColSet2[index]) - //testTex.setColor(testColSet2[index]) - //testTex.drawPixel(x, y) - } + //testTex.setColor(testColSet2[index]) + //testTex.drawPixel(x, y) } } } @@ -228,7 +211,6 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { override fun dispose() { testTex.dispose() tempTex.dispose() - threadingBuffer.forEach { it.destroy() } } } @@ -316,7 +298,7 @@ internal object AccidentalCave { Color(0.97f, 0.6f, 0.56f, 1f) ) - fun draw(xs: IntProgression, x: Int, y: Int, noiseValue: List, outTex: UnsafePtr) { + fun draw(xs: IntProgression, x: Int, y: Int, noiseValue: List, outTex: Pixmap) { // simple one-source draw /*val c = noiseValue[0].toFloat() val selector = c.minus(0.0001).floorInt() fmod notationColours.size @@ -350,9 +332,7 @@ internal object AccidentalCave { //val cout = c1 mul c23 val cout = c1 - //outTex.drawPixel(x, y, cout.toRGBA()) - - outTex[(y * (xs.last - xs.first + 1)) + (x - xs.first).toLong()] = n1.toByte() + outTex.drawPixel(x, y, cout.toRGBA()) } fun getGenerator(seed: Long, params: Any): List {