labyrinth

annotate src/noise.c @ 0:8ba79034e8a6

labyrinth example initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 15 Jan 2015 14:59:38 +0200
parents
children
rev   line source
nuclear@0 1 #include <stdlib.h>
nuclear@0 2 #include <math.h>
nuclear@0 3 #include "noise.h"
nuclear@0 4
nuclear@0 5 typedef struct vec2 {
nuclear@0 6 float x, y;
nuclear@0 7 } vec2_t;
nuclear@0 8
nuclear@0 9 typedef struct vec3 {
nuclear@0 10 float x, y, z;
nuclear@0 11 } vec3_t;
nuclear@0 12
nuclear@0 13 /* ---- Ken Perlin's implementation of noise ---- */
nuclear@0 14
nuclear@0 15 #define B 0x100
nuclear@0 16 #define BM 0xff
nuclear@0 17 #define N 0x1000
nuclear@0 18 #define NP 12 /* 2^N */
nuclear@0 19 #define NM 0xfff
nuclear@0 20
nuclear@0 21 #define lerp(a, b, t) ((a) + ((b) - (a)) * t)
nuclear@0 22 #define s_curve(t) (t * t * (3.0f - 2.0f * t))
nuclear@0 23
nuclear@0 24 #define setup(elem, b0, b1, r0, r1) \
nuclear@0 25 do { \
nuclear@0 26 float t = elem + N; \
nuclear@0 27 b0 = ((int)t) & BM; \
nuclear@0 28 b1 = (b0 + 1) & BM; \
nuclear@0 29 r0 = t - (int)t; \
nuclear@0 30 r1 = r0 - 1.0f; \
nuclear@0 31 } while(0)
nuclear@0 32
nuclear@0 33
nuclear@0 34 static int perm[B + B + 2]; /* permuted index from g_n onto themselves */
nuclear@0 35 static vec3_t grad3[B + B + 2]; /* 3D random gradients */
nuclear@0 36 static vec2_t grad2[B + B + 2]; /* 2D random gradients */
nuclear@0 37 static float grad1[B + B + 2]; /* 1D random ... slopes */
nuclear@0 38 static int tables_valid;
nuclear@0 39
nuclear@0 40 static vec2_t v2_normalize(vec2_t v)
nuclear@0 41 {
nuclear@0 42 vec2_t res;
nuclear@0 43 float len = sqrt(v.x * v.x + v.y * v.y);
nuclear@0 44 if(len != 0.0f) {
nuclear@0 45 res.x = v.x / len;
nuclear@0 46 res.y = v.y / len;
nuclear@0 47 } else {
nuclear@0 48 res = v;
nuclear@0 49 }
nuclear@0 50 return res;
nuclear@0 51 }
nuclear@0 52
nuclear@0 53 static vec3_t v3_normalize(vec3_t v)
nuclear@0 54 {
nuclear@0 55 vec3_t res;
nuclear@0 56 float len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
nuclear@0 57 if(len != 0.0f) {
nuclear@0 58 res.x = v.x / len;
nuclear@0 59 res.y = v.y / len;
nuclear@0 60 res.z = v.z / len;
nuclear@0 61 } else {
nuclear@0 62 res = v;
nuclear@0 63 }
nuclear@0 64 return res;
nuclear@0 65 }
nuclear@0 66
nuclear@0 67 static void init_noise()
nuclear@0 68 {
nuclear@0 69 int i;
nuclear@0 70
nuclear@0 71 /* calculate random gradients */
nuclear@0 72 for(i=0; i<B; i++) {
nuclear@0 73 perm[i] = i; /* .. and initialize permutation mapping to identity */
nuclear@0 74
nuclear@0 75 grad1[i] = (float)((rand() % (B + B)) - B) / B;
nuclear@0 76
nuclear@0 77 grad2[i].x = (float)((rand() % (B + B)) - B) / B;
nuclear@0 78 grad2[i].y = (float)((rand() % (B + B)) - B) / B;
nuclear@0 79 grad2[i] = v2_normalize(grad2[i]);
nuclear@0 80
nuclear@0 81 grad3[i].x = (float)((rand() % (B + B)) - B) / B;
nuclear@0 82 grad3[i].y = (float)((rand() % (B + B)) - B) / B;
nuclear@0 83 grad3[i].z = (float)((rand() % (B + B)) - B) / B;
nuclear@0 84 grad3[i] = v3_normalize(grad3[i]);
nuclear@0 85 }
nuclear@0 86
nuclear@0 87 /* permute indices by swapping them randomly */
nuclear@0 88 for(i=0; i<B; i++) {
nuclear@0 89 int rand_idx = rand() % B;
nuclear@0 90
nuclear@0 91 int tmp = perm[i];
nuclear@0 92 perm[i] = perm[rand_idx];
nuclear@0 93 perm[rand_idx] = tmp;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 /* fill up the rest of the arrays by duplicating the existing gradients */
nuclear@0 97 /* and permutations */
nuclear@0 98 for(i=0; i<B+2; i++) {
nuclear@0 99 perm[B + i] = perm[i];
nuclear@0 100 grad1[B + i] = grad1[i];
nuclear@0 101 grad2[B + i] = grad2[i];
nuclear@0 102 grad3[B + i] = grad3[i];
nuclear@0 103 }
nuclear@0 104 }
nuclear@0 105
nuclear@0 106
nuclear@0 107 float noise1(float x)
nuclear@0 108 {
nuclear@0 109 int bx0, bx1;
nuclear@0 110 float rx0, rx1, sx, u, v;
nuclear@0 111
nuclear@0 112 if(!tables_valid) {
nuclear@0 113 init_noise();
nuclear@0 114 tables_valid = 1;
nuclear@0 115 }
nuclear@0 116
nuclear@0 117 setup(x, bx0, bx1, rx0, rx1);
nuclear@0 118 sx = s_curve(rx0);
nuclear@0 119 u = rx0 * grad1[perm[bx0]];
nuclear@0 120 v = rx1 * grad1[perm[bx1]];
nuclear@0 121
nuclear@0 122 return lerp(u, v, sx);
nuclear@0 123 }
nuclear@0 124
nuclear@0 125 float fbm1(float x, int octaves)
nuclear@0 126 {
nuclear@0 127 int i;
nuclear@0 128 float res = 0.0f, freq = 1.0f;
nuclear@0 129 for(i=0; i<octaves; i++) {
nuclear@0 130 res += noise1(x * freq) / freq;
nuclear@0 131 freq *= 2.0f;
nuclear@0 132 }
nuclear@0 133 return res;
nuclear@0 134 }
nuclear@0 135
nuclear@0 136 float turbulence1(float x, int octaves)
nuclear@0 137 {
nuclear@0 138 int i;
nuclear@0 139 float res = 0.0f, freq = 1.0f;
nuclear@0 140 for(i=0; i<octaves; i++) {
nuclear@0 141 res += fabs(noise1(x * freq) / freq);
nuclear@0 142 freq *= 2.0f;
nuclear@0 143 }
nuclear@0 144 return res;
nuclear@0 145 }
nuclear@0 146