#ifndef SIMPLEX_MESH_H #define SIMPLEX_MESH_H #include #include #include #include template struct Mesh { std::vector verts; std::vector inds; Mesh(std::vector verts, std::vector inds) : verts(std::move(verts)), inds(std::move(inds)) {} unsigned size() { return (unsigned) inds.size() / prim; } }; template Mesh concat(Mesh m, Mesh n) { Mesh res({}, {}); for (auto v: m.verts) res.verts.push_back(v); for (auto v: n.verts) res.verts.push_back(v); auto off = (unsigned) m.verts.size(); for (auto i: m.inds) res.inds.push_back(i); for (auto i: n.inds) res.inds.push_back(off + i); return res; } template Mesh transform(Mesh m, glm::mat4 mat) { Mesh res(m.verts, m.inds); for (auto &vert : res.verts) vert = mat * vert; return res; } template Mesh offset(Mesh m, glm::vec4 off) { Mesh res(m.verts, m.inds); for (auto &vert : res.verts) vert += off; return res; } template Mesh scale(Mesh m, glm::vec4 scl) { Mesh res(m.verts, m.inds); for (auto &vert : res.verts) vert *= scl; return res; } template Mesh scale(Mesh m, float scl) { return scale(m, glm::vec4(scl)); } template Mesh pyramid(Mesh m, glm::vec4 apex) { Mesh res(m.verts, {}); res.verts.push_back(apex); auto apex_ind = (unsigned) res.verts.size() - 1; for (int i = 0; i < m.size(); ++i) { for (int j = 0; j < prim; ++j) { res.inds.push_back(m.inds[i * prim + j]); } res.inds.push_back(apex_ind); } return res; } template Mesh fill(Mesh m) { Mesh res(m.verts, {}); for (int i = 0; i < m.size(); ++i) { for (int j = 0; j < prim; ++j) { res.inds.push_back(m.inds[i * prim + j]); } res.inds.push_back(0); } return res; } template Mesh join(Mesh m, Mesh n) { Mesh res({}, {}); for (auto v : m.verts) res.verts.push_back(v); for (auto v : n.verts) res.verts.push_back(v); auto off = (unsigned) m.verts.size(); auto size = (int) std::min(m.inds.size(), n.inds.size()); for (int i = 0; i < size; i += prim) { for (int j = 0; j < prim; ++j) { for (int x = j; x < prim; ++x) res.inds.push_back(m.inds[i + x]); for (int x = 0; x <= j; ++x) res.inds.push_back(off + n.inds[i + x]); } } return res; } template Mesh joinCap(Mesh m, Mesh n) { return concat(join(m, n), concat(fill(m), fill(n))); } template Mesh thicken(const Mesh &m, glm::vec4 width) { return joinCap(m - width / 2.f, m + width / 2.f); } template Mesh operator+(Mesh m, Mesh n) { return concat(m, n); } template Mesh operator+(Mesh m, glm::vec4 off) { return offset(m, off); } template Mesh operator-(Mesh m, glm::vec4 off) { return offset(m, -off); } template Mesh operator*(Mesh m, glm::vec4 scl) { return scale(m, scl); } template Mesh operator/(Mesh m, glm::vec4 scl) { return scale(m, 1.f / scl); } template Mesh operator*(Mesh m, float scl) { return scale(m, scl); } template Mesh operator/(Mesh m, float scl) { return scale(m, 1.f / scl); } template Mesh operator*(glm::mat4 mat, Mesh m) { return transform(m, mat); } template Mesh simplify(Mesh m) { // todo remove redundant vertices and primitives return Mesh({}, {}); } #endif //SIMPLEX_MESH_H