/* Noise Wurst v1.2.1 Source: https://github.com/eGlint/wurstNoiselib Contributors: https://github.com/eGlint/wurstNoiselib/contributors Perlin Noise by Kenneth Perlin, https://mrl.nyu.edu/~perlin/noise/ Open Simplex by Kurt Spencer, https://gist.github.com/KdotJPG/b1270127455a94ac5d19 */ package Noise import NoWurst import NoiseRandom import Integer import Vectors import Wurstunit import Interpolation // import Printing // Uncomment if running visualTest() /** 1D Gradient */ function grad(int hash, real x) returns real let h = hash.bitAnd(15) return h.bitAnd(1) == 0 ? x : -x /** 2D Gradient */ function grad(int hash, vec2 vec) returns real let h = hash.bitAnd(15) let u = h < 8 ? vec.x : vec.y let v = h < 4 ? vec.y : vec.x return (h.bitAnd(1) == 0 ? u: -u) + (h.bitAnd(2) == 0 ? v : -v) /** 3D Gradient */ function grad(int hash, vec3 vec) returns real let h = hash.bitAnd(15) let u = h < 8 ? vec.x : vec.y let v = h < 4 ? vec.y : (h == 12 or h == 14 ? vec.x : vec.z) return (h.bitAnd(1) == 0 ? u : -u) + (h.bitAnd(2) == 0 ? v : -v) /** Fade */ function real.fade () returns real return this * this * this * (this * (this * 6. - 15.) + 10.) // 2D Open Simplex Constants constant var STRETCH_CONSTANT_2D = -0.21132486 //5405187 <- additional values when double constant var SQUISH_CONSTANT_2D = 0.36602540 //3784439 <- additional values when double constant var NORM_CONSTANT_2D = 47 constant var PMASK = 255 constant var gradT2D = [ vec2( 5, 2), vec2( 2, 5), vec2(-2, 5), vec2(-5, 2), vec2(-5, -2), vec2(-2, -5), vec2( 2, -5), vec2( 5, -2) ] constant vec2 SQUISH_CONSTANT_2D_VEC = vec2(2 * SQUISH_CONSTANT_2D, 2 * SQUISH_CONSTANT_2D) /** 2D Extrapolate */ function extrapolate(vec2 vecsb, vec2 dvec) returns real let index = Noise.p[Noise.p[vecsb.x.toInt().bitAnd(PMASK)].bitXor(vecsb.y.toInt().bitAnd(PMASK))].bitAnd(7) return gradT2D[index].x * dvec.x + gradT2D[index].y * dvec.y /** Noise A static class that contains noise functions. */ public class Noise /** The current version of the Noise Library. */ constant string getVersion = "1.2.1" /** Permutation */ static int array p /** 1D Perlin Noise Sample Usage: Noise.perlin((x + offsetx) * scale) * amplitude */ static function perlin (real x) returns real var lx = x let X = lx.floor().bitAnd(255) lx -= lx.floor() return linear(grad(p[X], lx), grad(p[X + 1], lx - 1), lx.fade()) * 2 /** 2D Perlin Noise Sample Usage: Noise.perlin(vec2((x + offsetx) * scale, (y + offsety) * scale)) * amplitude */ static function perlin (vec2 vec) returns real var lvec = vec let X = lvec.x.floor().bitAnd(255) let Y = lvec.y.floor().bitAnd(255) lvec = vec2(lvec.x - lvec.x.floor(), lvec.y - lvec.y.floor()) let u = lvec.x.fade() let v = lvec.y.fade() let A = p[X] + Y let B = p[X + 1] + Y return linear(linear(grad(p[A], lvec), grad(p[B], lvec - vec2(1, 0)), u), linear(grad(p[A + 1], lvec - vec2(0, 1)), grad(p[B + 1], lvec - vec2(1, 1)), u), v) /** 3D Perlin Noise Sample Usage: Noise.perlin(vec3((x + offsetx) * scale, (y + offsety) * scale, (z + offsetz) * scale)) * amplitude */ static function perlin (vec3 vec) returns real var lvec = vec let X = vec.x.floor().bitAnd(255) let Y = vec.y.floor().bitAnd(255) let Z = vec.z.floor().bitAnd(255) lvec = vec3(lvec.x - lvec.x.floor(), lvec.y - lvec.y.floor(), lvec.z - lvec.z.floor()) let u = lvec.x.fade() let v = lvec.y.fade() let w = lvec.z.fade() let A = p[X] + Y let AA = p[A] + Z let AB = p[A + 1] + Z let B = p[X + 1] + Y let BA = p[B] + Z let BB = p[B + 1] + Z return linear(linear(linear(grad(p[AA], lvec), grad(p[BA], lvec - vec3(1, 0, 0)), u), linear(grad(p[AB], lvec - vec3(0, 1, 0)), grad(p[BB], lvec - vec3(1, 1, 0)), u), v), linear(linear(grad(p[AA + 1], lvec - vec3(0, 0, 1)), grad(p[BA + 1], lvec - vec3(1, 0, 1)), u), linear(grad(p[AB + 1], lvec - vec3(0, 1, 1)), grad(p[BB + 1], lvec - vec3(1, 1, 1)), u), v), w) /** 2D Open Simplex Noise Sample Usage: Noise.openSimplex(vec2((x + offsetx) * scale, (y + offsety) * scale)) * amplitude */ static function openSimplex(vec2 vec) returns real let stretchOffset = (vec.x + vec.y) * STRETCH_CONSTANT_2D let vecs = vec2(vec.x + stretchOffset, vec.y + stretchOffset) var vecsb = vec2(vecs.x.floor().toReal(), vecs.y.floor().toReal()) let squishOffset = (vecsb.x + vecsb.y) * SQUISH_CONSTANT_2D let vecb = vec2(vecsb.x + squishOffset, vecsb.y + squishOffset) let vecins = vecs - vecsb let inSum = vecins.x + vecins.y var dvec0 = vec - vecb vec2 dvec_ext vec2 vecsv_ext var value = 0. let dvec1 = vec2(dvec0.x - 1. - SQUISH_CONSTANT_2D, dvec0.y - 0. - SQUISH_CONSTANT_2D) var attn1 = 2 - dvec1.x * dvec1.x - dvec1.y * dvec1.y if attn1 > 0. attn1 *= attn1 value += attn1 * attn1 * extrapolate(vecsb + vec2(1,0), dvec1) let dvec2 = vec2(dvec0.x - 0. - SQUISH_CONSTANT_2D, dvec0.y - 1. - SQUISH_CONSTANT_2D) var attn2 = 2 - dvec2.x * dvec2.x - dvec2.y * dvec2.y if attn2 > 0. attn2 *= attn2 value += attn2 * attn2 * extrapolate(vecsb + vec2(0,1), dvec2) real zins if inSum <= 1 zins = 1 - inSum if zins > vecins.x or zins > vecins.y if vecins.x > vecins.y vecsv_ext = vecsb + vec2(1, -1) dvec_ext = dvec0 + vec2(-1, 1) else vecsv_ext = vecsb + vec2(-1, 1) dvec_ext = dvec0 + vec2(1, -1) else vecsv_ext = vecsb + vec2(1, 1) dvec_ext = dvec0 + vec2(-1, -1) - SQUISH_CONSTANT_2D_VEC else zins = 2 - inSum if zins < vecins.x or zins < vecins.y if vecins.x > vecins.y vecsv_ext = vecsb + vec2(2, 0) dvec_ext = dvec0 + vec2(-2, 0) - SQUISH_CONSTANT_2D_VEC else vecsv_ext = vecsb + vec2(0, 2) dvec_ext = dvec0 + vec2(0, -2) - SQUISH_CONSTANT_2D_VEC else vecsv_ext = vecsb dvec_ext = dvec0 vecsb += vec2(1, 1) dvec0 = dvec0 - vec2(1, 1) - SQUISH_CONSTANT_2D_VEC var attn0 = 2 - dvec0.x * dvec0.x - dvec0.y * dvec0.y if attn0 > 0 attn0 *= attn0 value += attn0 * attn0 * extrapolate(vecsb, dvec0) var attn_ext = 2 - dvec_ext.x * dvec_ext.x - dvec_ext.y * dvec_ext.y if attn_ext > 0 attn_ext *= attn_ext value += attn_ext * attn_ext * extrapolate(vecsv_ext, dvec_ext) return value / NORM_CONSTANT_2D /** Generate Random Permutation Generates random values in the permutation table Sample Usage: let myCustomPrng = new MyCustomPRNG("Seed") generateRandomPermutation (low, high) -> return myCustomPrng.getRandomInt(low, high) */ static function generateRandomPermutation(NoiseRandom random) for i = 0 to 255 p[i] = random.getRandomInt(0, 255) p[i + 256] = p [i] /** Generate Random Permutation Generates random values in the permutation table. Uses Warcraft III's GetRandomInt to generate numbers. */ static function generateRandomPermutation() for i = 0 to 255 p[i] = GetRandomInt(0, 255) p[i + 256] = p [i] static function initialize() generateRandomPermutation() init Noise.initialize() @Test function testNoise() let testp = [151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180] for i = 0 to 255 Noise.p[i] = testp[i] Noise.p[i + 256] = testp[i] // 1D Perlin Noise assertTrue(Noise.perlin(0.1) == -0.213696) assertTrue(Noise.perlin(0.24) == -0.5769812) assertTrue(Noise.perlin(-0.86) == 0.31168038) assertTrue(Noise.perlin(1) == 0) // 2D Perlin Noise assertTrue(Noise.perlin(vec2(0.1, 0.1)) == 0.015144216) assertTrue(Noise.perlin(vec2(0.24, -0.71)) == -0.06949358) assertTrue(Noise.perlin(vec2(-0.86, -0.57)) == -0.0025302172) assertTrue(Noise.perlin(vec2(1, 1)) == 0) // 3D Perlin Noise assertTrue(Noise.perlin(vec3(0.1, 0.1, 0.1)) == 0.18616073) assertTrue(Noise.perlin(vec3(0.24, -0.71, 0.58)) == 0.087833166) assertTrue(Noise.perlin(vec3(-0.86, -0.57, -0.13)) == -0.6246815) assertTrue(Noise.perlin(vec3(1, 1, 1)) == 0) // 2D Open Simplex assertTrue(Noise.openSimplex(vec2(0.1, 0.1)) == 0.22610725) assertTrue(Noise.openSimplex(vec2(0.24, -0.71)) == -0.28248793) assertTrue(Noise.openSimplex(vec2(-0.86, -0.57)) == -0.49843946) assertTrue(Noise.openSimplex(vec2(1, 1)) == -0.6867029) // @Test // function visualTest() // Noise.generateRandomPermutation() // // 2D Perlin // print("\n\n Perlin") // let width = 55 // let height = 90 // let scale = 10 // for x = 0 to width - 1 // var sval = "" // for y = 0 to height - 1 // let nx = x / width // let ny = y / height // let val = (Noise.perlin(vec2(nx * scale, ny * scale))) // if val > -0.4 // if val > -0.2 // if val > 0.2 // if val > 0.6 // sval += "." // else // sval += "_" // else // sval += "-" // else // sval += "=" // else // sval += "T" // print(sval) // // 2D Open Simplex // print("\n\n Open Simplex") // for x = 0 to width - 1 // var sval = "" // for y = 0 to height - 1 // let nx = x / width - 0.5 // let ny = y / height - 0.5 // let val = (Noise.openSimplex(vec2(nx * scale, ny * scale))) // if val > -0.4 // if val > -0.2 // if val > 0.2 // if val > 0.6 // sval += "." // else // sval += "_" // else // sval += "-" // else // sval += "=" // else // sval += "T" // print(sval)