nuclear@29: #include nuclear@29: #include "bezmath.h" nuclear@29: nuclear@29: static float bernstein(int i, float x); nuclear@29: nuclear@29: nuclear@29: struct vec3 v3_add(struct vec3 a, struct vec3 b) nuclear@29: { nuclear@29: a.x += b.x; nuclear@29: a.y += b.y; nuclear@29: a.z += b.z; nuclear@29: return a; nuclear@29: } nuclear@29: nuclear@29: struct vec3 v3_sub(struct vec3 a, struct vec3 b) nuclear@29: { nuclear@29: a.x -= b.x; nuclear@29: a.y -= b.y; nuclear@29: a.z -= b.z; nuclear@29: return a; nuclear@29: } nuclear@29: nuclear@29: struct vec3 v3_cross(struct vec3 a, struct vec3 b) nuclear@29: { nuclear@29: struct vec3 res; nuclear@29: res.x = a.y * b.z - a.z * b.y; nuclear@29: res.y = a.z * b.x - a.x * b.z; nuclear@29: res.z = a.x * b.y - a.y * b.x; nuclear@29: return res; nuclear@29: } nuclear@29: nuclear@29: struct vec3 v3_normalize(struct vec3 v) nuclear@29: { nuclear@29: float len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); nuclear@29: v.x /= len; nuclear@29: v.y /= len; nuclear@29: v.z /= len; nuclear@29: return v; nuclear@29: } nuclear@29: nuclear@29: struct vec3 bezier_patch(struct vec3 *cp, float u, float v) nuclear@29: { nuclear@29: int i, j; nuclear@29: struct vec3 res = {0, 0, 0}; nuclear@29: nuclear@29: for(j=0; j<4; j++) { nuclear@29: for(i=0; i<4; i++) { nuclear@29: float bu = bernstein(i, u); nuclear@29: float bv = bernstein(j, v); nuclear@29: nuclear@29: res.x += cp->x * bu * bv; nuclear@29: res.y += cp->y * bu * bv; nuclear@29: res.z += cp->z * bu * bv; nuclear@29: nuclear@29: cp++; nuclear@29: } nuclear@29: } nuclear@29: return res; nuclear@29: } nuclear@29: nuclear@29: #define DT 0.001 nuclear@29: nuclear@29: struct vec3 bezier_patch_norm(struct vec3 *cp, float u, float v) nuclear@29: { nuclear@29: struct vec3 tang, bitan, norm; nuclear@29: nuclear@29: tang = v3_sub(bezier_patch(cp, u + DT, v), bezier_patch(cp, u - DT, v)); nuclear@29: bitan = v3_sub(bezier_patch(cp, u, v + DT), bezier_patch(cp, u, v - DT)); nuclear@29: norm = v3_cross(tang, bitan); nuclear@29: nuclear@29: return v3_normalize(norm); nuclear@29: } nuclear@29: nuclear@29: nuclear@29: nuclear@29: static float bernstein(int i, float x) nuclear@29: { nuclear@29: float invx = 1.0 - x; nuclear@29: nuclear@29: switch(i) { nuclear@29: case 0: nuclear@29: return invx * invx * invx; nuclear@29: case 1: nuclear@29: return 3 * x * invx * invx; nuclear@29: case 2: nuclear@29: return 3 * x * x * invx; nuclear@29: case 3: nuclear@29: return x * x * x; nuclear@29: default: nuclear@29: break; nuclear@29: } nuclear@29: return 0; nuclear@29: }