changeset 889:e5fde730b4fa

Move perlin noise functions to dmperlin.[ch] and make the API re-entrant.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 04 Feb 2015 23:45:21 +0200
parents 85fab9d640ec
children 6a2a286f3d70
files src/dmlib.h src/dmperlin.c
diffstat 2 files changed, 51 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 <math.h>
 
-#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;