ref: c61556ec4bbf4bdbebf95cc70e2367a207e8eafb
parent: 307ba8a8d9d7c0088462bc4e947639b4593ce597
author: phil9 <[email protected]>
date: Tue Dec 6 14:27:57 EST 2022
implement math.noise() function the implementation is Ken Perlin's reference implementation
--- a/a.h
+++ b/a.h
@@ -34,6 +34,7 @@
double map(double, double, double, double, double);
double lerp(double, double, double);
double randomgaussian(double, double);
+double noise(double, double, double);
extern int drawing;
extern int looping;
--- a/api.c
+++ b/api.c
@@ -737,7 +737,7 @@
a = luaL_checknumber(L, 1);
b = luaL_checknumber(L, 2);
r = luaL_checknumber(L, 3);
- lua_pushnumber(L, lerp(a, b, r));
+ lua_pushnumber(L, lerp(r, a, b));
return 1;
}
@@ -766,6 +766,17 @@
return 1;
}
+int
+cnoise(lua_State *L)
+{
+ double x, y;
+
+ x = luaL_checknumber(L, 1);
+ y = luaL_optnumber(L, 2, 0.0);
+ lua_pushnumber(L, noise(x, y, 0.0));
+ return 1;
+}
+
void
registerfunc(lua_State *L, const char *name, int(*f)(lua_State*))
{
@@ -831,4 +842,5 @@
registermathfunc(L, "norm", cnorm);
registermathfunc(L, "lerp", clerp);
registermathfunc(L, "randomGaussian", crandomgaussian);
+ registermathfunc(L, "noise", cnoise);
}
--- a/math.c
+++ b/math.c
@@ -1,7 +1,7 @@
#include "a.h"
double
-lerp(double a, double b, double r)
+lerp(double r, double a, double b)
{
if(r < 0.0)
r = 0.0;
@@ -51,3 +51,70 @@
return y1 * sd + mean;
}
+/* Perlin noise function reference implementation by Ken Perlin */
+
+int p[512] = { 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 };
+
+double
+fade(double t)
+{
+ return t * t * t * (t * (t * 6 - 15) + 10);
+}
+
+double
+grad(int hash, double x, double y, double z)
+{
+ int h;
+ double u, v;
+
+ h = hash & 15;
+ u = h<8 ? x : y;
+ v = h<4 ? y : h==12||h==14 ? x : z;
+ return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+}
+
+double
+noise(double x, double y, double z)
+{
+ int X, Y, Z, A, B, AA, AB, BA, BB;
+ double u, v, w;
+
+ X = (int)floor(x) & 255;
+ Y = (int)floor(y) & 255;
+ Z = (int)floor(z) & 255;
+ x -= floor(x);
+ y -= floor(y);
+ z -= floor(z);
+ u = fade(x);
+ v = fade(y);
+ w = fade(z);
+ A = p[X ]+Y;
+ AA = p[A]+Z;
+ AB = p[A+1]+Z;
+ B = p[X+1]+Y;
+ BA = p[B]+Z;
+ BB = p[B+1]+Z;
+
+ return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ),
+ grad(p[BA ], x-1, y , z )),
+ lerp(u, grad(p[AB ], x , y-1, z ),
+ grad(p[BB ], x-1, y-1, z ))),
+ lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ),
+ grad(p[BA+1], x-1, y , z-1 )),
+ lerp(u, grad(p[AB+1], x , y-1, z-1 ),
+ grad(p[BB+1], x-1, y-1, z-1 ))));
+}
--- /dev/null
+++ b/samples/noise.lua
@@ -1,0 +1,21 @@
+#!/bin/slug
+
+function setup()
+ size(400, 400)
+ background(0)
+ loadPixels()
+ for y = 1, 399 do
+ for x = 1, 399 do
+ n = math.noise(x * 0.01, y * 0.01)
+ n = n + 1.0
+ n = n / 2.0
+ v = math.floor(255 * n)
+ pixels[x + width * y] = color(v, v, v)
+ end
+ end
+ updatePixels()
+end
+
+function draw()
+ noLoop()
+end