#include #include "math/vec.hpp" namespace bezier { template struct vec_lmno { vec l; vec m; vec n; vec o; }; struct triangle { int a; int b; int c; }; template constexpr inline vec_lmno interpolate_quadratic(const T d, const vec& l1, const vec& m1, const vec& n1, const vec& o1, const vec& l2, const vec& m2, const vec& n2, const vec& o2, const vec& l3, const vec& m3, const vec& n3, const vec& o3) { T invd = 1.0 - d; T d1 = invd * invd; T d2 = 2.0 * d * invd; T d3 = d * d; vec l; for (int i = 0; i < L; i++) { l[i] = l1[i] * d1 + l2[i] * d2 + l3[i] * d3; }; vec m; for (int i = 0; i < M; i++) { m[i] = m1[i] * d1 + m2[i] * d2 + m3[i] * d3; } vec n; for (int i = 0; i < N; i++) { n[i] = n1[i] * d1 + n2[i] * d2 + n3[i] * d3; }; vec o; for (int i = 0; i < O; i++) { o[i] = o1[i] * d1 + o2[i] * d2 + o3[i] * d3; }; return {l, m, n, o}; } template constexpr inline vec_lmno interpolate_quadratic(const T d, const vec_lmno& va, const vec_lmno& vb, const vec_lmno& vc) { return interpolate_quadratic(d, va.l, va.m, va.n, va.o, vb.l, vb.m, vb.n, vb.o, vc.l, vc.m, vc.n, vc.o); } template constexpr inline void tessellate(const int level, const vec_lmno * control, // [9] vec_lmno * vertices, // [2 * level * level] triangle * triangles, int vertex_base = 0) { vec_lmno column[3][level + 1]; T inv_level = 1.0 / level; for (int i = 0; i <= level; i++) { T d = inv_level * i; column[0][i] = interpolate_quadratic(d, control[0], control[3], control[6]); column[1][i] = interpolate_quadratic(d, control[1], control[4], control[7]); column[2][i] = interpolate_quadratic(d, control[2], control[5], control[8]); } for (int i = 0; i <= level; i++) { for (int j = 0; j <= level; j++) { T d = inv_level * j; *vertices++ = interpolate_quadratic(d, column[0][i], column[1][i], column[2][i]); } } for (int i = 0; i < level; i++) { for (int j = 0; j < level; j++) { int ix = vertex_base + j * (level + 1) + i; *triangles++ = {ix + 0, ix + (level + 1) + 0, ix + (level + 1) + 1}; *triangles++ = {ix + 0, ix + (level + 1) + 1, ix + 1}; } } } }