From 2fcb15a14d6739b7d23060edd809fb56d4358674 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Fri, 13 Mar 2020 17:49:59 -0400 Subject: [PATCH] change combo iterator --- vis/include/combo_iterator.hpp | 98 +++++------- vis/src/combotest.cpp | 275 +++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 59 deletions(-) create mode 100644 vis/src/combotest.cpp diff --git a/vis/include/combo_iterator.hpp b/vis/include/combo_iterator.hpp index 866502f..8890bee 100644 --- a/vis/include/combo_iterator.hpp +++ b/vis/include/combo_iterator.hpp @@ -1,72 +1,58 @@ #pragma once -#include +#include #include +#include #include -template -struct ComboIterator { - typedef ComboIterator self_type; - typedef const std::vector value_type;; - typedef const std::vector *pointer; - typedef const std::vector &reference; - typedef size_t difference_type; - typedef std::forward_iterator_tag iterator_category; +template +class ComboIterator { + static_assert(N > K, "N must be larger than K"); - const std::vector &vals; - const size_t k; - size_t n; - std::vector bits; - std::vector curr; +public: + size_t at; + std::array bits; + std::array 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; + void inc() { + std::prev_permutation(bits.begin(), bits.end()); + for (int i = 0, k = 0; i < N; ++i) { + if (bits[i]) curr[k++] = i; } - std::reverse(bits.begin(), bits.end()); - set_curr(); + at++; } - ~ComboIterator() = default; - - void set_curr() { - for (size_t i = 0, j = 0; i < vals.size(); ++i) { - if (bits[i]) curr[j++] = vals[i]; - } +public: + ComboIterator(size_t at = 0) : at(at), bits(), curr() { + std::iota(curr.begin(), curr.end(), 0); + std::fill(bits.begin(), bits.begin() + K, true); } - [[nodiscard]] bool operator==(const ComboIterator &o) const { - return n == o.n; + [[nodiscard]] bool operator==(const ComboIterator &o) const { + return at == o.at; } - [[nodiscard]] bool operator!=(const ComboIterator &o) const { - return n != o.n; + [[nodiscard]] bool operator!=(const ComboIterator &o) const { + return at != o.at; } - reference operator*() const { + auto operator*() const { return curr; } - pointer operator->() const { + const auto *operator->() const { return &curr; } - self_type operator++(int) { - std::next_permutation(bits.begin(), bits.end()); - set_curr(); - ++n; - return *this; + auto operator++(int) { + auto res = *this; + inc(); + return res; } - self_type operator++() { - self_type r = *this; - std::next_permutation(bits.begin(), bits.end()); - set_curr(); - ++n; - return r; + auto operator++() &{ + inc(); + return *this; } }; @@ -75,21 +61,15 @@ size_t choose(size_t n, size_t k) { return n * choose(n - 1, k - 1) / k; } -template -struct Combos { - const std::vector &vals; - size_t k; - - // todo make k a template argument - Combos(const std::vector &vals, size_t k) : vals(vals), k(k) { +template +class Combos { +private: +public: + auto begin() const { + return ComboIterator(); } - [[nodiscard]] ComboIterator begin() const { - return ComboIterator(vals, k, 0); - } - - [[nodiscard]] ComboIterator end() const { - int j = choose(vals.size(), k); - return ComboIterator(vals, k, j); + auto end() const { + return ComboIterator(choose(N, K)); } }; diff --git a/vis/src/combotest.cpp b/vis/src/combotest.cpp new file mode 100644 index 0000000..9eb1976 --- /dev/null +++ b/vis/src/combotest.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include + +#include + +#include + +#include "util.hpp" +#include "mirror.hpp" +#include "geometry.hpp" + +#include +#include +#include +#include + +#include + +#ifdef _WIN32 +extern "C" { +__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001; +} +#endif + +struct Matrices { + glm::mat4 proj; + glm::mat4 view; + + Matrices(const glm::mat4 &proj, const glm::mat4 &view) + : proj(proj), view(view) { + } +}; + +template +struct Drawable { + GLenum mode{}; + cgl::VertexArray vao{}; + cgl::Buffer> ibo{}; + + Drawable(GLenum mode) : mode(mode), vao(), ibo() {} + + Drawable(Drawable &) = delete; + + Drawable(Drawable &&) = delete; + + void draw_deferred() { + vao.bound([&]() { + glDrawArrays(GL_POINTS, 0, ibo.count() * N); + }); + } + + void draw_direct() { + vao.bound([&]() { + ibo.bound(GL_ELEMENT_ARRAY_BUFFER, [&]() { + glDrawElements(mode, ibo.count() * N, GL_UNSIGNED_INT, nullptr); + }); + }); + } +}; + +class Slice { + +}; + +Matrices build(GLFWwindow *window, float st) { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + auto aspect = (float) width / (float) height; + auto pheight = 1.4f; + auto pwidth = aspect * pheight; + glm::mat4 proj = glm::ortho(-pwidth, pwidth, -pheight, pheight, -10.0f, 10.0f); + + auto view = glm::identity(); + view *= utilRotate(0, 1, st * .40f); + view *= utilRotate(0, 2, st * .20f); + view *= utilRotate(0, 3, st * 1.30f); + view *= utilRotate(1, 2, st * .50f); + view *= utilRotate(1, 3, st * .25f); + view *= utilRotate(2, 3, st * 1.42f); + + return Matrices(proj, view); +} + +template +auto hull(const tc::Group &group, T all_sg_gens) { + std::vector>> parts; + auto g_gens = gens(group); + for (const auto &sg_gens : all_sg_gens) { + const auto &base = triangulate(group, sg_gens); + const auto &tiles = each_tile(base, group, g_gens, sg_gens); + for (const auto &tile : tiles) { + parts.push_back(tile); + } + } + return parts; +} + +template +auto full_hull(const tc::Group &group) { + auto g_gens = gens(group); +// const Combos &combos = Combos(g_gens, N - 1); +// return hull>(group, combos); +} + +class Shaders { +public: + cgl::pgm::vert defer = cgl::pgm::vert::file( + "shaders/slice/deferred.vs.glsl"); + cgl::pgm::vert direct_ortho = cgl::pgm::vert::file( + "shaders/direct-ortho.vs.glsl"); + cgl::pgm::vert direct_stereo = cgl::pgm::vert::file( + "shaders/direct-stereo.vs.glsl"); + + cgl::pgm::geom slice = cgl::pgm::geom::file( + "shaders/slice/slice.gm.glsl"); + cgl::pgm::geom curve_stereo = cgl::pgm::geom::file( + "shaders/curve-stereo.gm.glsl"); + cgl::pgm::geom curve_ortho = cgl::pgm::geom::file( + "shaders/curve-ortho.gm.glsl"); + + cgl::pgm::frag solid = cgl::pgm::frag::file( + "shaders/solid.fs.glsl"); + cgl::pgm::frag diffuse = cgl::pgm::frag::file( + "shaders/diffuse.fs.glsl"); +}; + +std::vector points(const tc::Group &group, const std::vector &coords) { + auto cosets = group.solve(); + auto mirrors = mirror<5>(group); + + auto corners = plane_intersections(mirrors); + + auto start = barycentric(corners, coords); + + auto higher = cosets.path.walk(start, mirrors, reflect); + std::vector res(higher.size()); + std::transform(higher.begin(), higher.end(), res.begin(), stereo<4>); + + return res; +} + +void run(GLFWwindow *window) { + glEnable(GL_PROGRAM_POINT_SIZE); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_DEPTH_TEST); +// glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Shaders sh; + + auto proj_pipe = cgl::pipeline(); + proj_pipe + .stage(sh.direct_stereo) + .stage(sh.solid); + + auto slice_pipe = cgl::pipeline(); + slice_pipe + .stage(sh.defer) + .stage(sh.slice) + .stage(sh.solid); + + auto group = tc::schlafli({5, 3, 3, 2}); +// std::cout << group.solve({}).size() << std::endl; +// const auto &all = merge(full_hull<4>(group)); +// std::cout << all.size() / sizeof(Primitive<4>) << std::endl; +// const auto &one = merge(full_hull<4>(tc::schlafli({5, 3, 3}))); +// std::cout << one.size() / sizeof(Primitive<4>) << std::endl; + + + auto slice_faces = hull<4>(group, (std::vector>) { + {0, 1, 2}, + {0, 1, 4}, + {0, 2, 4}, + {1, 2, 4}, + +// {0, 1, 2,}, +// {0, 1, 3,}, +// {0, 2, 3,}, +// {1, 2, 3,}, + }); + auto slice_face_data = merge<4>(slice_faces); + + auto slice_edges = hull<4>(group, (std::vector>) { + {0, 1, 3}, + {0, 1, 4}, + {0, 2, 3}, + {0, 2, 4}, + {1, 2, 3}, + {1, 2, 4}, + {1, 3, 4}, + }); + auto slice_edge_data = merge<4>(slice_edges); + + Drawable<4> edges(GL_POINTS); + edges.ibo.put(slice_edge_data); + edges.vao.ipointer(0, edges.ibo, 4, GL_UNSIGNED_INT); + + Drawable<4> faces(GL_POINTS); + faces.ibo.put(slice_face_data); + faces.vao.ipointer(0, faces.ibo, 4, GL_UNSIGNED_INT); + + auto pbo_white = cgl::Buffer(points(group, {0.3f, 0.12f, 0.12f, 0.12f, 0.025f})); + auto pbo_black = cgl::Buffer(); + + auto ubo = cgl::Buffer(); + glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo); + + while (!glfwWindowShouldClose(window)) { + auto time = (float) glfwGetTime(); + pbo_black.put(points(group, {0.5f, 0.1f, 0.1f, 0.1f, sinf(time / 2)})); + + int width, height; + glfwGetFramebufferSize(window, &width, &height); + glViewport(0, 0, width, height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + auto st = time / 16 - 1; + Matrices mats = build(window, st); + ubo.put(mats); + + glLineWidth(1.5); + + slice_pipe.bound([&]() { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, pbo_black); + glProgramUniform4f(sh.solid, 2, 0.3, 0.3, 0.3, 1.0); + edges.draw_deferred(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, pbo_white); + glProgramUniform4f(sh.solid, 2, 1.0, 1.0, 1.0, 1.0); + faces.draw_deferred(); + }); + + glfwSwapInterval(2); + glfwSwapBuffers(window); + + glfwPollEvents(); + } +} + +int main(int argc, char *argv[]) { + if (!glfwInit()) { + std::cerr << "Failed to initialize GLFW" << std::endl; + return EXIT_FAILURE; + } + + auto window = glfwCreateWindow( + 1280, 720, + "Coset Visualization", + nullptr, nullptr); + + if (!window) { + std::cerr << "Failed to create window" << std::endl; + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwMakeContextCurrent(window); + gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); + glfwSwapInterval(1); + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(window); + + std::cout << utilInfo(); + + run(window); + + glfwTerminate(); + return EXIT_SUCCESS; +}