3dphotoshoot
diff libs/vmath/vmath.c @ 10:c71c477521ca
converting to GLES2 and C++
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 31 May 2015 00:40:26 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/vmath/vmath.c Sun May 31 00:40:26 2015 +0300 1.3 @@ -0,0 +1,396 @@ 1.4 +/* 1.5 +libvmath - a vector math library 1.6 +Copyright (C) 2004-2015 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU Lesser General Public License as published 1.10 +by the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU Lesser General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU Lesser General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#include <stdlib.h> 1.22 +#include <math.h> 1.23 +#include "vmath.h" 1.24 + 1.25 +#if defined(__APPLE__) && !defined(TARGET_IPHONE) 1.26 +#include <xmmintrin.h> 1.27 + 1.28 +void enable_fpexcept(void) 1.29 +{ 1.30 + unsigned int bits; 1.31 + bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW; 1.32 + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~bits); 1.33 +} 1.34 + 1.35 +void disable_fpexcept(void) 1.36 +{ 1.37 + unsigned int bits; 1.38 + bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW; 1.39 + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | bits); 1.40 +} 1.41 + 1.42 +#elif defined(__GNUC__) && !defined(TARGET_IPHONE) && !defined(__MINGW32__) 1.43 +#define __USE_GNU 1.44 +#include <fenv.h> 1.45 + 1.46 +void enable_fpexcept(void) 1.47 +{ 1.48 + feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); 1.49 +} 1.50 + 1.51 +void disable_fpexcept(void) 1.52 +{ 1.53 + fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); 1.54 +} 1.55 + 1.56 +#elif defined(_MSC_VER) || defined(__MINGW32__) 1.57 +#include <float.h> 1.58 + 1.59 +#if defined(__MINGW32__) && !defined(_EM_OVERFLOW) 1.60 +/* if gcc's float.h gets precedence, the mingw MSVC includes won't be declared */ 1.61 +#define _MCW_EM 0x8001f 1.62 +#define _EM_INVALID 0x10 1.63 +#define _EM_ZERODIVIDE 0x08 1.64 +#define _EM_OVERFLOW 0x04 1.65 +unsigned int __cdecl _clearfp(void); 1.66 +unsigned int __cdecl _controlfp(unsigned int, unsigned int); 1.67 +#endif 1.68 + 1.69 +void enable_fpexcept(void) 1.70 +{ 1.71 + _clearfp(); 1.72 + _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM); 1.73 +} 1.74 + 1.75 +void disable_fpexcept(void) 1.76 +{ 1.77 + _clearfp(); 1.78 + _controlfp(_controlfp(0, 0) | (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM); 1.79 +} 1.80 +#else 1.81 +void enable_fpexcept(void) {} 1.82 +void disable_fpexcept(void) {} 1.83 +#endif 1.84 + 1.85 + 1.86 +/** Numerical calculation of integrals using simpson's rule */ 1.87 +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples) 1.88 +{ 1.89 + int i; 1.90 + scalar_t h = (high - low) / (scalar_t)samples; 1.91 + scalar_t sum = 0.0; 1.92 + 1.93 + for(i=0; i<samples+1; i++) { 1.94 + scalar_t y = f((scalar_t)i * h + low); 1.95 + sum += ((!i || i == samples) ? y : ((i % 2) ? 4.0 * y : 2.0 * y)) * (h / 3.0); 1.96 + } 1.97 + return sum; 1.98 +} 1.99 + 1.100 +/** Gaussuan function */ 1.101 +scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev) 1.102 +{ 1.103 + scalar_t exponent = -SQ(x - mean) / (2.0 * SQ(sdev)); 1.104 + return 1.0 - -pow(M_E, exponent) / (sdev * sqrt(TWO_PI)); 1.105 +} 1.106 + 1.107 + 1.108 +/** b-spline approximation */ 1.109 +scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) 1.110 +{ 1.111 + vec4_t tmp; 1.112 + scalar_t tsq = t * t; 1.113 + 1.114 + static mat4_t bspline_mat = { 1.115 + {-1, 3, -3, 1}, 1.116 + {3, -6, 3, 0}, 1.117 + {-3, 0, 3, 0}, 1.118 + {1, 4, 1, 0} 1.119 + }; 1.120 + 1.121 + tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), bspline_mat), 1.0 / 6.0); 1.122 + return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp); 1.123 +} 1.124 + 1.125 +/** Catmull-rom spline interpolation */ 1.126 +scalar_t spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) 1.127 +{ 1.128 + vec4_t tmp; 1.129 + scalar_t tsq = t * t; 1.130 + 1.131 + static mat4_t crspline_mat = { 1.132 + {-1, 3, -3, 1}, 1.133 + {2, -5, 4, -1}, 1.134 + {-1, 0, 1, 0}, 1.135 + {0, 2, 0, 0} 1.136 + }; 1.137 + 1.138 + tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), crspline_mat), 0.5); 1.139 + return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp); 1.140 +} 1.141 + 1.142 +/** Bezier interpolation */ 1.143 +scalar_t bezier(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t) 1.144 +{ 1.145 + scalar_t omt, omt3, t3, f; 1.146 + t3 = t * t * t; 1.147 + omt = 1.0f - t; 1.148 + omt3 = omt * omt * omt; 1.149 + f = 3 * t * omt; 1.150 + 1.151 + return (a * omt3) + (b * f * omt) + (c * f * t) + (d * t3); 1.152 +} 1.153 + 1.154 +/* ---- Ken Perlin's implementation of noise ---- */ 1.155 + 1.156 +#define B 0x100 1.157 +#define BM 0xff 1.158 +#define N 0x1000 1.159 +#define NP 12 /* 2^N */ 1.160 +#define NM 0xfff 1.161 + 1.162 +#define s_curve(t) (t * t * (3.0f - 2.0f * t)) 1.163 + 1.164 +#define setup(elem, b0, b1, r0, r1) \ 1.165 + do { \ 1.166 + scalar_t t = elem + N; \ 1.167 + b0 = ((int)t) & BM; \ 1.168 + b1 = (b0 + 1) & BM; \ 1.169 + r0 = t - (int)t; \ 1.170 + r1 = r0 - 1.0f; \ 1.171 + } while(0) 1.172 + 1.173 + 1.174 +static int perm[B + B + 2]; /* permuted index from g_n onto themselves */ 1.175 +static vec3_t grad3[B + B + 2]; /* 3D random gradients */ 1.176 +static vec2_t grad2[B + B + 2]; /* 2D random gradients */ 1.177 +static scalar_t grad1[B + B + 2]; /* 1D random ... slopes */ 1.178 +static int tables_valid; 1.179 + 1.180 +static void init_noise() 1.181 +{ 1.182 + int i; 1.183 + 1.184 + /* calculate random gradients */ 1.185 + for(i=0; i<B; i++) { 1.186 + perm[i] = i; /* .. and initialize permutation mapping to identity */ 1.187 + 1.188 + grad1[i] = (scalar_t)((rand() % (B + B)) - B) / B; 1.189 + 1.190 + grad2[i].x = (scalar_t)((rand() % (B + B)) - B) / B; 1.191 + grad2[i].y = (scalar_t)((rand() % (B + B)) - B) / B; 1.192 + grad2[i] = v2_normalize(grad2[i]); 1.193 + 1.194 + grad3[i].x = (scalar_t)((rand() % (B + B)) - B) / B; 1.195 + grad3[i].y = (scalar_t)((rand() % (B + B)) - B) / B; 1.196 + grad3[i].z = (scalar_t)((rand() % (B + B)) - B) / B; 1.197 + grad3[i] = v3_normalize(grad3[i]); 1.198 + } 1.199 + 1.200 + /* permute indices by swapping them randomly */ 1.201 + for(i=0; i<B; i++) { 1.202 + int rand_idx = rand() % B; 1.203 + 1.204 + int tmp = perm[i]; 1.205 + perm[i] = perm[rand_idx]; 1.206 + perm[rand_idx] = tmp; 1.207 + } 1.208 + 1.209 + /* fill up the rest of the arrays by duplicating the existing gradients */ 1.210 + /* and permutations */ 1.211 + for(i=0; i<B+2; i++) { 1.212 + perm[B + i] = perm[i]; 1.213 + grad1[B + i] = grad1[i]; 1.214 + grad2[B + i] = grad2[i]; 1.215 + grad3[B + i] = grad3[i]; 1.216 + } 1.217 +} 1.218 + 1.219 +scalar_t noise1(scalar_t x) 1.220 +{ 1.221 + int bx0, bx1; 1.222 + scalar_t rx0, rx1, sx, u, v; 1.223 + 1.224 + if(!tables_valid) { 1.225 + init_noise(); 1.226 + tables_valid = 1; 1.227 + } 1.228 + 1.229 + setup(x, bx0, bx1, rx0, rx1); 1.230 + sx = s_curve(rx0); 1.231 + u = rx0 * grad1[perm[bx0]]; 1.232 + v = rx1 * grad1[perm[bx1]]; 1.233 + 1.234 + return lerp(u, v, sx); 1.235 +} 1.236 + 1.237 +scalar_t noise2(scalar_t x, scalar_t y) 1.238 +{ 1.239 + int i, j, b00, b10, b01, b11; 1.240 + int bx0, bx1, by0, by1; 1.241 + scalar_t rx0, rx1, ry0, ry1; 1.242 + scalar_t sx, sy, u, v, a, b; 1.243 + 1.244 + if(!tables_valid) { 1.245 + init_noise(); 1.246 + tables_valid = 1; 1.247 + } 1.248 + 1.249 + setup(x, bx0, bx1, rx0, rx1); 1.250 + setup(y, by0, by1, ry0, ry1); 1.251 + 1.252 + i = perm[bx0]; 1.253 + j = perm[bx1]; 1.254 + 1.255 + b00 = perm[i + by0]; 1.256 + b10 = perm[j + by0]; 1.257 + b01 = perm[i + by1]; 1.258 + b11 = perm[j + by1]; 1.259 + 1.260 + /* calculate hermite inteprolating factors */ 1.261 + sx = s_curve(rx0); 1.262 + sy = s_curve(ry0); 1.263 + 1.264 + /* interpolate along the left edge */ 1.265 + u = v2_dot(grad2[b00], v2_cons(rx0, ry0)); 1.266 + v = v2_dot(grad2[b10], v2_cons(rx1, ry0)); 1.267 + a = lerp(u, v, sx); 1.268 + 1.269 + /* interpolate along the right edge */ 1.270 + u = v2_dot(grad2[b01], v2_cons(rx0, ry1)); 1.271 + v = v2_dot(grad2[b11], v2_cons(rx1, ry1)); 1.272 + b = lerp(u, v, sx); 1.273 + 1.274 + /* interpolate between them */ 1.275 + return lerp(a, b, sy); 1.276 +} 1.277 + 1.278 +scalar_t noise3(scalar_t x, scalar_t y, scalar_t z) 1.279 +{ 1.280 + int i, j; 1.281 + int bx0, bx1, by0, by1, bz0, bz1; 1.282 + int b00, b10, b01, b11; 1.283 + scalar_t rx0, rx1, ry0, ry1, rz0, rz1; 1.284 + scalar_t sx, sy, sz; 1.285 + scalar_t u, v, a, b, c, d; 1.286 + 1.287 + if(!tables_valid) { 1.288 + init_noise(); 1.289 + tables_valid = 1; 1.290 + } 1.291 + 1.292 + setup(x, bx0, bx1, rx0, rx1); 1.293 + setup(y, by0, by1, ry0, ry1); 1.294 + setup(z, bz0, bz1, rz0, rz1); 1.295 + 1.296 + i = perm[bx0]; 1.297 + j = perm[bx1]; 1.298 + 1.299 + b00 = perm[i + by0]; 1.300 + b10 = perm[j + by0]; 1.301 + b01 = perm[i + by1]; 1.302 + b11 = perm[j + by1]; 1.303 + 1.304 + /* calculate hermite interpolating factors */ 1.305 + sx = s_curve(rx0); 1.306 + sy = s_curve(ry0); 1.307 + sz = s_curve(rz0); 1.308 + 1.309 + /* interpolate along the top slice of the cell */ 1.310 + u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz0)); 1.311 + v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz0)); 1.312 + a = lerp(u, v, sx); 1.313 + 1.314 + u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz0)); 1.315 + v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz0)); 1.316 + b = lerp(u, v, sx); 1.317 + 1.318 + c = lerp(a, b, sy); 1.319 + 1.320 + /* interpolate along the bottom slice of the cell */ 1.321 + u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz1)); 1.322 + v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz1)); 1.323 + a = lerp(u, v, sx); 1.324 + 1.325 + u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz1)); 1.326 + v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz1)); 1.327 + b = lerp(u, v, sx); 1.328 + 1.329 + d = lerp(a, b, sy); 1.330 + 1.331 + /* interpolate between slices */ 1.332 + return lerp(c, d, sz); 1.333 +} 1.334 + 1.335 +scalar_t fbm1(scalar_t x, int octaves) 1.336 +{ 1.337 + int i; 1.338 + scalar_t res = 0.0f, freq = 1.0f; 1.339 + for(i=0; i<octaves; i++) { 1.340 + res += noise1(x * freq) / freq; 1.341 + freq *= 2.0f; 1.342 + } 1.343 + return res; 1.344 +} 1.345 + 1.346 +scalar_t fbm2(scalar_t x, scalar_t y, int octaves) 1.347 +{ 1.348 + int i; 1.349 + scalar_t res = 0.0f, freq = 1.0f; 1.350 + for(i=0; i<octaves; i++) { 1.351 + res += noise2(x * freq, y * freq) / freq; 1.352 + freq *= 2.0f; 1.353 + } 1.354 + return res; 1.355 +} 1.356 + 1.357 +scalar_t fbm3(scalar_t x, scalar_t y, scalar_t z, int octaves) 1.358 +{ 1.359 + int i; 1.360 + scalar_t res = 0.0f, freq = 1.0f; 1.361 + for(i=0; i<octaves; i++) { 1.362 + res += noise3(x * freq, y * freq, z * freq) / freq; 1.363 + freq *= 2.0f; 1.364 + } 1.365 + return res; 1.366 +} 1.367 + 1.368 +scalar_t turbulence1(scalar_t x, int octaves) 1.369 +{ 1.370 + int i; 1.371 + scalar_t res = 0.0f, freq = 1.0f; 1.372 + for(i=0; i<octaves; i++) { 1.373 + res += fabs(noise1(x * freq) / freq); 1.374 + freq *= 2.0f; 1.375 + } 1.376 + return res; 1.377 +} 1.378 + 1.379 +scalar_t turbulence2(scalar_t x, scalar_t y, int octaves) 1.380 +{ 1.381 + int i; 1.382 + scalar_t res = 0.0f, freq = 1.0f; 1.383 + for(i=0; i<octaves; i++) { 1.384 + res += fabs(noise2(x * freq, y * freq) / freq); 1.385 + freq *= 2.0f; 1.386 + } 1.387 + return res; 1.388 +} 1.389 + 1.390 +scalar_t turbulence3(scalar_t x, scalar_t y, scalar_t z, int octaves) 1.391 +{ 1.392 + int i; 1.393 + scalar_t res = 0.0f, freq = 1.0f; 1.394 + for(i=0; i<octaves; i++) { 1.395 + res += fabs(noise3(x * freq, y * freq, z * freq) / freq); 1.396 + freq *= 2.0f; 1.397 + } 1.398 + return res; 1.399 +}