Skip to content

Commit

Permalink
[orx-noise] Add generated and verified documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
edwinRNDR committed Jan 19, 2025
1 parent 342c144 commit 3309bd9
Show file tree
Hide file tree
Showing 16 changed files with 792 additions and 31 deletions.
19 changes: 19 additions & 0 deletions orx-noise/src/commonMain/kotlin/Cell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ package org.openrndr.extra.noise
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3

/**
* Represents a 2D array of pre-defined normalized Vector2 values often used
* in algorithms requiring pseudo-random or structured deterministic value sets.
*
* Each `Vector2` instance inside the array constitutes X and Y components
* that are normalized or constrained to a specific range.
*
* This array may serve as a set of offsets, noise gradients, or lookup values
* for computational geometry, randomization, or procedural generation tasks.
*/
val Cell2D = arrayOf(
Vector2(-0.4313539279, 0.1281943404), Vector2(-0.1733316799, 0.415278375), Vector2(-0.2821957395, -0.3505218461), Vector2(-0.2806473808, 0.3517627718), Vector2(0.3125508975, -0.3237467165), Vector2(0.3383018443, -0.2967353402), Vector2(-0.4393982022, -0.09710417025), Vector2(-0.4460443703, -0.05953502905),
Vector2(-0.302223039, 0.3334085102), Vector2(-0.212681052, -0.3965687458), Vector2(-0.2991156529, 0.3361990872), Vector2(0.2293323691, 0.3871778202), Vector2(0.4475439151, -0.04695150755), Vector2(0.1777518, 0.41340573), Vector2(0.1688522499, -0.4171197882), Vector2(-0.0976597166, 0.4392750616),
Expand Down Expand Up @@ -37,6 +47,15 @@ val Cell2D = arrayOf(
Vector2(0.1475103971, -0.4251360756), Vector2(0.09258030352, 0.4403735771), Vector2(-0.1589664637, -0.4209865359), Vector2(0.2482445008, 0.3753327428), Vector2(0.4383624232, -0.1016778537), Vector2(0.06242802956, 0.4456486745), Vector2(0.2846591015, -0.3485243118), Vector2(-0.344202744, -0.2898697484),
Vector2(0.1198188883, -0.4337550392), Vector2(-0.243590703, 0.3783696201), Vector2(0.2958191174, -0.3391033025), Vector2(-0.1164007991, 0.4346847754), Vector2(0.1274037151, -0.4315881062), Vector2(0.368047306, 0.2589231171), Vector2(0.2451436949, 0.3773652989), Vector2(-0.4314509715, 0.12786735))

/**
* `Cell3D` represents a predefined 3-dimensional grid or lattice of points in space, where each point
* is represented as a `Vector3` object containing three coordinates (x, y, z). These coordinates are used
* for various computational purposes such as procedural generation, cell-based simulations, or spatial analysis.
*
* The points in `Cell3D` are statically defined and may represent offsets, directions, or specific positions
* within a system. The choice of values implies a structure or pattern that can be applied to systems utilizing
* a 3D grid or space representation.
*/
val Cell3D = arrayOf(
Vector3(0.1453787434, -0.4149781685, -0.0956981749), Vector3(-0.01242829687, -0.1457918398, -0.4255470325), Vector3(0.2877979582, -0.02606483451, -0.3449535616), Vector3(-0.07732986802, 0.2377094325, 0.3741848704), Vector3(0.1107205875, -0.3552302079, -0.2530858567), Vector3(0.2755209141, 0.2640521179, -0.238463215), Vector3(0.294168941, 0.1526064594, 0.3044271714), Vector3(0.4000921098, -0.2034056362, 0.03244149937),
Vector3(-0.1697304074, 0.3970864695, -0.1265461359), Vector3(-0.1483224484, -0.3859694688, 0.1775613147), Vector3(0.2623596946, -0.2354852944, 0.2796677792), Vector3(-0.2709003183, 0.3505271138, -0.07901746678), Vector3(-0.03516550699, 0.3885234328, 0.2243054374), Vector3(-0.1267712655, 0.1920044036, 0.3867342179), Vector3(0.02952021915, 0.4409685861, 0.08470692262), Vector3(-0.2806854217, -0.266996757, 0.2289725438),
Expand Down
281 changes: 269 additions & 12 deletions orx-noise/src/commonMain/kotlin/Fractal.kt

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions orx-noise/src/commonMain/kotlin/GaussianRandom.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import kotlin.math.ln
import kotlin.math.sqrt
import kotlin.random.Random

/**
* Generates a random number following a Gaussian (normal) distribution.
*
* @param mean The mean of the Gaussian distribution. Defaults to 0.0.
* @param deviation The standard deviation of the Gaussian distribution. Defaults to 1.0.
* @param random The random number generator to use. Defaults to Random.Default.
* @return A random number sampled from the specified Gaussian distribution.
*/
fun gaussian(mean: Double = 0.0, deviation: Double = 1.0, random: Random = Random.Default): Double {
var v1: Double
var v2: Double
Expand All @@ -21,20 +29,52 @@ fun gaussian(mean: Double = 0.0, deviation: Double = 1.0, random: Random = Rando
return v1 * multiplier * deviation + mean
}

/**
* Generates a random number following a Gaussian (normal) distribution.
*
* @param mean The mean of the Gaussian distribution. Defaults to 0.0.
* @param deviation The standard deviation of the Gaussian distribution. Defaults to 1.0.
* @param random The random number generator to use. Defaults to Random.Default.
* @return A random number sampled from the specified Gaussian distribution.
*/
fun Double.Companion.gaussian(
mean: Double = 0.0,
deviation: Double = 1.0,
random: Random = Random.Default
): Double = org.openrndr.extra.noise.gaussian(mean, deviation, random)

/**
* Generates a random 2D vector with components sampled from independent Gaussian (normal) distributions.
*
* @param mean The mean vector of the Gaussian distributions for the x and y components. Defaults to Vector2.ZERO.
* @param deviation The standard deviation vector of the Gaussian distributions for the x and y components. Defaults to Vector2.ONE.
* @param random The random number generator to use. Defaults to Random.Default.
* @return A 2D vector with components sampled from their respective Gaussian distributions.
*/
fun Vector2.Companion.gaussian(mean: Vector2 = Vector2.ZERO, deviation: Vector2 = Vector2.ONE, random: Random = Random.Default): Vector2 {
return Vector2(gaussian(mean.x, deviation.x, random), gaussian(mean.y, deviation.y, random))
}

/**
* Generates a random Vector3 following a Gaussian (normal) distribution.
*
* @param mean The mean vector for the Gaussian distribution. Defaults to Vector3.ZERO.
* @param deviation The standard deviation vector for the Gaussian distribution. Defaults to Vector3.ONE.
* @param random The random number generator to use. Defaults to Random.Default.
* @return A random Vector3 sampled from the specified Gaussian distribution.
*/
fun Vector3.Companion.gaussian(mean: Vector3 = Vector3.ZERO, deviation: Vector3 = Vector3.ONE, random: Random = Random.Default): Vector3 {
return Vector3(gaussian(mean.x, deviation.x, random), gaussian(mean.y, deviation.y, random), gaussian(mean.z, deviation.z, random))
}

/**
* Generates a random `Vector4` where each component is sampled independently from a Gaussian (normal) distribution.
*
* @param mean A `Vector4` representing the mean of the distribution for each component. Defaults to `Vector4.ZERO`.
* @param deviation A `Vector4` representing the standard deviation of the distribution for each component. Defaults to `Vector4.ONE`.
* @param random The random number generator to use. Defaults to `Random.Default`.
* @return A `Vector4` where each component is a random number sampled from the specified Gaussian distribution.
*/
fun Vector4.Companion.gaussian(mean: Vector4 = Vector4.ZERO, deviation: Vector4 = Vector4.ONE, random: Random = Random.Default): Vector4 {
return Vector4(gaussian(mean.x, deviation.x, random), gaussian(mean.y, deviation.y, random), gaussian(mean.z, deviation.z, random), gaussian(mean.w, deviation.w, random))
}
Expand Down
45 changes: 45 additions & 0 deletions orx-noise/src/commonMain/kotlin/GradCoord.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ private val GRAD_3D = arrayOf(
Vector3(0.0, 1.0, 1.0), Vector3(0.0, -1.0, 1.0), Vector3(0.0, 1.0, -1.0), Vector3(0.0, -1.0, -1.0),
Vector3(1.0, 1.0, 0.0), Vector3(0.0, -1.0, 1.0), Vector3(-1.0, 1.0, 0.0), Vector3(0.0, -1.0, -1.0))

/**
* Computes the dot product of a gradient vector and a distance vector in 2D space.
*
* @param seed The seed value used for hashing and determining the gradient vector.
* @param x The x-coordinate in grid space used for hashing.
* @param y The y-coordinate in grid space used for hashing.
* @param xd The x component of the distance vector.
* @param yd The y component of the distance vector.
* @return The dot product of the gradient vector and the distance vector.
*/
fun gradCoord2D(seed: Int, x: Int, y: Int, xd: Double, yd: Double): Double {
val hash = uhash2D(seed, x, y)

Expand All @@ -27,6 +37,18 @@ fun gradCoord2D(seed: Int, x: Int, y: Int, xd: Double, yd: Double): Double {
return xd * x1 + yd * y1
}

/**
* Computes a gradient dot-product noise value for 3D coordinates based on the given seed and position inputs.
*
* @param seed The seed value used to generate the pseudo-random gradient.
* @param x The x-coordinate of the position in 3D space.
* @param y The y-coordinate of the position in 3D space.
* @param z The z-coordinate of the position in 3D space.
* @param xd The x-offset or displacement in 3D space.
* @param yd The y-offset or displacement in 3D space.
* @param zd The z-offset or displacement in 3D space.
* @return The computed gradient dot-product noise value as a Double.
*/
fun gradCoord3D(seed: Int, x: Int, y: Int, z: Int, xd: Double, yd: Double, zd: Double): Double {
val hash = uhash3D(seed, x, y, z)

Expand All @@ -35,6 +57,20 @@ fun gradCoord3D(seed: Int, x: Int, y: Int, z: Int, xd: Double, yd: Double, zd: D
return xd * g.x + yd * g.y + zd * g.z
}

/**
* Computes a gradient coordinate value in 4D space based on the provided inputs.
*
* @param seed An integer seed value used to initialize the hash function.
* @param x The x-coordinate as an integer.
* @param y The y-coordinate as an integer.
* @param z The z-coordinate as an integer.
* @param w The w-coordinate as an integer.
* @param xd The x-offset as a double.
* @param yd The y-offset as a double.
* @param zd The z-offset as a double.
* @param wd The w-offset as a double.
* @return A double value representing the calculated gradient coordinate in 4D space.
*/
fun gradCoord4D(seed: Int, x: Int, y: Int, z: Int, w: Int, xd: Double, yd: Double, zd: Double, wd: Double): Double {
val hash = (uhash4D(seed, x, y, z, w) and 31U).toInt()

Expand Down Expand Up @@ -64,6 +100,15 @@ fun gradCoord4D(seed: Int, x: Int, y: Int, z: Int, w: Int, xd: Double, yd: Doubl
return (if (hash and 4 == 0) -a else a) + (if (hash and 2 == 0) -b else b) + if (hash and 1 == 0) -c else c
}

/**
* Generates a pseudo-random value based on the input seed and 3D coordinates.
*
* @param seed The base seed value used for pseudo-random generation.
* @param x The x-coordinate in the 3D space.
* @param y The y-coordinate in the 3D space.
* @param z The z-coordinate in the 3D space.
* @return A pseudo-random double value calculated using the seed and coordinates.
*/
fun valCoord3D(seed: Int, x: Int, y: Int, z: Int): Double {
var n = seed
n = n xor X_PRIME * x
Expand Down
53 changes: 53 additions & 0 deletions orx-noise/src/commonMain/kotlin/GradientPerturb.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.math.mix

/**
* Applies fractal gradient perturbation to a 3D position vector.
*
* This method perturbs the input position vector using a fractal noise pattern based on multiple
* octaves of gradient noise. It combines parameters such as amplitude, frequency, lacunarity, and gain
* to control the noise characteristics, while supporting custom interpolation.
*
* @param seed The initial seed value to generate the noise.
* @param amplitude The initial magnitude of the displacement during the perturbation.
* @param frequency The base frequency for the noise generation.
* @param lacunarity The frequency multiplier between successive octaves.
* @param gain The amplitude multiplier between successive octaves.
* @param octaves The number of noise layers (octaves) to combine in the fractal calculation.
* @param position The input 3D vector representing the position to perturb.
* @param interpolator A function to apply smooth interpolation, typically used for gradient noise transitions.
* @return The perturbed 3D position vector after applying the fractal gradient perturbation.
*/
fun gradientPerturbFractal(
seed: Int, amplitude: Double = 1.0, frequency: Double = 2.0,
lacunarity: Double = 2.0, gain: Double = 0.5,
Expand All @@ -24,6 +41,17 @@ fun gradientPerturbFractal(
return p
}

/**
* Perturbs a position vector in 3D space by applying a gradient noise algorithm.
*
* @param seed The seed value used for generating deterministic patterns.
* @param amplitude The amplitude of the perturbation, which controls the scale of displacement.
* @param frequency The frequency of the perturbation, which determines the scale of the noise.
* @param position The original position vector to be perturbed.
* @param interpolator The interpolation function used to smooth the noise transitions,
* defaulting to the quintic function.
* @return A new position vector that has been perturbed by the gradient noise algorithm.
*/
fun gradientPerturb(
seed: Int,
amplitude: Double,
Expand Down Expand Up @@ -85,6 +113,21 @@ fun gradientPerturb(
) * amplitude
}

/**
* Applies fractal gradient perturbation to the given position vector using the specified parameters.
* This method introduces multiple layers of noise to create a fractal effect by perturbing the position iteratively
* based on the number of octaves, frequency, and amplitude adjustments.
*
* @param seed An integer seed used to initialize the random number generator for noise generation.
* @param amplitude The initial amplitude of the perturbation. Higher values result in larger displacements.
* @param frequency The initial frequency of the noise. Higher values increase the density of the noise variation.
* @param lacunarity The rate at which the frequency increases with each octave.
* @param gain The rate at which the amplitude decreases with each octave.
* @param octaves The number of fractal noise layers to apply. More octaves increase detail.
* @param position A 2D vector representing the original point to be perturbed.
* @param interpolator A function that defines how to interpolate values smoothly. Defaults to the quintic function.
* @return A 2D vector representing the perturbed position after applying the fractal gradient noise.
*/
fun gradientPerturbFractal(
seed: Int, amplitude: Double = 1.0, frequency: Double = 2.0,
lacunarity: Double = 2.0, gain: Double = 0.5,
Expand All @@ -105,6 +148,16 @@ fun gradientPerturbFractal(
return p
}

/**
* Calculates a perturbed position based on gradient noise.
*
* @param seed An integer seed value used to initialize the pseudo-random number generator.
* @param amplitude A double value that determines the strength of the perturbation applied to the position.
* @param frequency A double value that defines how frequent the perturbation occurs in the space.
* @param position A 2D vector specifying the initial position to perturb.
* @param interpolator A function used for interpolation between gradient values, defaults to the quintic interpolation function.
* @return A 2D vector that represents the new perturbed position.
*/
fun gradientPerturb(
seed: Int,
amplitude: Double,
Expand Down
28 changes: 28 additions & 0 deletions orx-noise/src/commonMain/kotlin/Interpolation.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
package org.openrndr.extra.noise

/**
* Computes the Hermite interpolation function value for the given parameter.
*
* The Hermite interpolation ensures smooth transitions and is often used in
* animations or procedural generation to create a smooth curve between points.
*
* @param t A double value representing the parameter for the interpolation.
* It is usually expected to be in the range [0.0, 1.0].
* @return The interpolated value based on the Hermite polynomial.
*/
fun hermite(t: Double): Double {
return t * t * (3 - 2 * t)
}

/**
* Calculates the result of the quintic polynomial function, commonly used in smooth interpolation.
*
* The function is defined as t^3 * (t * (t * 6 - 15) + 10), where t is the input value.
*
* @param t The input value for which the quintic function is to be calculated.
* @return The result of the quintic polynomial for the given input value.
*/
fun quintic(t: Double): Double {
return t * t * t * (t * (t * 6 - 15) + 10)
}

/**
* Computes the value of a cubic interpolation given control points and a parameter t.
*
* @param a The first control point.
* @param b The second control point.
* @param c The third control point.
* @param d The fourth control point.
* @param t The interpolation factor, typically between 0 and 1.
* @return The interpolated value at the given t.
*/
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
Expand Down
12 changes: 0 additions & 12 deletions orx-noise/src/commonMain/kotlin/Polar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,3 @@ fun ((Int, Double, Double) -> Double).fixedRadiusPolar(
origin: Vector2 = Vector2.ZERO
): (Int, Double) -> Double =
fixedRadiusPolarFunc(this, radius, origin)



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()

}
13 changes: 11 additions & 2 deletions orx-noise/src/commonMain/kotlin/ShapeNoise.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,24 @@ import org.openrndr.shape.*
import kotlin.random.Random

/**
* Generates specified amount of random points that lie inside the [Shape].
* Generates a list of uniformly distributed points within the shape provided by the ShapeProvider.
*
* @param pointCount The number of points to generate.
* @param random The [Random] number generator to use, defaults to [Random.Default].
* @param random An optional random number generator to influence the distribution.
* @return A list of Vector2 objects representing the uniformly distributed points.
*/
fun ShapeProvider.uniform(pointCount: Int, random: Random = Random.Default): List<Vector2> {
return shape.triangulation.uniform(pointCount, random)
}

/**
* Generates a list of hashed points based on the shape's triangulation.
*
* @param pointCount The number of points to generate in the hashed result.
* @param seed The seed value used for randomization in the hashing process.
* @param x An additional parameter used in the hashing process to modify randomization.
* @return A list of vectors representing the hashed points.
*/
fun ShapeProvider.hash(pointCount: Int, seed: Int, x: Int): List<Vector2> {
return shape.triangulation.hash(pointCount, seed, x)
}
Expand Down
16 changes: 15 additions & 1 deletion orx-noise/src/commonMain/kotlin/SimplexNoise2D.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ 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)
/**
* Computes a 2D simplex noise value for given coordinates and seed.
*
* @param seed The seed value used for generating the noise.
* @param x The x-coordinate in 2D space for which the noise value is calculated.
* @param y The y-coordinate in 2D space for which the noise value is calculated.
* @return The 2D simplex noise value for the given coordinates and seed.
*/
fun simplex(seed: Int, x: Double, y: Double): Double {
var t = (x + y) * F2
val i = (x + t).fastFloor()
Expand Down Expand Up @@ -70,6 +77,13 @@ val simplex2D: (Int, Double, Double) -> Double = ::simplex
val simplex3D: (Int, Double, Double, Double) -> Double = ::simplex
val simplex4D: (Int, Double, Double, Double) -> Double = ::simplex

/**
* Generates a 2D simplex noise vector based on the given seed and input position.
*
* @param seed The seed value used to generate deterministic noise.
* @param x The x-coordinate for the noise generation.
* @return A Vector2 object representing the 2D noise values at the given position.
*/
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)
Expand Down
Loading

0 comments on commit 3309bd9

Please sign in to comment.