![JAR search and dependency download from the Maven repository](/logo.png)
commonMain.ru.casperix.math.perlin.CachedValueNoise2D.kt Maven / Gradle / Ivy
package ru.casperix.math.perlin
import ru.casperix.math.array.float64.DoubleMap2D
import ru.casperix.math.axis_aligned.int32.Box2i
import ru.casperix.math.vector.int32.Vector2i
import ru.casperix.math.function.Function2D
import ru.casperix.math.interpolation.float64.hermiteInterpolate
class CachedValueNoise2D(val source: ValueNoise2D, val area: Box2i) {
class CacheInfo(val octave: ValueNoise2D.OctaveCache, val map: DoubleMap2D, val offset: Vector2i)
init {
if (source.interpolateFunction != hermiteInterpolate)
throw Error("Support only hermite interpolate")
}
val normalizer = source.normalizer
val octaves = Array(source.octaves.size) { index ->
val octave = source.octaves[index]
createRandomCache(octave)
}
private fun createRandomCache(octave: ValueNoise2D.OctaveCache): CacheInfo {
val minX = (area.min.x * octave.frequencyX).toInt()
val minY = (area.min.y * octave.frequencyY).toInt()
val maxX = (area.max.x * octave.frequencyX).toInt() + 1
val maxY = (area.max.y * octave.frequencyY).toInt() + 1
val map = DoubleMap2D.createByXY(Vector2i(maxX - minX + 1, maxY - minY + 1)) {
ValueNoise2D.randomWithFactor(it.x + minX, it.y + minY, octave.primeNumber)
}
return CacheInfo(octave, map, Vector2i(minX, minY))
}
val output: Function2D = { x, y ->
var total = 0.0
for (cache in octaves) {
val octave = cache.octave
total += interpolate2dFlat(x * octave.frequencyX - cache.offset.x, y * octave.frequencyY - cache.offset.y, cache.map) * octave.amplitude
}
total * normalizer
}
private fun interpolateFunction(a: Double, b: Double, x: Double): Double {
return a + (b - a) * (3.0 - 2.0 * x) * x * x
}
private fun interpolate2dFlat(fx: Double, fy: Double, randoms: DoubleMap2D): Double {
val baseX = fx.toInt()
val fractionalX = fx - baseX
val baseY = fy.toInt()
val fractionalY = fy - baseY
val directArray = randoms.array
val firstIndex = baseX + randoms.sizeX * baseY
val v1 = directArray[firstIndex]
val v2 = directArray[firstIndex + 1]
val v3 = directArray[firstIndex + randoms.sizeX]
val v4 = directArray[firstIndex + 1 + randoms.sizeX]
val i1 = interpolateFunction(v1, v2, fractionalX)
val i2 = interpolateFunction(v3, v4, fractionalX)
return interpolateFunction(i1, i2, fractionalY)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy