Added partial port of fastnoise-java

This commit is contained in:
Edwin Jakobs
2018-12-05 16:07:28 +01:00
parent 0272c68e0f
commit 362c7a5889
13 changed files with 733 additions and 0 deletions

View File

@@ -24,5 +24,100 @@ val v4uc = Vector4.uniform(Vector4(0.0, 0.0, 0.0, 0.0), Vector4(1.0, 1.0, 1.0, 1
val v4ur = Vector4.uniformRing(0.5, 1.0)
val ringSamples = List(500) { Vector2.uniformRing() }
```
## Multi-dimensional noise
These are a mostly straight port from FastNoise-Java but have a slightly different interface.
### Perlin noise
```
// -- 2d
val v0 = perlinLinear(seed, x, y)
val v1 = perlinQuintic(seed, x, y)
val v2 = perlinHermite(seed, x, y)
// -- 3d
val v3 = perlinLinear(seed, x, y, z)
val v4 = perlinQuintic(seed, x, y, z)
val v5 = perlinHermite(seed, x, y, z)
```
### Value noise
```
// -- 2d
val v0 = valueLinear(seed, x, y)
val v1 = valueQuintic(seed, x, y)
val v2 = valueHermite(seed, x, y)
// -- 3d
val v3 = valueLinear(seed, x, y, z)
val v4 = valueQuintic(seed, x, y, z)
val v5 = valueHermite(seed, x, y ,z)
```
### Simplex noise
```
// -- 2d
val v0 = simplexLinear(seed, x, y)
val v1 = simplexQuintic(seed, x, y)
val v2 = simplexHermite(seed, x, y)
// -- 3d
val v3 = simplexLinear(seed, x, y, z)
val v4 = simplexQuintic(seed, x, y, z)
val v5 = simplexHermite(seed, x, y ,z)
```
### Cubic noise
```
// -- 2d
val v0 = cubicLinear(seed, x, y)
val v1 = cubicQuintic(seed, x, y)
val v2 = cubicHermite(seed, x, y)
// -- 3d
val v3 = cubicLinear(seed, x, y, z)
val v4 = cubicQuintic(seed, x, y, z)
val v5 = cubicHermite(seed, x, y ,z)
```
### Fractal noise
The library provides 3 functions with which fractal noise can be composed.
#### Fractal brownian motion (FBM)
```
val v0 = fbm(seed, x, y, ::perlinLinear, octaves, lacunarity, gain)
val v1 = fbm(seed, x, y, ::simplexLinear, octaves, lacunarity, gain)
val v2 = fbm(seed, x, y, ::valueLinear, octaves, lacunarity, gain)
val v3 = fbm(seed, x, y, z, ::perlinLinear, octaves, lacunarity, gain)
val v4 = fbm(seed, x, y, z, ::simplexLinear, octaves, lacunarity, gain)
val v5 = fbm(seed, x, y, z, ::valueLinear, octaves, lacunarity, gain)
```
#### Rigid
```
val v0 = rigid(seed, x, y, ::perlinLinear, octaves, lacunarity, gain)
val v1 = rigid(seed, x, y, ::simplexLinear, octaves, lacunarity, gain)
val v2 = rigid(seed, x, y, ::valueLinear, octaves, lacunarity, gain)
val v3 = rigid(seed, x, y, z, ::perlinLinear, octaves, lacunarity, gain)
val v4 = rigid(seed, x, y, z, ::simplexLinear, octaves, lacunarity, gain)
val v5 = rigid(seed, x, y, z, ::valueLinear, octaves, lacunarity, gain)
```
#### Billow
```
val v0 = billow(seed, x, y, ::perlinLinear, octaves, lacunarity, gain)
val v1 = billow(seed, x, y, ::perlinLinear, octaves, lacunarity, gain)
val v2 = billow(seed, x, y, ::perlinLinear, octaves, lacunarity, gain)
val v3 = billow(seed, x, y, z, ::perlinLinear, octaves, lacunarity, gain)
val v4 = billow(seed, x, y, z, ::perlinLinear, octaves, lacunarity, gain)
val v5 = billow(seed, x, y, z, ::perlinLinear, octaves, lacunarity, gain)
```

View File

@@ -0,0 +1,28 @@
package org.openrndr.extra.noise
private const val CUBIC_2D_BOUNDING = 1 / (1.5 * 1.5).toFloat()
fun cubic(seed: Int, x: Double, y: Double): Double {
val x1 = x.fastFloor()
val y1 = y.fastFloor()
val x0 = x1 - 1
val y0 = y1 - 1
val x2 = x1 + 1
val y2 = y1 + 1
val x3 = x1 + 2
val y3 = y1 + 2
val xs = x - x1.toDouble()
val ys = y - y1.toDouble()
return cubic(
cubic(valCoord2D(seed, x0, y0), valCoord2D(seed, x1, y0), valCoord2D(seed, x2, y0), valCoord2D(seed, x3, y0),
xs),
cubic(valCoord2D(seed, x0, y1), valCoord2D(seed, x1, y1), valCoord2D(seed, x2, y1), valCoord2D(seed, x3, y1),
xs),
cubic(valCoord2D(seed, x0, y2), valCoord2D(seed, x1, y2), valCoord2D(seed, x2, y2), valCoord2D(seed, x3, y2),
xs),
cubic(valCoord2D(seed, x0, y3), valCoord2D(seed, x1, y3), valCoord2D(seed, x2, y3), valCoord2D(seed, x3, y3),
xs),
ys) * CUBIC_2D_BOUNDING
}

View File

@@ -0,0 +1,51 @@
package org.openrndr.extra.noise
private const val CUBIC_3D_BOUNDING = 1 / (1.5 * 1.5 * 1.5).toFloat()
private fun cubic(seed: Int, x: Double, y: Double, z: Double): Double {
val x1 = x.fastFloor()
val y1 = y.fastFloor()
val z1 = z.fastFloor()
val x0 = x1 - 1
val y0 = y1 - 1
val z0 = z1 - 1
val x2 = x1 + 1
val y2 = y1 + 1
val z2 = z1 + 1
val x3 = x1 + 2
val y3 = y1 + 2
val z3 = z1 + 2
val xs = x - x1.toFloat()
val ys = y - y1.toFloat()
val zs = z - z1.toFloat()
return cubic(
cubic(
cubic(valCoord3D(seed, x0, y0, z0), valCoord3D(seed, x1, y0, z0), valCoord3D(seed, x2, y0, z0), valCoord3D(seed, x3, y0, z0), xs),
cubic(valCoord3D(seed, x0, y1, z0), valCoord3D(seed, x1, y1, z0), valCoord3D(seed, x2, y1, z0), valCoord3D(seed, x3, y1, z0), xs),
cubic(valCoord3D(seed, x0, y2, z0), valCoord3D(seed, x1, y2, z0), valCoord3D(seed, x2, y2, z0), valCoord3D(seed, x3, y2, z0), xs),
cubic(valCoord3D(seed, x0, y3, z0), valCoord3D(seed, x1, y3, z0), valCoord3D(seed, x2, y3, z0), valCoord3D(seed, x3, y3, z0), xs),
ys),
cubic(
cubic(valCoord3D(seed, x0, y0, z1), valCoord3D(seed, x1, y0, z1), valCoord3D(seed, x2, y0, z1), valCoord3D(seed, x3, y0, z1), xs),
cubic(valCoord3D(seed, x0, y1, z1), valCoord3D(seed, x1, y1, z1), valCoord3D(seed, x2, y1, z1), valCoord3D(seed, x3, y1, z1), xs),
cubic(valCoord3D(seed, x0, y2, z1), valCoord3D(seed, x1, y2, z1), valCoord3D(seed, x2, y2, z1), valCoord3D(seed, x3, y2, z1), xs),
cubic(valCoord3D(seed, x0, y3, z1), valCoord3D(seed, x1, y3, z1), valCoord3D(seed, x2, y3, z1), valCoord3D(seed, x3, y3, z1), xs),
ys),
cubic(
cubic(valCoord3D(seed, x0, y0, z2), valCoord3D(seed, x1, y0, z2), valCoord3D(seed, x2, y0, z2), valCoord3D(seed, x3, y0, z2), xs),
cubic(valCoord3D(seed, x0, y1, z2), valCoord3D(seed, x1, y1, z2), valCoord3D(seed, x2, y1, z2), valCoord3D(seed, x3, y1, z2), xs),
cubic(valCoord3D(seed, x0, y2, z2), valCoord3D(seed, x1, y2, z2), valCoord3D(seed, x2, y2, z2), valCoord3D(seed, x3, y2, z2), xs),
cubic(valCoord3D(seed, x0, y3, z2), valCoord3D(seed, x1, y3, z2), valCoord3D(seed, x2, y3, z2), valCoord3D(seed, x3, y3, z2), xs),
ys),
cubic(
cubic(valCoord3D(seed, x0, y0, z3), valCoord3D(seed, x1, y0, z3), valCoord3D(seed, x2, y0, z3), valCoord3D(seed, x3, y0, z3), xs),
cubic(valCoord3D(seed, x0, y1, z3), valCoord3D(seed, x1, y1, z3), valCoord3D(seed, x2, y1, z3), valCoord3D(seed, x3, y1, z3), xs),
cubic(valCoord3D(seed, x0, y2, z3), valCoord3D(seed, x1, y2, z3), valCoord3D(seed, x2, y2, z3), valCoord3D(seed, x3, y2, z3), xs),
cubic(valCoord3D(seed, x0, y3, z3), valCoord3D(seed, x1, y3, z3), valCoord3D(seed, x2, y3, z3), valCoord3D(seed, x3, y3, z3), xs),
ys),
zs) * CUBIC_3D_BOUNDING
}

View File

@@ -0,0 +1,105 @@
package org.openrndr.extra.noise
inline fun fbm(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (Int, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = noise(seed, x, y, z)
var amp = 1.0
var x = x
var y = y
var z = z
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
z *= lacunarity
amp *= gain
sum += noise(seed + i, x, y, z) * amp
}
return sum
}
inline fun fbm(seed: Int, x: Double, y: Double, crossinline noise: (Int, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = noise(seed, x, y)
var amp = 1.0
var x = x
var y = y
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
amp *= gain
sum += noise(seed + i, x, y) * amp
}
return sum
}
inline fun billow(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (Int, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) : Double {
var sum = Math.abs(noise(seed, x, y, z) * 2.0 - 1.0)
var amp = 1.0
var x = x
var y = y
var z = z
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
z *= lacunarity
amp *= gain
sum += Math.abs(noise(seed + i, x, y, z) * 2.0 - 1.0) * amp
}
return sum
}
inline fun billow(seed: Int, x: Double, y: Double, crossinline noise: (Int, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) : Double {
var sum = Math.abs(noise(seed, x, y) * 2.0 - 1.0)
var amp = 1.0
var x = x
var y = y
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
amp *= gain
sum += Math.abs(noise(seed + i, x, y) * 2.0 - 1.0) * amp
}
return sum
}
inline fun rigid(seed: Int, x: Double, y: Double, crossinline noise: (Int, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = 1.0 - Math.abs(noise(seed, x, y))
var amp = 1.0
var x = x
var y = y
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
amp *= gain
sum -= (1.0 - Math.abs(noise(seed + i, x, y))) * amp
}
return sum
}
inline fun rigid(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (Int, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = 1.0 - Math.abs(noise(seed, x, y, z))
var amp = 1.0
var x = x
var y = y
var z = z
for (i in 1 until octaves) {
x *= lacunarity
y *= lacunarity
z *= lacunarity
amp *= gain
sum -= (1.0 - Math.abs(noise(seed + i, x, y, z))) * amp
}
return sum
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
package org.openrndr.extra.noise
fun hermite(t: Double): Double {
return t * t * (3 - 2 * t)
}
fun quintic(t: Double): Double {
return t * t * t * (t * (t * 6 - 15) + 10)
}
fun cubic(a: Double, b: Double, c: Double, d: Double, t: Double) : Double {
val p = d - c - (a - b)
return t * t * t * p + t * t * (a - b - p) + t * (c - a) + b
}
fun linear(x: Double) : Double {
return x
}
fun lerp(left: Double, right: Double, x: Double): Double {
return left * (1.0 - x) + right * x
}

View File

@@ -0,0 +1,6 @@
package org.openrndr.extra.noise
fun Double.fastFloor(): Int {
return if (this >= 0) this.toInt() else this.toInt() - 1
}

View File

@@ -0,0 +1,26 @@
package org.openrndr.extra.noise
fun perlinLinear(seed: Int, x: Double, y: Double) = perlin(seed, x, y, ::linear)
fun perlinQuintic(seed: Int, x: Double, y: Double) = perlin(seed, x, y, ::quintic)
fun perlinHermite(seed: Int, x: Double, y: Double) = perlin(seed, x, y, ::hermite)
private fun perlin(seed: Int, x: Double, y: Double, interpolator: (Double) -> Double): Double {
val x0 = x.fastFloor()
val y0 = y.fastFloor()
val x1 = x0 + 1
val y1 = y0 + 1
val xs = interpolator(x - x0)
val ys = interpolator(y - y0)
val xd0 = x - x0
val yd0 = y - y0
val xd1 = xd0 - 1
val yd1 = yd0 - 1
val xf0 = lerp(gradCoord2D(seed, x0, y0, xd0, yd0), gradCoord2D(seed, x1, y0, xd1, yd0), xs)
val xf1 = lerp(gradCoord2D(seed, x0, y1, xd0, yd1), gradCoord2D(seed, x1, y1, xd1, yd1), xs)
return lerp(xf0, xf1, ys)
}

View File

@@ -0,0 +1,35 @@
package org.openrndr.extra.noise
fun perlinLinear(seed: Int, x: Double, y: Double, z: Double) = perlin(seed, x, y, z, ::linear)
fun perlinQuintic(seed: Int, x: Double, y: Double, z: Double) = perlin(seed, x, y, z, ::quintic)
fun perlinHermite(seed: Int, x: Double, y: Double, z: Double) = perlin(seed, x, y, z, ::hermite)
inline fun perlin(seed: Int, x: Double, y: Double, z: Double, crossinline interpolator: (Double) -> Double = ::linear): Double {
val x0 = x.fastFloor()
val y0 = y.fastFloor()
val z0 = z.fastFloor()
val x1 = x0 + 1
val y1 = y0 + 1
val z1 = z0 + 1
val xs: Double = interpolator(x - x0)
val ys: Double = interpolator(y - y0)
val zs: Double = interpolator(z - z0)
val xd0 = x - x0
val yd0 = y - y0
val zd0 = z - z0
val xd1 = xd0 - 1
val yd1 = yd0 - 1
val zd1 = zd0 - 1
val xf00 = lerp(gradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs)
val xf10 = lerp(gradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs)
val xf01 = lerp(gradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs)
val xf11 = lerp(gradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs)
val yf0 = lerp(xf00, xf10, ys)
val yf1 = lerp(xf01, xf11, ys)
return lerp(yf0, yf1, zs)
}

View File

@@ -0,0 +1,63 @@
package org.openrndr.extra.noise
private val G2 = 1.0 / 4.0
private val F2 = 1.0 / 2.0
fun simplex(seed: Int, x: Double, y: Double): Double {
var t = (x + y) * F2
val i = (x + t).fastFloor()
val j = (y + t).fastFloor()
t = ((i + j) * G2)
val X0 = i - t
val Y0 = j - t
val x0 = x - X0
val y0 = y - Y0
val i1: Int
val j1: Int
if (x0 > y0) {
i1 = 1
j1 = 0
} else {
i1 = 0
j1 = 1
}
val x1 = x0 - i1 + G2
val y1 = y0 - j1 + G2
val x2 = x0 - 1 + F2
val y2 = y0 - 1 + F2
val n0: Double
val n1: Double
val n2: Double
t = 0.5 - x0 * x0 - y0 * y0
if (t < 0)
n0 = 0.0
else {
t *= t
n0 = t * t * gradCoord2D(seed, i, j, x0, y0)
}
t = 0.5 - x1 * x1 - y1 * y1
if (t < 0)
n1 = 0.0
else {
t *= t
n1 = t * t * gradCoord2D(seed, i + i1, j + j1, x1, y1)
}
t = 0.5 - x2 * x2 - y2 * y2
if (t < 0)
n2 = 0.0
else {
t *= t
n2 = t * t * gradCoord2D(seed, i + 1, j + 1, x2, y2)
}
return 50.0 * (n0 + n1 + n2)
}

View File

@@ -0,0 +1,94 @@
package org.openrndr.extra.noise
fun simplex(seed: Int, x: Double, y: Double, z: Double): Double {
var t = (x + y + z) / 3.0
val i = (x + t).fastFloor()
val j = (y + t).fastFloor()
val k = (z + t).fastFloor()
val t2 = (i + j + k) / 6.0
val x0 = x - (i - t2)
val y0 = y - (j - t2)
val z0 = z - (k - t2)
val i1: Int
val j1: Int
val k1: Int
val i2: Int
val j2: Int
val k2: Int
if (x0 >= y0) {
when {
y0 >= z0 -> {
i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; }
x0 >= z0 -> {
i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; }
else -> {
i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; }
}
} else {
when {
y0 < z0 -> {
i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; }
x0 < z0 -> {
i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; }
else -> {
i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; }
}
}
val x1 = x0 - i1 + 1.0 / 6.0
val y1 = y0 - j1 + 1.0 / 6.0
val z1 = z0 - k1 + 1.0 / 6.0
val x2 = x0 - i2 + 1.0 / 3.0
val y2 = y0 - j2 + 1.0 / 3.0
val z2 = z0 - k2 + 1.0 / 3.0
val x3 = x0 + ((1.0 / 6.0) * 3.0 - 1.0)
val y3 = y0 + ((1.0 / 6.0) * 3.0 - 1.0)
val z3 = z0 + ((1.0 / 6.0) * 3.0 - 1.0)
val n0: Double
run {
var t = 0.6 * x0 * x0 - y0 * y0 - z0 * z0
if (t < 0) {
n0 = 0.0
} else {
t *= t
n0 = t * t * gradCoord3D(seed, i, j, k, x0, y0, z0)
}
}
val n1: Double
run {
var t = 0.6 * x1 * x1 - y1 * y1 - z1 * z1
if (t < 0) {
n1 = 0.0
} else {
t *= t
n1 = t * t * gradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1)
}
}
val n2: Double
run {
var t = 0.6 * x2 * x2 - y2 * y2 - z2 * z2
if (t < 0) {
n2 = 0.0
} else {
t *= t
n2 = t * t * gradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2)
}
}
val n3: Double
run {
var t = 0.6 - x3 * x3 - y3 * y3 - z3 * z3
if (t < 0)
n3 = 0.0
else {
t *= t
n3 = t * t * gradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3)
}
}
return 32 * (n0 + n1 + n2 + n3)
}

View File

@@ -0,0 +1,21 @@
package org.openrndr.extra.noise
fun valueLinear(seed: Int, x:Double, y:Double) = value(seed, x, y, ::linear)
fun valueQuintic(seed: Int, x:Double, y:Double) = value(seed, x, y, ::quintic)
fun valueHermite(seed: Int, x:Double, y:Double) = value(seed, x, y, ::hermite)
inline fun value(seed: Int, x: Double, y: Double, crossinline interpolation: (Double) -> Double = ::linear): Double {
val x0 = x.fastFloor()
val y0 = y.fastFloor()
val x1 = x0 + 1
val y1 = y0 + 1
val xs = interpolation(x - x0)
val ys = interpolation(y - y0)
val xf0 = lerp(valCoord2D(seed, x0, y0), valCoord2D(seed, x1, y0), xs)
val xf1 = lerp(valCoord2D(seed, x0, y1), valCoord2D(seed, x1, y1), xs)
return lerp(xf0, xf1, ys)
}

View File

@@ -0,0 +1,29 @@
package org.openrndr.extra.noise
fun valueLinear(seed: Int, x:Double, y:Double, z:Double) = value(seed, x, y, z, ::linear)
fun valueQuintic(seed: Int, x:Double, y:Double, z:Double) = value(seed, x, y, z, ::quintic)
fun valueHermite(seed: Int, x:Double, y:Double, z:Double) = value(seed, x, y, z, ::hermite)
inline fun value(seed:Int, x: Double, y: Double, z: Double, crossinline interpolation:(Double)->Double = ::linear) : Double {
val x0 = x.fastFloor()
val y0 = y.fastFloor()
val z0 = z.fastFloor()
val x1 = x0 + 1
val y1 = y0 + 1
val z1 = z0 + 1
val xs = interpolation(x - x0)
val ys = interpolation(y - y0)
val zs = interpolation(z - z0)
val xf00 = lerp(valCoord3D(seed, x0, y0, z0), valCoord3D(seed, x1, y0, z0), xs)
val xf10 = lerp(valCoord3D(seed, x0, y1, z0), valCoord3D(seed, x1, y1, z0), xs)
val xf01 = lerp(valCoord3D(seed, x0, y0, z1), valCoord3D(seed, x1, y0, z1), xs)
val xf11 = lerp(valCoord3D(seed, x0, y1, z1), valCoord3D(seed, x1, y1, z1), xs)
val yf0 = lerp(xf00, xf10, ys)
val yf1 = lerp(xf01, xf11, ys)
return lerp(yf0, yf1, zs)
}