From 454affbdfdcb3962414753ddeadad9084a733f48 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sun, 25 Jul 2021 22:36:07 +0200 Subject: [PATCH] [orx-noise] Add tools for functional composition --- orx-noise/README.md | 21 ++ .../src/commonMain/kotlin/CubicNoise1D.kt | 6 +- .../src/commonMain/kotlin/CubicNoise2D.kt | 6 +- .../src/commonMain/kotlin/CubicNoise3D.kt | 6 +- orx-noise/src/commonMain/kotlin/Fractal.kt | 337 ++++++++++++++---- orx-noise/src/commonMain/kotlin/Functions.kt | 96 +++++ .../src/commonMain/kotlin/PerlinNoise1D.kt | 4 +- .../src/commonMain/kotlin/PerlinNoise2D.kt | 4 +- .../src/commonMain/kotlin/PerlinNoise3D.kt | 4 +- orx-noise/src/commonMain/kotlin/Polar.kt | 77 ++++ .../src/commonMain/kotlin/SimplexNoise2D.kt | 13 +- .../src/commonMain/kotlin/ValueNoise1D.kt | 6 +- .../src/commonMain/kotlin/ValueNoise2D.kt | 6 +- .../src/commonMain/kotlin/ValueNoise3D.kt | 6 +- orx-noise/src/commonMain/kotlin/Vector.kt | 14 + 15 files changed, 532 insertions(+), 74 deletions(-) create mode 100644 orx-noise/src/commonMain/kotlin/Functions.kt create mode 100644 orx-noise/src/commonMain/kotlin/Polar.kt create mode 100644 orx-noise/src/commonMain/kotlin/Vector.kt diff --git a/orx-noise/README.md b/orx-noise/README.md index 7ad26d0c..35407be2 100644 --- a/orx-noise/README.md +++ b/orx-noise/README.md @@ -26,6 +26,27 @@ val v4ur = Vector4.uniformRing(0.5, 1.0) val ringSamples = List(500) { Vector2.uniformRing() } ``` +## Noise function composition + +Since ORX 0.4 the orx-noise module comes with functional composition tooling that allow one to create complex noise +functions. + +```kotlin +// create an FBM version of 1D linear perlin noise +val myNoise0 = perlinLinear1D.fbm(octaves=3) +val noiseValue0 = myNoise0(431, seconds) + +// create polar version of 2D simplex noise +val myNoise1 = simplex2D.withPolarInput() +val noiseValue1 = myNoise1(5509, Polar(seconds*60.0, 0.5)) + +// create value linear noise with squared outputs which is then billowed +val myNoise2 = valueLinear1D.mapOutput { it * it }.billow() +val noiseValue2 = myNoise2(993, seconds * 0.1) +``` + + + ## Multi-dimensional noise These are a mostly straight port from FastNoise-Java but have a slightly different interface. diff --git a/orx-noise/src/commonMain/kotlin/CubicNoise1D.kt b/orx-noise/src/commonMain/kotlin/CubicNoise1D.kt index 881f3ad8..417ba498 100644 --- a/orx-noise/src/commonMain/kotlin/CubicNoise1D.kt +++ b/orx-noise/src/commonMain/kotlin/CubicNoise1D.kt @@ -7,4 +7,8 @@ fun cubicHermite(seed: Int, x: Double) = cubic(seed, x, ::hermite) fun cubic(seed: Int, x: Double, interpolator: (Double) -> Double = ::linear): Double { return cubic(seed, x, 0.0, interpolator) -} \ No newline at end of file +} + +val cubicLinear1D: (Int, Double) -> Double = ::cubicLinear +val cubicQuintic1D: (Int, Double) -> Double = ::cubicQuintic +val cubicHermite1D: (Int, Double) -> Double = ::cubicHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/CubicNoise2D.kt b/orx-noise/src/commonMain/kotlin/CubicNoise2D.kt index 9bd28940..e27df4f8 100644 --- a/orx-noise/src/commonMain/kotlin/CubicNoise2D.kt +++ b/orx-noise/src/commonMain/kotlin/CubicNoise2D.kt @@ -38,4 +38,8 @@ fun cubic(seed: Int, x: Double, y: Double, interpolator: (Double) -> Double = :: cubic(valCoord2D(seed, x0, y3), valCoord2D(seed, x1, y3), valCoord2D(seed, x2, y3), valCoord2D(seed, x3, y3), xs), ys) * CUBIC_2D_BOUNDING -} \ No newline at end of file +} + +val cubicLinear2D: (Int, Double, Double) -> Double = ::cubicLinear +val cubicQuintic2D: (Int, Double, Double) -> Double = ::cubicQuintic +val cubicHermite2D: (Int, Double, Double) -> Double = ::cubicHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/CubicNoise3D.kt b/orx-noise/src/commonMain/kotlin/CubicNoise3D.kt index d689f19e..cfa0db59 100644 --- a/orx-noise/src/commonMain/kotlin/CubicNoise3D.kt +++ b/orx-noise/src/commonMain/kotlin/CubicNoise3D.kt @@ -59,4 +59,8 @@ fun cubic(seed: Int, x: Double, y: Double, z: Double, interpolator: (Double) -> 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 -} \ No newline at end of file +} + +val cubicLinear3D: (Int, Double, Double, Double) -> Double = ::cubicLinear +val cubicQuintic3D: (Int, Double, Double, Double) -> Double = ::cubicQuintic +val cubicHermite3D: (Int, Double, Double, Double) -> Double = ::cubicHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/Fractal.kt b/orx-noise/src/commonMain/kotlin/Fractal.kt index 12c42688..4a1ebb88 100644 --- a/orx-noise/src/commonMain/kotlin/Fractal.kt +++ b/orx-noise/src/commonMain/kotlin/Fractal.kt @@ -5,12 +5,23 @@ import org.openrndr.math.Vector3 import org.openrndr.math.Vector4 import kotlin.math.abs -inline fun fbm(seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - fbm(seed, position.x, position.y, position.z, position.w, noise, octaves, lacunarity, gain) +inline fun fbm( + seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + fbm(seed, position.x, position.y, position.z, position.w, noise, octaves, lacunarity, gain) -inline fun fbm(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun fbm( + seed: Int, + x: Double, + y: Double, + z: Double, + w: Double, + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): Double { var sum = noise(seed, x, y, z, w) var amp = 1.0 @@ -29,12 +40,16 @@ inline fun fbm(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinlin return sum } -inline fun fbm(seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - fbm(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) +inline fun fbm( + seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + fbm(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) -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 { +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 @@ -51,12 +66,16 @@ inline fun fbm(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (I return sum } -inline fun fbm(seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - fbm(seed, position.x, position.y, noise, octaves, lacunarity, gain) +inline fun fbm( + seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + fbm(seed, position.x, position.y, noise, octaves, lacunarity, gain) -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 { +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 @@ -71,8 +90,10 @@ inline fun fbm(seed: Int, x: Double, y: Double, crossinline noise: (Int, Double, return sum } -inline fun fbm(seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun fbm( + seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +): Double { var sum = noise(seed, x) var amp = 1.0 @@ -85,36 +106,69 @@ inline fun fbm(seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, return sum } -inline fun fbmFunc1D(crossinline noise: (Int, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double) -> Double { +inline fun fbmFunc1D( + crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double { return { seed, x -> fbm(seed, x, noise, octaves, lacunarity, gain) } } -inline fun fbmFunc2D(crossinline noise: (Int, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double) -> Double { +inline fun fbmFunc2D( + crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double { return { seed, x, y -> fbm(seed, x, y, noise, octaves, lacunarity, gain) } } -inline fun fbmFunc3D(crossinline noise: (Int, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double) -> Double { +inline fun fbmFunc3D( + crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double { return { seed, x, y, z -> fbm(seed, x, y, z, noise, octaves, lacunarity, gain) } } -inline fun fbmFunc4D(crossinline noise: (Int, Double, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double, Double) -> Double { +inline fun fbmFunc4D( + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double { return { seed, x, y, z, w -> fbm(seed, x, y, z, w, noise, octaves, lacunarity, gain) } } -inline fun billow(seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = billow(seed, position.x, position.y, - position.z, position.w, noise, octaves, lacunarity, gain) +inline fun billow( + seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = billow( + seed, position.x, position.y, + position.z, position.w, noise, octaves, lacunarity, gain +) -inline fun billow(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun billow( + seed: Int, + x: Double, + y: Double, + z: Double, + w: Double, + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): Double { var sum = abs(noise(seed, x, y, z, w) * 2.0 - 1.0) var amp = 1.0 @@ -133,12 +187,16 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, w: Double, crossin return sum } -inline fun billow(seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - billow(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) +inline fun billow( + seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + billow(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) -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 { +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 = abs(noise(seed, x, y, z) * 2.0 - 1.0) var amp = 1.0 @@ -155,12 +213,16 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, crossinline noise: return sum } -inline fun billow(seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - billow(seed, position.x, position.y, noise, octaves, lacunarity, gain) +inline fun billow( + seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + billow(seed, position.x, position.y, noise, octaves, lacunarity, gain) -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 { +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 = abs(noise(seed, x, y) * 2.0 - 1.0) var amp = 1.0 @@ -175,8 +237,10 @@ inline fun billow(seed: Int, x: Double, y: Double, crossinline noise: (Int, Doub return sum } -inline fun billow(seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun billow( + seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +): Double { var sum = abs(noise(seed, x) * 2.0 - 1.0) var amp = 1.0 @@ -189,36 +253,67 @@ inline fun billow(seed: Int, x: Double, crossinline noise: (Int, Double) -> Doub return sum } -inline fun billowFunc1D(crossinline noise: (Int, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double) -> Double { +inline fun billowFunc1D( + crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double { return { seed, x -> billow(seed, x, noise, octaves, lacunarity, gain) } } -inline fun billowFunc2D(crossinline noise: (Int, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double) -> Double { +inline fun billowFunc2D( + crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double { return { seed, x, y -> billow(seed, x, y, noise, octaves, lacunarity, gain) } } -inline fun billowFunc3D(crossinline noise: (Int, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double) -> Double { +inline fun billowFunc3D( + crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double { return { seed, x, y, z -> billow(seed, x, y, z, noise, octaves, lacunarity, gain) } } -inline fun billowFunc4D(crossinline noise: (Int, Double, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double, Double) -> Double { +inline fun billowFunc4D( + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double { return { seed, x, y, z, w -> billow(seed, x, y, z, w, noise, octaves, lacunarity, gain) } } -inline fun rigid(seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - rigid(seed, position.x, position.y, position.z, position.w, noise, octaves, lacunarity, gain) +inline fun rigid( + seed: Int, position: Vector4, crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + rigid(seed, position.x, position.y, position.z, position.w, noise, octaves, lacunarity, gain) -inline fun rigid(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinline noise: (Int, Double, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun rigid( + seed: Int, + x: Double, + y: Double, + z: Double, + w: Double, + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): Double { var sum = 1.0 - abs(noise(seed, x, y, z, w)) var amp = 1.0 @@ -237,12 +332,16 @@ inline fun rigid(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinl return sum } -inline fun rigid(seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - rigid(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) +inline fun rigid( + seed: Int, position: Vector3, crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + rigid(seed, position.x, position.y, position.z, noise, octaves, lacunarity, gain) -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 { +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 - abs(noise(seed, x, y, z)) var amp = 1.0 @@ -259,12 +358,16 @@ inline fun rigid(seed: Int, x: Double, y: Double, z: Double, crossinline noise: return sum } -inline fun rigid(seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5) = - rigid(seed, position.x, position.y, noise, octaves, lacunarity, gain) +inline fun rigid( + seed: Int, position: Vector2, crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +) = + rigid(seed, position.x, position.y, noise, octaves, lacunarity, gain) -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 { +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 - abs(noise(seed, x, y)) var amp = 1.0 @@ -279,8 +382,10 @@ inline fun rigid(seed: Int, x: Double, y: Double, crossinline noise: (Int, Doubl return sum } -inline fun rigid(seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, - octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double { +inline fun rigid( + seed: Int, x: Double, crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5 +): Double { var sum = 1.0 - abs(noise(seed, x)) var amp = 1.0 @@ -293,26 +398,132 @@ inline fun rigid(seed: Int, x: Double, crossinline noise: (Int, Double) -> Doubl return sum } -inline fun rigidFunc1D(crossinline noise: (Int, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double) -> Double { +inline fun rigidFunc1D( + crossinline noise: (Int, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double { return { seed, x -> rigid(seed, x, noise, octaves, lacunarity, gain) } } -inline fun rigidFunc2D(crossinline noise: (Int, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double) -> Double { +inline fun rigidFunc2D( + crossinline noise: (Int, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double { return { seed, x, y -> rigid(seed, x, y, noise, octaves, lacunarity, gain) } } -inline fun rigidFunc3D(crossinline noise: (Int, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double) -> Double { +inline fun rigidFunc3D( + crossinline noise: (Int, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double { return { seed, x, y, z -> rigid(seed, x, y, z, noise, octaves, lacunarity, gain) } } -inline fun rigidFunc4D(crossinline noise: (Int, Double, Double, Double, Double) -> Double, octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): (Int, Double, Double, Double, Double) -> Double { +inline fun rigidFunc4D( + crossinline noise: (Int, Double, Double, Double, Double) -> Double, + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double { return { seed, x, y, z, w -> rigid(seed, x, y, z, w, noise, octaves, lacunarity, gain) } } + +// functional composition tools + +fun ((Int, Double) -> Double).fbm( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double = + fbmFunc1D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double) -> Double).fbm( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double = + fbmFunc2D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double) -> Double).fbm( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double = + fbmFunc3D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double, Double) -> Double).fbm( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double = + fbmFunc4D(this, octaves, lacunarity, gain) + +fun ((Int, Double) -> Double).billow( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double = + billowFunc1D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double) -> Double).billow( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double = + billowFunc2D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double) -> Double).billow( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double = + billowFunc3D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double, Double) -> Double).billow( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double = + billowFunc4D(this, octaves, lacunarity, gain) + +fun ((Int, Double) -> Double).rigid( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double) -> Double = + rigidFunc1D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double) -> Double).rigid( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double) -> Double = + rigidFunc2D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double) -> Double).rigid( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double) -> Double = + rigidFunc3D(this, octaves, lacunarity, gain) + +fun ((Int, Double, Double, Double, Double) -> Double).rigid( + octaves: Int = 8, + lacunarity: Double = 0.5, + gain: Double = 0.5 +): (Int, Double, Double, Double, Double) -> Double = + rigidFunc4D(this, octaves, lacunarity, gain) diff --git a/orx-noise/src/commonMain/kotlin/Functions.kt b/orx-noise/src/commonMain/kotlin/Functions.kt new file mode 100644 index 00000000..333788df --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/Functions.kt @@ -0,0 +1,96 @@ +package org.openrndr.extra.noise + +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector3 +import org.openrndr.math.Vector4 +import kotlin.jvm.JvmName + +fun ((Double) -> Double).withSeedAsOffset(offset: Double): (Int, Double) -> Double = { seed, x -> + this(x + seed * offset) +} + +fun ((Int, Double) -> Double).withFixedSeed(seed: Int): (Double) -> Double = { x -> this(seed, x) } + +fun ((Int, Double) -> Double).scaleBiasOutput( + scale: Double = 1.0, + bias: Double = 0.0 +): (Int, Double) -> Double = { seed, x -> + this(seed, x) * scale + bias +} + +fun ((Int, Double) -> Double).mapOutput(map: (Double)->Double): (Int, Double) -> Double = { seed, x -> + map(this(seed, x)) +} + +fun ((Int, Double, Double) -> Double).withVector2Input(): (Int, Vector2) -> Double = { seed, v -> + this(seed, v.x, v.y) +} + +@JvmName("scaleBiasVector2") +fun ((Int, Vector2) -> Double).scaleBiasOutput( + scale: Double = 1.0, + bias: Double = 0.0 +): (Int, Vector2) -> Double = { seed, v -> + this(seed, v) * scale + bias +} + +fun ((Int, Double, Double) -> Double).scaleBiasOutput( + scale: Double = 1.0, + bias: Double = 0.0 +): (Int, Double, Double) -> Double = { seed, x, y -> + this(seed, x, y) * scale + bias +} + +fun ((Int, Vector2) -> Double).withScalarInput(): (Int, Double, Double) -> Double = { seed, x, y -> + this(seed, Vector2(x, y)) +} + +fun ((Int, Double, Double, Double) -> Double).withVector3Input(): (Int, Vector3) -> Double = { seed, v -> + this(seed, v.x, v.y, v.z) +} + +fun ((Int, Vector3) -> Double).withScalarInput(): (Int, Double, Double, Double) -> Double = { seed, x, y, z -> + this(seed, Vector3(x, y, z)) +} + +fun ((Int, Double, Double, Double, Double) -> Double).withVector4Input(): (Int, Vector4) -> Double = { seed, v -> + this(seed, v.x, v.y, v.z, v.w) +} + +@JvmName("perturb1") +fun ((Int, Double) -> Double).perturb(distort: (Double) -> Double): (Int, Double) -> Double = + { seed, x -> + this(seed, distort(x)) + } + +@JvmName("perturb2v") +inline fun ((Int, Vector2) -> Double).perturb(crossinline distort: (Vector2) -> Vector2): (Int, Vector2) -> Double = + { seed, v -> + this(seed, distort(v)) + } + +@JvmName("perturb2ds") +inline fun ((Int, Double, Double) -> Double).perturb(crossinline distort: (Vector2) -> Vector2): (Int, Double, Double) -> Double = + { seed, x, y -> + val d = distort(Vector2(x, y)) + this(seed, d.x, d.y) + } + +@JvmName("perturb3") +inline fun ((Int, Vector3) -> Double).perturb(crossinline distort: (Vector3) -> Vector3): (Int, Vector3) -> Double = + { seed, v -> + this(seed, distort(v)) + } + +@JvmName("perturb3ds") +inline fun ((Int, Double, Double, Double) -> Double).perturb(crossinline distort: (Vector3) -> Vector3): (Int, Double, Double, Double) -> Double = + { seed, x, y, z -> + val d = distort(Vector3(x, y, z)) + this(seed, d.x, d.y, d.z) + } + +@JvmName("perturb4") +inline fun ((Int, Vector4) -> Double).perturb(crossinline distort: (Vector4) -> Vector4): (Int, Vector4) -> Double = + { seed, v -> + this(seed, distort(v)) + } \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/PerlinNoise1D.kt b/orx-noise/src/commonMain/kotlin/PerlinNoise1D.kt index 95539e8d..9e8070eb 100644 --- a/orx-noise/src/commonMain/kotlin/PerlinNoise1D.kt +++ b/orx-noise/src/commonMain/kotlin/PerlinNoise1D.kt @@ -6,4 +6,6 @@ fun perlinQuintic(seed: Int, x: Double) = perlin(seed, x, ::quintic) fun perlinHermite(seed: Int, x: Double) = perlin(seed, x, ::hermite) inline fun perlin(seed: Int, x: Double, crossinline interpolator: (Double) -> Double): Double = - perlin(seed, x, 0.0, interpolator) \ No newline at end of file + perlin(seed, x, 0.0, interpolator) + +val perlin1D: (Int, Double) -> Double = ::perlin \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/PerlinNoise2D.kt b/orx-noise/src/commonMain/kotlin/PerlinNoise2D.kt index 14a31ec7..6b502c30 100644 --- a/orx-noise/src/commonMain/kotlin/PerlinNoise2D.kt +++ b/orx-noise/src/commonMain/kotlin/PerlinNoise2D.kt @@ -31,4 +31,6 @@ inline fun perlin(seed: Int, x: Double, y: Double, crossinline interpolator: (Do val xf1 = mix(gradCoord2D(seed, x0, y1, xd0, yd1), gradCoord2D(seed, x1, y1, xd1, yd1), xs) return mix(xf0, xf1, ys) -} \ No newline at end of file +} + +val perlin2D: (Int, Double, Double) -> Double = ::perlin \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/PerlinNoise3D.kt b/orx-noise/src/commonMain/kotlin/PerlinNoise3D.kt index 889962e7..218b6fed 100644 --- a/orx-noise/src/commonMain/kotlin/PerlinNoise3D.kt +++ b/orx-noise/src/commonMain/kotlin/PerlinNoise3D.kt @@ -39,4 +39,6 @@ inline fun perlin(seed: Int, x: Double, y: Double, z: Double, crossinline interp val yf1 = mix(xf01, xf11, ys) return mix(yf0, yf1, zs) -} \ No newline at end of file +} + +val perlin3D: (Int, Double, Double, Double) -> Double = ::perlinLinear \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/Polar.kt b/orx-noise/src/commonMain/kotlin/Polar.kt new file mode 100644 index 00000000..f073f2ba --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/Polar.kt @@ -0,0 +1,77 @@ +package org.openrndr.extra.noise + +import org.openrndr.math.Polar +import org.openrndr.math.Vector2 + +/** + * Polar coordinate front-end for 2D noise functions + */ +fun polarFunc( + noise: (Int, Double, Double) -> Double, + origin: Vector2 = Vector2.ZERO, +): (seed: Int, polar: Polar) -> Double { + return { seed, polar -> + val c = polar.cartesian + origin + noise(seed, c.x, c.y) + } +} + +/** + * Polar coordinate front-end for 2D noise functions + */ +fun fixedRadiusPolarFunc( + noise: (Int, Double, Double) -> Double, + radius: Double, + origin: Vector2 = Vector2.ZERO, +): (seed: Int, angleInDegrees: Double) -> Double { + return { seed, angleInDegrees -> + val c = Polar(angleInDegrees, radius).cartesian + origin + noise(seed, c.x, c.y) + } +} + +/** + * Polar coordinate front-end for 2D noise functions with variable offset + */ +fun polarOffsetFunc( + noise: (Int, Double, Double) -> Double, + origin: Vector2 = Vector2.ZERO, + +): (seed: Int, polar: Polar, offset: Vector2) -> Double { + return { seed, polar, offset -> + val c = polar.cartesian + origin + offset + noise(seed, c.x, c.y) + } +} + +fun ((Int, Double, Double) -> Double).withPolarInput(origin: Vector2 = Vector2.ZERO): (Int, Polar) -> Double = + polarFunc(this, origin) + +fun ((Int, Vector2) -> Double).withPolarInput(origin: Vector2 = Vector2.ZERO): (Int, Polar) -> Double = + polarFunc(this.withScalarInput(), origin) + + +fun ((Int, Double, Double) -> Double).withPolarOffsetInput(origin: Vector2 = Vector2.ZERO): (Int, Polar, Vector2) -> Double = + polarOffsetFunc(this, origin) + + +fun ((Int, Vector2) -> Double).withPolarOffsetInput(origin: Vector2 = Vector2.ZERO): (Int, Polar, Vector2) -> Double = + polarOffsetFunc(this.withScalarInput(), origin) + + + +fun ((Int, Double, Double) -> Double).fixedRadiusPolar( + radius: Double, + origin: Vector2 = Vector2.ZERO +): (Int, Double) -> Double = + fixedRadiusPolarFunc(this, radius, origin) + +private fun example() { + val polarFbmSimplex = polarFunc(noise = fbmFunc2D(noise = ::simplex)) + val polarBillowPerlin = polarFunc(noise = billowFunc2D(noise = ::perlin)) + + val polarFbmSimplexAlt = fbmFunc2D(noise = ::simplex).withPolarInput() + + val polarFbm = simplex2D.fbm().withPolarInput() + +} \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/SimplexNoise2D.kt b/orx-noise/src/commonMain/kotlin/SimplexNoise2D.kt index 2c34689d..23b8f8ea 100644 --- a/orx-noise/src/commonMain/kotlin/SimplexNoise2D.kt +++ b/orx-noise/src/commonMain/kotlin/SimplexNoise2D.kt @@ -8,6 +8,8 @@ private const val G2 = (3.0 - SQRT3) / 6.0 fun simplex(seed: Int, position: Vector2): Double = simplex(seed, position.x, position.y) + +//fun simplex2D(seed:Int, x:Double, y:Double) = simplex(seed, x, y) fun simplex(seed: Int, x: Double, y: Double): Double { var t = (x + y) * F2 val i = (x + t).fastFloor() @@ -63,5 +65,12 @@ fun simplex(seed: Int, x: Double, y: Double): Double { return 50.0 * (n0 + n1 + n2) } -fun Vector2.Companion.simplex(seed: Int, x: Double): Vector2 = Vector2(simplex(seed, x, 0.0, 0.0, 0.0), - simplex(seed, 0.0, x + 31.3383, 0.0, 0.0)) \ No newline at end of file +val simplex1D: (Int, Double) -> Double = ::simplex +val simplex2D: (Int, Double, Double) -> Double = ::simplex +val simplex3D: (Int, Double, Double, Double) -> Double = ::simplex +val simplex4D: (Int, Double, Double, Double) -> Double = ::simplex + +fun Vector2.Companion.simplex(seed: Int, x: Double): Vector2 = Vector2( + simplex(seed, x, 0.0, 0.0, 0.0), + simplex(seed, 0.0, x + 31.3383, 0.0, 0.0) +) \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/ValueNoise1D.kt b/orx-noise/src/commonMain/kotlin/ValueNoise1D.kt index 86b5e880..ef3ffeba 100644 --- a/orx-noise/src/commonMain/kotlin/ValueNoise1D.kt +++ b/orx-noise/src/commonMain/kotlin/ValueNoise1D.kt @@ -5,4 +5,8 @@ fun valueQuintic(seed: Int, x: Double) = value(seed, x, ::quintic) fun valueHermite(seed: Int, x: Double) = value(seed, x, ::hermite) inline fun value(seed: Int, x: Double, crossinline interpolation: (Double) -> Double = ::linear): Double = - value(seed, x, 0.0, interpolation) \ No newline at end of file + value(seed, x, 0.0, interpolation) + +val valueLinear1D: (Int, Double) -> Double = ::valueLinear +val valueQuintic1D: (Int, Double) -> Double = ::valueQuintic +val valueHermite1D: (Int, Double) -> Double = ::valueHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/ValueNoise2D.kt b/orx-noise/src/commonMain/kotlin/ValueNoise2D.kt index e4c4173c..26d3c369 100644 --- a/orx-noise/src/commonMain/kotlin/ValueNoise2D.kt +++ b/orx-noise/src/commonMain/kotlin/ValueNoise2D.kt @@ -29,4 +29,8 @@ inline fun value(seed: Int, x: Double, y: Double, crossinline interpolation: (Do val xf1 = mix(valCoord2D(seed, x0, y1), valCoord2D(seed, x1, y1), xs) return mix(xf0, xf1, ys) -} \ No newline at end of file +} + +val valueLinear2D: (Int, Double, Double) -> Double = ::valueLinear +val valueQuintic2D: (Int, Double, Double) -> Double = ::valueQuintic +val valueHermite2D: (Int, Double, Double) -> Double = ::valueHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/ValueNoise3D.kt b/orx-noise/src/commonMain/kotlin/ValueNoise3D.kt index dd17f91a..8c40da5c 100644 --- a/orx-noise/src/commonMain/kotlin/ValueNoise3D.kt +++ b/orx-noise/src/commonMain/kotlin/ValueNoise3D.kt @@ -38,4 +38,8 @@ inline fun value(seed: Int, x: Double, y: Double, z: Double, crossinline interpo val yf1 = mix(xf01, xf11, ys) return mix(yf0, yf1, zs) -} \ No newline at end of file +} + +val valueLinear3D: (Int, Double, Double, Double) -> Double = ::valueLinear +val valueQuintic3D: (Int, Double, Double, Double) -> Double = ::valueQuintic +val valueHermite3D: (Int, Double, Double, Double) -> Double = ::valueHermite \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/Vector.kt b/orx-noise/src/commonMain/kotlin/Vector.kt new file mode 100644 index 00000000..18495f9e --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/Vector.kt @@ -0,0 +1,14 @@ +package org.openrndr.extra.noise + +import org.openrndr.math.Vector2 + +fun ((Int, Double) -> Double).vector2(): (seed: Int, x: Double) -> Vector2 { + val ref = this + return { seed:Int, x:Double -> + Vector2(ref(-seed, x), ref(seed, -x)) + } +} + +private fun exampleVector() { + ::simplex2D +}