istereo
diff libs/vmath/vmath.c @ 28:c0ae8e668447
added vmath library
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 08 Sep 2011 08:30:42 +0300 |
parents | |
children | ff055bff6a15 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/vmath/vmath.c Thu Sep 08 08:30:42 2011 +0300 1.3 @@ -0,0 +1,317 @@ 1.4 +#include <stdlib.h> 1.5 +#include <math.h> 1.6 +#include "vmath.h" 1.7 + 1.8 +/** Numerical calculation of integrals using simpson's rule */ 1.9 +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples) 1.10 +{ 1.11 + int i; 1.12 + scalar_t h = (high - low) / (scalar_t)samples; 1.13 + scalar_t sum = 0.0; 1.14 + 1.15 + for(i=0; i<samples+1; i++) { 1.16 + scalar_t y = f((scalar_t)i * h + low); 1.17 + sum += ((!i || i == samples) ? y : ((i % 2) ? 4.0 * y : 2.0 * y)) * (h / 3.0); 1.18 + } 1.19 + return sum; 1.20 +} 1.21 + 1.22 +/** Gaussuan function */ 1.23 +scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev) 1.24 +{ 1.25 + scalar_t exponent = -SQ(x - mean) / (2.0 * SQ(sdev)); 1.26 + return 1.0 - -pow(M_E, exponent) / (sdev * sqrt(TWO_PI)); 1.27 +} 1.28 + 1.29 + 1.30 +/** b-spline approximation */ 1.31 +scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) 1.32 +{ 1.33 + vec4_t tmp; 1.34 + scalar_t tsq = t * t; 1.35 + 1.36 + static mat4_t bspline_mat = { 1.37 + {-1, 3, -3, 1}, 1.38 + {3, -6, 3, 0}, 1.39 + {-3, 0, 3, 0}, 1.40 + {1, 4, 1, 0} 1.41 + }; 1.42 + 1.43 + tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), bspline_mat), 1.0 / 6.0); 1.44 + return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp); 1.45 +} 1.46 + 1.47 +/** Catmull-rom spline interpolation */ 1.48 +scalar_t spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) { 1.49 + vec4_t tmp; 1.50 + scalar_t tsq = t * t; 1.51 + 1.52 + static mat4_t crspline_mat = { 1.53 + {-1, 3, -3, 1}, 1.54 + {2, -5, 4, -1}, 1.55 + {-1, 0, 1, 0}, 1.56 + {0, 2, 0, 0} 1.57 + }; 1.58 + 1.59 + tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), crspline_mat), 0.5); 1.60 + return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp); 1.61 +} 1.62 + 1.63 +/** Bezier interpolation */ 1.64 +scalar_t bezier(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) 1.65 +{ 1.66 + scalar_t omt, omt3, t3, f; 1.67 + t3 = t * t * t; 1.68 + omt = 1.0f - t; 1.69 + omt3 = omt * omt * omt; 1.70 + f = 3 * t * omt; 1.71 + 1.72 + return (a * omt3) + (b * f * omt) + (c * f * t) + (d * t3); 1.73 +} 1.74 + 1.75 +/* ---- Ken Perlin's implementation of noise ---- */ 1.76 + 1.77 +#define B 0x100 1.78 +#define BM 0xff 1.79 +#define N 0x1000 1.80 +#define NP 12 /* 2^N */ 1.81 +#define NM 0xfff 1.82 + 1.83 +#define s_curve(t) (t * t * (3.0f - 2.0f * t)) 1.84 + 1.85 +#define setup(elem, b0, b1, r0, r1) \ 1.86 + do { \ 1.87 + scalar_t t = elem + N; \ 1.88 + b0 = ((int)t) & BM; \ 1.89 + b1 = (b0 + 1) & BM; \ 1.90 + r0 = t - (int)t; \ 1.91 + r1 = r0 - 1.0f; \ 1.92 + } while(0) 1.93 + 1.94 + 1.95 +static int perm[B + B + 2]; /* permuted index from g_n onto themselves */ 1.96 +static vec3_t grad3[B + B + 2]; /* 3D random gradients */ 1.97 +static vec2_t grad2[B + B + 2]; /* 2D random gradients */ 1.98 +static scalar_t grad1[B + B + 2]; /* 1D random ... slopes */ 1.99 +static int tables_valid; 1.100 + 1.101 +static void init_noise() 1.102 +{ 1.103 + int i; 1.104 + 1.105 + /* calculate random gradients */ 1.106 + for(i=0; i<B; i++) { 1.107 + perm[i] = i; /* .. and initialize permutation mapping to identity */ 1.108 + 1.109 + grad1[i] = (scalar_t)((rand() % (B + B)) - B) / B; 1.110 + 1.111 + grad2[i].x = (scalar_t)((rand() % (B + B)) - B) / B; 1.112 + grad2[i].y = (scalar_t)((rand() % (B + B)) - B) / B; 1.113 + grad2[i] = v2_normalize(grad2[i]); 1.114 + 1.115 + grad3[i].x = (scalar_t)((rand() % (B + B)) - B) / B; 1.116 + grad3[i].y = (scalar_t)((rand() % (B + B)) - B) / B; 1.117 + grad3[i].z = (scalar_t)((rand() % (B + B)) - B) / B; 1.118 + grad3[i] = v3_normalize(grad3[i]); 1.119 + } 1.120 + 1.121 + /* permute indices by swapping them randomly */ 1.122 + for(i=0; i<B; i++) { 1.123 + int rand_idx = rand() % B; 1.124 + 1.125 + int tmp = perm[i]; 1.126 + perm[i] = perm[rand_idx]; 1.127 + perm[rand_idx] = tmp; 1.128 + } 1.129 + 1.130 + /* fill up the rest of the arrays by duplicating the existing gradients */ 1.131 + /* and permutations */ 1.132 + for(i=0; i<B+2; i++) { 1.133 + perm[B + i] = perm[i]; 1.134 + grad1[B + i] = grad1[i]; 1.135 + grad2[B + i] = grad2[i]; 1.136 + grad3[B + i] = grad3[i]; 1.137 + } 1.138 +} 1.139 + 1.140 +scalar_t noise1(scalar_t x) 1.141 +{ 1.142 + int bx0, bx1; 1.143 + scalar_t rx0, rx1, sx, u, v; 1.144 + 1.145 + if(!tables_valid) { 1.146 + init_noise(); 1.147 + tables_valid = 1; 1.148 + } 1.149 + 1.150 + setup(x, bx0, bx1, rx0, rx1); 1.151 + sx = s_curve(rx0); 1.152 + u = rx0 * grad1[perm[bx0]]; 1.153 + v = rx1 * grad1[perm[bx1]]; 1.154 + 1.155 + return lerp(u, v, sx); 1.156 +} 1.157 + 1.158 +scalar_t noise2(scalar_t x, scalar_t y) 1.159 +{ 1.160 + int i, j, b00, b10, b01, b11; 1.161 + int bx0, bx1, by0, by1; 1.162 + scalar_t rx0, rx1, ry0, ry1; 1.163 + scalar_t sx, sy, u, v, a, b; 1.164 + 1.165 + if(!tables_valid) { 1.166 + init_noise(); 1.167 + tables_valid = 1; 1.168 + } 1.169 + 1.170 + setup(x, bx0, bx1, rx0, rx1); 1.171 + setup(y, by0, by1, ry0, ry1); 1.172 + 1.173 + i = perm[bx0]; 1.174 + j = perm[bx1]; 1.175 + 1.176 + b00 = perm[i + by0]; 1.177 + b10 = perm[j + by0]; 1.178 + b01 = perm[i + by1]; 1.179 + b11 = perm[j + by1]; 1.180 + 1.181 + /* calculate hermite inteprolating factors */ 1.182 + sx = s_curve(rx0); 1.183 + sy = s_curve(ry0); 1.184 + 1.185 + /* interpolate along the left edge */ 1.186 + u = v2_dot(grad2[b00], v2_cons(rx0, ry0)); 1.187 + v = v2_dot(grad2[b10], v2_cons(rx1, ry0)); 1.188 + a = lerp(u, v, sx); 1.189 + 1.190 + /* interpolate along the right edge */ 1.191 + u = v2_dot(grad2[b01], v2_cons(rx0, ry1)); 1.192 + v = v2_dot(grad2[b11], v2_cons(rx1, ry1)); 1.193 + b = lerp(u, v, sx); 1.194 + 1.195 + /* interpolate between them */ 1.196 + return lerp(a, b, sy); 1.197 +} 1.198 + 1.199 +scalar_t noise3(scalar_t x, scalar_t y, scalar_t z) 1.200 +{ 1.201 + int i, j; 1.202 + int bx0, bx1, by0, by1, bz0, bz1; 1.203 + int b00, b10, b01, b11; 1.204 + scalar_t rx0, rx1, ry0, ry1, rz0, rz1; 1.205 + scalar_t sx, sy, sz; 1.206 + scalar_t u, v, a, b, c, d; 1.207 + 1.208 + if(!tables_valid) { 1.209 + init_noise(); 1.210 + tables_valid = 1; 1.211 + } 1.212 + 1.213 + setup(x, bx0, bx1, rx0, rx1); 1.214 + setup(y, by0, by1, ry0, ry1); 1.215 + setup(z, bz0, bz1, rz0, rz1); 1.216 + 1.217 + i = perm[bx0]; 1.218 + j = perm[bx1]; 1.219 + 1.220 + b00 = perm[i + by0]; 1.221 + b10 = perm[j + by0]; 1.222 + b01 = perm[i + by1]; 1.223 + b11 = perm[j + by1]; 1.224 + 1.225 + /* calculate hermite interpolating factors */ 1.226 + sx = s_curve(rx0); 1.227 + sy = s_curve(ry0); 1.228 + sz = s_curve(rz0); 1.229 + 1.230 + /* interpolate along the top slice of the cell */ 1.231 + u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz0)); 1.232 + v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz0)); 1.233 + a = lerp(u, v, sx); 1.234 + 1.235 + u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz0)); 1.236 + v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz0)); 1.237 + b = lerp(u, v, sx); 1.238 + 1.239 + c = lerp(a, b, sy); 1.240 + 1.241 + /* interpolate along the bottom slice of the cell */ 1.242 + u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz1)); 1.243 + v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz1)); 1.244 + a = lerp(u, v, sx); 1.245 + 1.246 + u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz1)); 1.247 + v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz1)); 1.248 + b = lerp(u, v, sx); 1.249 + 1.250 + d = lerp(a, b, sy); 1.251 + 1.252 + /* interpolate between slices */ 1.253 + return lerp(c, d, sz); 1.254 +} 1.255 + 1.256 +scalar_t fbm1(scalar_t x, int octaves) 1.257 +{ 1.258 + int i; 1.259 + scalar_t res = 0.0f, freq = 1.0f; 1.260 + for(i=0; i<octaves; i++) { 1.261 + res += noise1(x * freq) / freq; 1.262 + freq *= 2.0f; 1.263 + } 1.264 + return res; 1.265 +} 1.266 + 1.267 +scalar_t fbm2(scalar_t x, scalar_t y, int octaves) 1.268 +{ 1.269 + int i; 1.270 + scalar_t res = 0.0f, freq = 1.0f; 1.271 + for(i=0; i<octaves; i++) { 1.272 + res += noise2(x * freq, y * freq) / freq; 1.273 + freq *= 2.0f; 1.274 + } 1.275 + return res; 1.276 +} 1.277 + 1.278 +scalar_t fbm3(scalar_t x, scalar_t y, scalar_t z, int octaves) 1.279 +{ 1.280 + int i; 1.281 + scalar_t res = 0.0f, freq = 1.0f; 1.282 + for(i=0; i<octaves; i++) { 1.283 + res += noise3(x * freq, y * freq, z * freq) / freq; 1.284 + freq *= 2.0f; 1.285 + } 1.286 + return res; 1.287 +} 1.288 + 1.289 +scalar_t turbulence1(scalar_t x, int octaves) 1.290 +{ 1.291 + int i; 1.292 + scalar_t res = 0.0f, freq = 1.0f; 1.293 + for(i=0; i<octaves; i++) { 1.294 + res += fabs(noise1(x * freq) / freq); 1.295 + freq *= 2.0f; 1.296 + } 1.297 + return res; 1.298 +} 1.299 + 1.300 +scalar_t turbulence2(scalar_t x, scalar_t y, int octaves) 1.301 +{ 1.302 + int i; 1.303 + scalar_t res = 0.0f, freq = 1.0f; 1.304 + for(i=0; i<octaves; i++) { 1.305 + res += fabs(noise2(x * freq, y * freq) / freq); 1.306 + freq *= 2.0f; 1.307 + } 1.308 + return res; 1.309 +} 1.310 + 1.311 +scalar_t turbulence3(scalar_t x, scalar_t y, scalar_t z, int octaves) 1.312 +{ 1.313 + int i; 1.314 + scalar_t res = 0.0f, freq = 1.0f; 1.315 + for(i=0; i<octaves; i++) { 1.316 + res += fabs(noise3(x * freq, y * freq, z * freq) / freq); 1.317 + freq *= 2.0f; 1.318 + } 1.319 + return res; 1.320 +}