# HG changeset patch # User Matti Hamalainen # Date 1423086321 -7200 # Node ID e5fde730b4fade978aa7e8100b31a7d5e6739e3c # Parent 85fab9d640ec60b404166ba9b2ba71e41aaf59b0 Move perlin noise functions to dmperlin.[ch] and make the API re-entrant. diff -r 85fab9d640ec -r e5fde730b4fa src/dmlib.h --- a/src/dmlib.h Wed Feb 04 23:44:53 2015 +0200 +++ b/src/dmlib.h Wed Feb 04 23:45:21 2015 +0200 @@ -271,12 +271,6 @@ } -/* Perlin noise - */ -void dmPerlinInit(void); -DMFloat dmPerlinNoise2D(DMFloat x, DMFloat y, DMFloat alpha, DMFloat beta, int n); - - /* Arbitrary line drawing */ #ifdef DM_GFX_LINES diff -r 85fab9d640ec -r e5fde730b4fa src/dmperlin.c --- a/src/dmperlin.c Wed Feb 04 23:44:53 2015 +0200 +++ b/src/dmperlin.c Wed Feb 04 23:45:21 2015 +0200 @@ -1,63 +1,57 @@ /* - * Coherent noise function over 1 or 2 dimensions. + * DMLib + * -- Perlin noise functionality + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) */ -#include "dmlib.h" +#include "dmperlin.h" #include -#define B (0x100) -#define BM (0x0ff) -#define NP (12) -#define N (0x1000) -#define NM (0x0fff) - #define DM_PERLIN_SETUP(i, b0, b1, r0, r1) \ { \ - t = (vec[i] + N); \ - b0 = (((int) t) & BM); \ - b1 = ((b0 + 1) & BM); \ + t = (vec[i] + DM_PLNS_N); \ + b0 = (((int) t) & DM_PLNS_BM); \ + b1 = ((b0 + 1) & DM_PLNS_BM); \ r0 = (t - ((int) t)); \ r1 = (r0 - 1.0f); \ } - #define DM_PERLIN_AT2(rx,ry) ((rx) * q[0] + (ry) * q[1]) -static int p[B + B + 2]; -static DMFloat g2[B + B + 2][2]; -static DMFloat g1[B + B + 2]; - - -static DMFloat dmPerlinDoNoise2(DMFloat vec[2]) +static DMFloat dmPerlinDoNoise2(const DMPerlinContext *ctx, const DMFloat vec[2]) { int bx0, bx1, by0, by1, b00, b10, b01, b11; - DMFloat rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; + DMFloat rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v; + const DMFloat *q; int i, j; DM_PERLIN_SETUP(0, bx0, bx1, rx0, rx1); DM_PERLIN_SETUP(1, by0, by1, ry0, ry1); - i = p[bx0]; - j = p[bx1]; + i = ctx->p[bx0]; + j = ctx->p[bx1]; - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; + b00 = ctx->p[i + by0]; + b10 = ctx->p[j + by0]; + b01 = ctx->p[i + by1]; + b11 = ctx->p[j + by1]; sx = DMM_S_CURVE(rx0); sy = DMM_S_CURVE(ry0); - q = g2[b00]; + q = ctx->g2[b00]; u = DM_PERLIN_AT2(rx0, ry0); - q = g2[b10]; + + q = ctx->g2[b10]; v = DM_PERLIN_AT2(rx1, ry0); a = DMM_LERP(sx, u, v); - q = g2[b01]; + q = ctx->g2[b01]; u = DM_PERLIN_AT2(rx0, ry1); - q = g2[b11]; + + q = ctx->g2[b11]; v = DM_PERLIN_AT2(rx1, ry1); b = DMM_LERP(sx, u, v); @@ -73,38 +67,48 @@ } -void dmPerlinInit(void) +int dmPerlinInit(DMPerlinContext *ctx, const int seed) { - int i, j, k; + int i, j; + + if (ctx == NULL) + return DMERR_NULLPTR; + + memset(ctx, 0, sizeof(*ctx)); - srand(32); - - for (i = 0; i < B; i++) + if (seed < 0) + return DMERR_INVALID_ARGS; + + srand(seed); + + for (i = 0; i < DM_PLNS_B; i++) { - p[i] = i; - g1[i] = (DMFloat) ((rand() % (B + B)) - B) / B; + ctx->p[i] = i; + ctx->g1[i] = (DMFloat) ((rand() % (DM_PLNS_B + DM_PLNS_B)) - DM_PLNS_B) / DM_PLNS_B; for (j = 0; j < 2; j++) - g2[i][j] = (DMFloat) ((rand() % (B + B)) - B) / B; + ctx->g2[i][j] = (DMFloat) ((rand() % (DM_PLNS_B + DM_PLNS_B)) - DM_PLNS_B) / DM_PLNS_B; - dmPerlinNormalize2(g2[i]); + dmPerlinNormalize2(ctx->g2[i]); } while (--i) { - k = p[i]; - p[i] = p[j = rand() % B]; - p[j] = k; + int k = ctx->p[i]; + ctx->p[i] = ctx->p[j = rand() % DM_PLNS_B]; + ctx->p[j] = k; } - for (i = 0; i < B + 2; i++) + for (i = 0; i < DM_PLNS_B + 2; i++) { - p[B + i] = p[i]; - g1[B + i] = g1[i]; + ctx->p[DM_PLNS_B + i] = ctx->p[i]; + ctx->g1[DM_PLNS_B + i] = ctx->g1[i]; for (j = 0; j < 2; j++) - g2[B + i][j] = g2[i][j]; + ctx->g2[DM_PLNS_B + i][j] = ctx->g2[i][j]; } + + return DMERR_OK; } @@ -113,7 +117,7 @@ * Typically it is 2, As this approaches 1 the function is noisier. * "beta" is the harmonic scaling/spacing, typically 2. */ -DMFloat dmPerlinNoise2D(DMFloat x, DMFloat y, DMFloat alpha, DMFloat beta, int n) +DMFloat dmPerlinNoise2D(const DMPerlinContext *ctx, DMFloat x, DMFloat y, DMFloat alpha, DMFloat beta, int n) { int i; DMFloat val, sum = 0; @@ -123,7 +127,7 @@ p[1] = y; for (i = 0; i < n; i++) { - val = dmPerlinDoNoise2(p); + val = dmPerlinDoNoise2(ctx, p); sum += val / scale; scale *= alpha; p[0] *= beta;