TileableValueNoise: it's working

Former-commit-id: 00c8c9490726fe8d7073044de7dd47482cc6788b
Former-commit-id: 9eb4521219f1465bdb2fe924282e09f81035dd99
This commit is contained in:
Song Minjae
2016-11-02 22:17:12 +09:00
parent cddbdeab7d
commit 5a366a84da
2 changed files with 38 additions and 26 deletions

View File

@@ -16,6 +16,11 @@ import java.util.*
class TileableValueNoise(
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 var noiseGenerated = false
@@ -25,41 +30,48 @@ class TileableValueNoise(
// initialise
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
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 pointNext = rng.nextBipolarFloat()
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) {
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 % (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()
}
// next pair of points
if (stepWithinWindow == 0 && x > 0) {
pointThis = pointNext
pointNext = if (nextSampleStart >= width) pointLoop else rng.nextBipolarFloat()
}
// additive mix
val noiseValue = FastMath.interpolateLinear(windowScale, pointThis, pointNext) * amp
noiseData[x] += noiseValue
// additive mix
val noiseValue = FastMath.interpolateLinear(windowScale, pointThis, pointNext) * amp
noiseData[x] += noiseValue
/*println("x: $x\tstart: $thisSampleStart\tnext: $nextSampleStart\t" +
/*println("x: $x\tstart: $thisSampleStart\tnext: $nextSampleStart\t" +
"window: $stepWithinWindow\t" +
"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) {

View File

@@ -34,7 +34,7 @@ class StateTestingSandbox : BasicGameState() {
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?) {
noiseGen.generate(seed)
@@ -61,13 +61,13 @@ class StateTestingSandbox : BasicGameState() {
val xoff = 10f
val yoff = 300f
for (x in noiseGen.width downTo 1) {
for (x in 0..noiseGen.width - 1) {
val pStart = noiseGen[x] * amp + yoff
val pEnd = noiseGen[x - 1] * amp + yoff
val pEnd = noiseGen[x + 1] * amp + yoff
val step = 6
g.drawLine((noiseGen.width - x) * step + xoff, pStart,
(noiseGen.width - x +1) * step + xoff, pEnd)
g.drawLine(x * step + xoff, pStart,
(x+1) * step + xoff, pEnd)
}
g.color = Color.red