#pragma once #include #include #include #include template using vec = std::array; using vec1 = vec<1>; using vec2 = vec<2>; using vec3 = vec<3>; using vec4 = vec<4>; using vec5 = vec<5>; template V operator*(V a, const float &b) { for (auto &e : a) e *= b; return a; } template V operator*(const float &b, V a) { for (auto &e : a) e *= b; return a; } template V operator/(V a, const float &b) { for (auto &e : a) e /= b; return a; } template V operator+(const V &a, V b) { for (int i = 0; i < a.size(); ++i) { a[i] += b[i]; } return a; } template V operator-(V a, const V &b) { for (int i = 0; i < a.size(); ++i) { a[i] -= b[i]; } return a; } template void operator-=(V &a, const V &b) { for (int i = 0; i < a.size(); ++i) { a[i] -= b[i]; } } template void operator+=(V &a, const V &b) { for (int i = 0; i < a.size(); ++i) { a[i] += b[i]; } } template float length(const V &a) { float sum = 0; for (const auto &e : a) sum += e * e; return sqrtf(sum); } template V normalized(const V &a) { return a / length(a); } template float dot(int n, const V &a, const V &b) { float sum = 0; for (int i = 0; i < n; ++i) { sum += a[i] * b[i]; } return sum; } template float dot(const V &a, const V &b) { float sum = 0; for (int i = 0; i < a.size(); ++i) { sum += a[i] * b[i]; } return sum; } template std::vector> mirror(const tc::Group<> &group) { std::vector> mirrors; for (int p = 0; p < group.rank(); ++p) { std::vector vp; for (int m = 0; m < p; ++m) { auto &vq = mirrors[m]; vp.push_back((cos(M_PI / group.get(p, m)) - dot(m, vp, vq)) / vq[m]); } vp.push_back(std::sqrt(1 - dot(p, vp, vp))); for (const auto &v : mirrors) { if (dot(p, vp, vp) > 0) { for (auto &e : vp) { e *= -1; } break; } } mirrors.push_back(vp); } std::vector> res; for (const auto &v : mirrors) { vec rv{}; // ortho proj for (int i = 0; i < std::min(v.size(), (size_t) N); ++i) { rv[i] = v[i]; } res.push_back(rv); } return res; } template vec stereo(const vec &v) { vec r; for (int i = 0; i < N; ++i) { r[i] = v[i] / (1 - v[N]); } return r; } template V project(const V &vec, const V &target) { return dot(vec, target) / dot(target, target) * target; } template V reflect(const V &a, const V &axis) { return a - 2.f * project(a, axis); } template V gram_schmidt_last(std::vector vecs) { for (int i = 0; i < vecs.size(); ++i) { for (int j = 0; j < i; ++j) { vecs[i] -= project(vecs[i], vecs[j]); } } return normalized(vecs[vecs.size() - 1]); } template V barycentric(const std::vector &basis, const C &coords) { V res{}; int N = std::min(basis.size(), coords.size()); for (int i = 0; i < N; ++i) { res += basis[i] * coords[i]; } return res; } template std::vector plane_intersections(std::vector normals) { std::vector results(normals.size()); for (int i = 0; i < normals.size(); ++i) { std::rotate(normals.begin(), normals.begin() + 1, normals.end()); results[i] = gram_schmidt_last(normals); } return results; } glm::mat4 utilRotate(const int u, const int v, const float theta) { auto res = glm::identity(); res[u][u] = std::cos(theta); res[u][v] = std::sin(theta); res[v][u] = -std::sin(theta); res[v][v] = std::cos(theta); return res; }