diff --git a/vis/CMakeLists.txt b/vis/CMakeLists.txt index 12f2dd9..394e3c0 100644 --- a/vis/CMakeLists.txt +++ b/vis/CMakeLists.txt @@ -12,3 +12,6 @@ add_executable(vis src/main.cpp) target_include_directories(vis PRIVATE include) target_link_libraries(vis PRIVATE tc glad glm glfw) add_dependencies(vis shaders) + +add_executable(ctest src/combotest.cpp) +target_include_directories(ctest PRIVATE include) diff --git a/vis/include/combo_iterator.hpp b/vis/include/combo_iterator.hpp index 8890bee..49bdb5c 100644 --- a/vis/include/combo_iterator.hpp +++ b/vis/include/combo_iterator.hpp @@ -1,38 +1,43 @@ #pragma once +#include #include #include #include #include -template +size_t choose(size_t n, size_t k) { + if (k == 0) return 1; + return n * choose(n - 1, k - 1) / k; +} + +template class ComboIterator { - static_assert(N > K, "N must be larger than K"); +private: + const std::vector &options; -public: - size_t at; - std::array bits; - std::array curr; + std::vector bits; + std::vector curr; + int at; - void inc() { - std::prev_permutation(bits.begin(), bits.end()); - for (int i = 0, k = 0; i < N; ++i) { - if (bits[i]) curr[k++] = i; + void set_curr() { + for (int i = 0, j = 0; i < bits.size(); ++i) { + if (bits[i]) curr[j++] = options[i]; } - at++; } 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); + ComboIterator(const std::vector &options, int k, int at = 0) + : options(options), bits(options.size()), curr(k), at(at) { + std::fill(bits.begin(), bits.begin() + k, true); + set_curr(); } - [[nodiscard]] bool operator==(const ComboIterator &o) const { + [[nodiscard]] bool operator==(const ComboIterator &o) const { return at == o.at; } - [[nodiscard]] bool operator!=(const ComboIterator &o) const { + [[nodiscard]] bool operator!=(const ComboIterator &o) const { return at != o.at; } @@ -40,36 +45,41 @@ public: return curr; } - const auto *operator->() const { - return &curr; + const auto &operator->() const { + return &this; } auto operator++(int) { - auto res = *this; - inc(); - return res; + std::prev_permutation(bits.begin(), bits.end()); + set_curr(); + ++at; + return *this; } auto operator++() &{ - inc(); - return *this; + auto res = *this; + (*this)++; + return res; } }; -size_t choose(size_t n, size_t k) { - if (k == 0) return 1; - return n * choose(n - 1, k - 1) / k; -} - -template +template class Combos { private: + const std::vector options; + int k; + int size; + public: - auto begin() const { - return ComboIterator(); + Combos(const std::vector &options, int k) + : options(options), k(k), size(choose(options.size(), k)) { } - auto end() const { - return ComboIterator(choose(N, K)); + ComboIterator begin() const { + return ComboIterator(options, k); + } + + ComboIterator end() const { + return ComboIterator(options, k, size); } }; diff --git a/vis/src/combotest.cpp b/vis/src/combotest.cpp index 9eb1976..6438fba 100644 --- a/vis/src/combotest.cpp +++ b/vis/src/combotest.cpp @@ -1,275 +1,15 @@ -#include -#include -#include +#include #include -#include +int main() { + auto cs = Combos({7, 2, 3}, 2); -#include + auto beg = cs.begin(); + auto end = cs.end(); -#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(); + while (beg != end) { + const auto &c = *(++beg); + for (const auto &e : c) std::cout << e << " "; + std::cout << std::endl; } } - -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; -} diff --git a/vis/src/main.cpp b/vis/src/main.cpp index fa88957..0bbeaa2 100644 --- a/vis/src/main.cpp +++ b/vis/src/main.cpp @@ -60,12 +60,6 @@ struct Drawable { } }; -float factor(unsigned index, unsigned size) { - auto num = (float) index; - auto den = size > 1 ? (float) size - 1 : 1; - return num / den; -} - Matrices build(GLFWwindow *window, float st) { int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -100,13 +94,6 @@ auto hull(const tc::Group &group, T all_sg_gens) { 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( @@ -168,16 +155,15 @@ void run(GLFWwindow *window) { auto group = tc::schlafli({5, 3, 3, 2}); -// auto wire_data = full_hull<2>(group); - - // slice_parts.erase(slice_parts.end() - 1, slice_parts.end()); auto slice_faces = hull<4>(group, (std::vector>) { {0, 1, 2}, }); + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine rand(seed); std::shuffle(slice_faces.begin(), slice_faces.end(), rand); slice_faces.erase(slice_faces.begin(), slice_faces.begin() + slice_faces.size() / 2); + auto slice_face_data = merge<4>(slice_faces); auto slice_edges = hull<4>(group, (std::vector>) { {0, 1, 3}, @@ -190,9 +176,6 @@ void run(GLFWwindow *window) { }); auto slice_edge_data = merge<4>(slice_edges); -// Drawable<2> wires(GL_LINES); -// wires.ibo.put(wire_data); - Drawable<4> edges(GL_POINTS); edges.ibo.put(slice_edge_data); edges.vao.ipointer(0, edges.ibo, 4, GL_UNSIGNED_INT); @@ -230,11 +213,6 @@ void run(GLFWwindow *window) { faces.draw_deferred(); }); -// proj_pipe.bound([&]() { -// glProgramUniform4f(sh.solid, 2, 0.3, 0.3, 0.3, 0.4); -// wires.draw_direct(); -// }); - glfwSwapInterval(2); glfwSwapBuffers(window); @@ -243,7 +221,6 @@ void run(GLFWwindow *window) { } int main(int argc, char *argv[]) { - //region init window if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return EXIT_FAILURE; @@ -265,7 +242,6 @@ int main(int argc, char *argv[]) { glfwSwapInterval(1); glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(window); - //endregion std::cout << utilInfo();