mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 11:04:05 +09:00
TileableValueNoise: it's working
Former-commit-id: 00c8c9490726fe8d7073044de7dd47482cc6788b Former-commit-id: 9eb4521219f1465bdb2fe924282e09f81035dd99
This commit is contained in:
@@ -16,6 +16,11 @@ import java.util.*
|
|||||||
class TileableValueNoise(
|
class TileableValueNoise(
|
||||||
val octaves: Int, val persistency: Float, val width: Int) {
|
val octaves: Int, val persistency: Float, val width: Int) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// FIXME wow, such primitive!
|
||||||
|
if (!FastMath.isPowerOfTwo(width)) throw Error("width is not power of two!")
|
||||||
|
}
|
||||||
|
|
||||||
private val noiseData = Array<Float>(width + 1, { 0f })
|
private val noiseData = Array<Float>(width + 1, { 0f })
|
||||||
private var noiseGenerated = false
|
private var noiseGenerated = false
|
||||||
|
|
||||||
@@ -25,41 +30,48 @@ class TileableValueNoise(
|
|||||||
// initialise
|
// initialise
|
||||||
Arrays.fill(noiseData, 0f)
|
Arrays.fill(noiseData, 0f)
|
||||||
|
|
||||||
|
val octavesIntStream = Array(octaves, { 1.shl(it) }) // array of (1, 2, 4, 8, ...)
|
||||||
|
|
||||||
for (i in 1..octaves) {
|
|
||||||
|
octaveLoop@ for (octcnt in 0..octaves - 1) { // 1, 2, 3, 4, ...
|
||||||
|
val i = octavesIntStream[octcnt] // 1, 2, 4, 8, ...
|
||||||
// octave 1 samples four points
|
// octave 1 samples four points
|
||||||
val samples = 4 * i
|
val samples = 4 * i
|
||||||
val amp = FastMath.pow(persistency, (i - 1).toFloat())
|
val amp = FastMath.pow(persistency, octcnt.toFloat()) // 1/1, 1/2, 1/3, 1/4, ...
|
||||||
|
|
||||||
var pointThis = 0f
|
var pointThis = 0f
|
||||||
var pointNext = rng.nextBipolarFloat()
|
var pointNext = rng.nextBipolarFloat()
|
||||||
var pointLoop = pointThis
|
var pointLoop = pointThis
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (x in 0..width) {
|
||||||
|
val thisSampleStart: Int = // 0-256 -> 0-4 -> 0-256(qnt)
|
||||||
|
(x / width.toFloat() * samples).floorInt() * (width / samples)
|
||||||
|
val nextSampleStart: Int =
|
||||||
|
(x / width.toFloat() * samples).floorInt().plus(1) * (width / samples)
|
||||||
|
val stepWithinWindow: Int = x % (nextSampleStart - thisSampleStart)
|
||||||
|
val windowScale: Float = stepWithinWindow.toFloat() / (width / samples)
|
||||||
|
|
||||||
for (x in 0..width) {
|
// next pair of points
|
||||||
val thisSampleStart: Int = // 0-256 -> 0-4 -> 0-256(qnt)
|
if (stepWithinWindow == 0 && x > 0) {
|
||||||
(x / width.toFloat() * samples).floorInt() * (width / samples)
|
pointThis = pointNext
|
||||||
val nextSampleStart: Int =
|
pointNext = if (nextSampleStart >= width) pointLoop else rng.nextBipolarFloat()
|
||||||
(x / width.toFloat() * samples).floorInt().plus(1) * (width / samples)
|
}
|
||||||
val stepWithinWindow: Int = x % (width / samples)
|
|
||||||
val windowScale: Float = stepWithinWindow.toFloat() / (width / samples)
|
|
||||||
|
|
||||||
// next pair of points
|
|
||||||
if (stepWithinWindow == 0 && x > 0) {
|
|
||||||
pointThis = pointNext
|
|
||||||
pointNext = if (nextSampleStart >= width) pointLoop else rng.nextBipolarFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// additive mix
|
||||||
// additive mix
|
val noiseValue = FastMath.interpolateLinear(windowScale, pointThis, pointNext) * amp
|
||||||
val noiseValue = FastMath.interpolateLinear(windowScale, pointThis, pointNext) * amp
|
noiseData[x] += noiseValue
|
||||||
noiseData[x] += noiseValue
|
|
||||||
|
|
||||||
|
|
||||||
/*println("x: $x\tstart: $thisSampleStart\tnext: $nextSampleStart\t" +
|
|
||||||
|
/*println("x: $x\tstart: $thisSampleStart\tnext: $nextSampleStart\t" +
|
||||||
"window: $stepWithinWindow\t" +
|
"window: $stepWithinWindow\t" +
|
||||||
"pThis: $pointThis\tpNext: $pointNext\tvalue: $noiseValue")*/
|
"pThis: $pointThis\tpNext: $pointNext\tvalue: $noiseValue")*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (e: ArithmeticException) {
|
||||||
|
println("[TileableValueNoise] division by zero error occured, aborting further octave iteration.")
|
||||||
|
break@octaveLoop
|
||||||
|
} // division by zero; which means octave value was too high
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x in 0..width - 1) {
|
for (x in 0..width - 1) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class StateTestingSandbox : BasicGameState() {
|
|||||||
|
|
||||||
val bolt = LightingBolt(lightning_start, lightning_end, 50)
|
val bolt = LightingBolt(lightning_start, lightning_end, 50)
|
||||||
|
|
||||||
val noiseGen = TileableValueNoise(12, 0.5f, 128)
|
val noiseGen = TileableValueNoise(6, 0.4f, 128)
|
||||||
|
|
||||||
override fun init(container: GameContainer?, game: StateBasedGame?) {
|
override fun init(container: GameContainer?, game: StateBasedGame?) {
|
||||||
noiseGen.generate(seed)
|
noiseGen.generate(seed)
|
||||||
@@ -61,13 +61,13 @@ class StateTestingSandbox : BasicGameState() {
|
|||||||
val xoff = 10f
|
val xoff = 10f
|
||||||
val yoff = 300f
|
val yoff = 300f
|
||||||
|
|
||||||
for (x in noiseGen.width downTo 1) {
|
for (x in 0..noiseGen.width - 1) {
|
||||||
val pStart = noiseGen[x] * amp + yoff
|
val pStart = noiseGen[x] * amp + yoff
|
||||||
val pEnd = noiseGen[x - 1] * amp + yoff
|
val pEnd = noiseGen[x + 1] * amp + yoff
|
||||||
val step = 6
|
val step = 6
|
||||||
|
|
||||||
g.drawLine((noiseGen.width - x) * step + xoff, pStart,
|
g.drawLine(x * step + xoff, pStart,
|
||||||
(noiseGen.width - x +1) * step + xoff, pEnd)
|
(x+1) * step + xoff, pEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.color = Color.red
|
g.color = Color.red
|
||||||
|
|||||||
Reference in New Issue
Block a user