diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8f68652..8f8485a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,3 +4,5 @@ target_link_libraries(memo PRIVATE tc vis-util) add_executable(geom geomtest.cpp) target_link_libraries(geom PRIVATE tc vis-util) +add_executable(sub subtest.cpp) +target_link_libraries(sub PRIVATE vis-util) diff --git a/examples/subtest.cpp b/examples/subtest.cpp new file mode 100644 index 0000000..76f6a68 --- /dev/null +++ b/examples/subtest.cpp @@ -0,0 +1,24 @@ +#include +#include + +#include +#include + +template +std::ostream &operator<<(std::ostream &o, const std::vector &v) { + for (const auto &e : v) o << e << " "; + return o; +} + +int main() { + std::vector gens(5); + std::iota(gens.begin(), gens.end(), 0); + + const Combos &combos = Combos(gens, 2); + + for (const auto &e : combos) { + std::cout << e << std::endl; + } + + return EXIT_SUCCESS; +} diff --git a/vis/include/combo_iterator.hpp b/vis/include/combo_iterator.hpp new file mode 100644 index 0000000..c9238c4 --- /dev/null +++ b/vis/include/combo_iterator.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include + +template +struct ComboIterator { + const std::vector &vals; + const size_t k; + size_t n; + std::vector bits; + std::vector curr; + + ComboIterator(ComboIterator &) = default; + + ComboIterator(const std::vector &vals, const size_t k, const size_t n) + : vals(vals), k(k), n(n), curr(k), bits(vals.size()) { + for (size_t i = 0; i < vals.size(); ++i) { + bits[i] = i < k; + } + std::reverse(bits.begin(), bits.end()); + set_curr(); + } + + void set_curr() { + for (size_t i = 0, j = 0; i < vals.size(); ++i) { + if (bits[i]) curr[j++] = vals[i]; + } + } + + const std::vector &operator*() const { + return curr; + } + + void operator++() { + std::next_permutation(bits.begin(), bits.end()); + set_curr(); + ++n; + } + + [[nodiscard]] bool operator!=(const ComboIterator &o) const { + return n != o.n; + } + + [[nodiscard]] bool operator==(const ComboIterator &o) const { + return n == o.n; + } +}; + +size_t choose(size_t n, size_t k) { + if (k == 0) return 1; + return n * choose(n - 1, k - 1) / k; +} + +template +struct Combos { + const std::vector &vals; + size_t k; + + Combos(const std::vector &vals, size_t k) : vals(vals), k(k) { + } + + [[nodiscard]] ComboIterator begin() const { + return ComboIterator(vals, k, 0); + } + + [[nodiscard]] ComboIterator end() const { + int j = choose(vals.size(), k); + return ComboIterator(vals, k, j); + } +}; diff --git a/vis/include/geometry.hpp b/vis/include/geometry.hpp index 037b7c4..2736afb 100644 --- a/vis/include/geometry.hpp +++ b/vis/include/geometry.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "combo_iterator.hpp" size_t get_key_from_gens(std::vector &gens) { size_t key = 0; @@ -229,14 +230,7 @@ struct GeomGen { S.vals.push_back(0); return S; } - std::vector sg_gens(g_gens.size()-1); - for (int i = 0; i < g_gens.size(); i++) { - int k = 0; - for (int j = 0; j < g_gens.size(); j++) { - if (j != i) { - sg_gens[k++] = g_gens[j]; - } - } + for (std::vector sg_gens : Combos(g_gens, g_gens.size() - 1)) { auto sub_simps = triangulate(sg_gens); int start = sub_simps.size(); sub_simps = tile(g_gens, sg_gens, sub_simps); diff --git a/vis/include/util.hpp b/vis/include/util.hpp index 49ec0d1..17d30ab 100644 --- a/vis/include/util.hpp +++ b/vis/include/util.hpp @@ -139,3 +139,23 @@ GLuint utilCreateShaderProgramFile(GLenum type, const std::vector & std::transform(files.begin(), files.end(), sources.begin(), utilReadFile); return utilCreateShaderProgram(type, sources); } + +std::vector utilCreateVertexArrays(int n) { + std::vector res(n); + glCreateVertexArrays(n, &res[0]); + return res; +} + +GLuint utilCreateVertexArray() { + return utilCreateVertexArrays(1)[0]; +} + +std::vector utilCreateBuffers(int n) { + std::vector res(n); + glCreateBuffers(n, &res[0]); + return res; +} + +GLuint utilCreateBuffer() { + return utilCreateBuffers(1)[0]; +} \ No newline at end of file diff --git a/vis/src/main.cpp b/vis/src/main.cpp index 5a12906..41b3326 100644 --- a/vis/src/main.cpp +++ b/vis/src/main.cpp @@ -102,12 +102,35 @@ int main(int argc, char *argv[]) { auto mirrors = mirror(group); auto corners = plane_intersections(mirrors); - auto start = barycentric(corners, {1.00f, 0.1f, 0.01f, 0.01f}); +// auto start = barycentric(corners, {1.0f, 1.0f, 1.0f, 1.0f}); + auto start = barycentric(corners, {1.00f, 0.2f, 0.1f, 0.05f}); +// auto start = barycentric(corners, {0.05f, 0.1f, 0.2f, 1.00f}); auto points = res.path.walk(start, mirrors, reflect); auto g_gens = gg.group_gens(); - std::vector sg_gens = {0, 1, 2}; - const std::vector simps = gg.tile(g_gens, sg_gens, gg.triangulate(sg_gens)).vals; + + std::vector vaos; + std::vector ibos; + std::vector counts; + + for (auto sg_gens : Combos(g_gens, 3)) { + const std::vector data = gg.tile(g_gens, sg_gens, gg.triangulate(sg_gens)).vals; + + GLuint vao = utilCreateVertexArray(); + GLuint ibo = utilCreateBuffer(); + unsigned count = data.size(); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, ibo); + glBufferData(GL_ARRAY_BUFFER, sizeof(int) * count, &data[0], GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribIPointer(0, 4, GL_INT, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + vaos.push_back(vao); + ibos.push_back(ibo); + counts.push_back(count); + } //endregion GLuint vbo; @@ -119,30 +142,11 @@ int main(int argc, char *argv[]) { GLuint ubo; glGenBuffers(1, &ubo); - GLuint ibo; - glGenBuffers(1, &ibo); - glBindBuffer(GL_ARRAY_BUFFER, ibo); - glBufferData(GL_ARRAY_BUFFER, sizeof(int) * simps.size(), &simps[0], GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo); glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo); - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, ibo); - glEnableVertexAttribArray(0); - glVertexAttribIPointer(0, 4, GL_INT, 0, nullptr); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - std::cout << points.size() << " points" << std::endl; - std::cout << simps.size() << " simplexes" << std::endl; - while (!glfwWindowShouldClose(window)) { int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -156,11 +160,18 @@ int main(int argc, char *argv[]) { glBufferData(GL_UNIFORM_BUFFER, sizeof(mats), &mats, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glBindVertexArray(vao); - glBindProgramPipeline(pipe); + for (int i = 0; i < vaos.size(); ++i) { + auto c = glm::mix( + glm::vec3(.3, .2, .5), + glm::vec3(.9, .9, .95), + (float) (i + 1) / vaos.size() + ); - glProgramUniform3f(fs, 2, 1.0f, 1.0f, 1.0f); - glDrawArrays(GL_POINTS, 0, simps.size() / 4); + glBindProgramPipeline(pipe); + glBindVertexArray(vaos[i]); + glProgramUniform3f(fs, 2, c.r, c.g, c.b); + glDrawArrays(GL_POINTS, 0, counts[i] / 4); + } glBindProgramPipeline(0); glBindVertexArray(0);