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