All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.math.perlin.PerlinNoise.kt Maven / Gradle / Ivy

package ru.casperix.math.perlin

import ru.casperix.math.vector.float64.Vector2d
import kotlin.math.cos
import kotlin.math.sin

/**
 * https://en.wikipedia.org/wiki/Perlin_noise
 */
object PerlinNoise {
	/* Function to linearly interpolate between a0 and a1
 * Weight w should be in the range [0.0, 1.0]
 */
	fun interpolate(a0:Double, a1:Double, w:Double):Double {
		/* // You may want clamping by inserting:
		 * if (0.0 > w) return a0;
		 * if (1.0 < w) return a1;
		 */
		return (a1 - a0) * w + a0;
		/* // Use this cubic interpolation [[Smoothstep]] instead, for a smooth appearance:
		 * return (a1 - a0) * (3.0 - w * 2.0) * w * w + a0;
		 *
		 * // Use [[Smootherstep]] for an even smoother result with a second derivative equal to zero on boundaries:
		 * return (a1 - a0) * (x * (w * 6.0 - 15.0) * w * w *w + 10.0) + a0;
		 */
	}

/* Create random direction vector
 */
	fun randomGradient(ix:Int, iy:Int): Vector2d {
		// Random float. No precomputed gradients mean this works for any number of grid coordinates
		val random = 2920.0 * sin(ix * 21942.0 + iy * 171324.0 + 8912.0) * cos(ix * 23157.0 * iy * 217832.0 + 9758.0);
		return Vector2d(cos(random), sin(random))
	}

// Computes the dot product of the distance and gradient vectors.
	fun dotGridGradient(ix:Int, iy:Int, x:Double, y:Double):Double {
		// Get gradient from integer coordinates
		val gradient = randomGradient(ix, iy)

		// Compute the distance vector
		val dx = x - ix.toDouble()
		val dy = y - iy.toDouble()

		// Compute the dot-product
		return (dx*gradient.x + dy*gradient.y)
	}

// Compute Perlin noise at coordinates x, y
	fun perlin(x:Double, y:Double):Double {
		// Determine grid cell coordinates
		val x0 = x.toInt()
		val x1 = x0 + 1
		val y0 = y.toInt()
		val y1 = y0 + 1

		// Determine interpolation weights
		// Could also use higher order polynomial/s-curve here
		val sx = x - x0.toDouble()
		val sy = y - y0.toDouble()

		// Interpolate between grid point gradients
		val n0 = dotGridGradient(x0, y0, x, y)
		val n1 = dotGridGradient(x1, y0, x, y)
		val ix0 = interpolate(n0, n1, sx)

		val n2 = dotGridGradient(x0, y1, x, y)
		val n3 = dotGridGradient(x1, y1, x, y)
		val ix1 = interpolate(n2, n3, sx)

		return interpolate(ix0, ix1, sy)
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy