diff --git a/.idea/misc.xml b/.idea/misc.xml index 2edf9aa..e8c6c13 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -12,4 +12,7 @@ - + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..10a684a --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# toddcox-visualize +A new (basic) implementation of the Todd-Coxeter algorithm for Coxeter groups in C++ that beats GAP. + +--- + +Example output with group F4. + +![Example render](screen.png) + diff --git a/screen.png b/screen.png new file mode 100644 index 0000000..61a5d8f Binary files /dev/null and b/screen.png differ diff --git a/vis/include/util.hpp b/vis/include/util.hpp index f038e0c..0019c21 100644 --- a/vis/include/util.hpp +++ b/vis/include/util.hpp @@ -11,18 +11,21 @@ class gl_error : public std::domain_error { public: explicit gl_error(const std::string &arg) : domain_error(arg) {} + explicit gl_error(const char *string) : domain_error(string) {} }; class shader_error : public gl_error { public: explicit shader_error(const std::string &arg) : gl_error(arg) {} + explicit shader_error(const char *string) : gl_error(string) {} }; class program_error : public gl_error { public: explicit program_error(const std::string &arg) : gl_error(arg) {} + explicit program_error(const char *string) : gl_error(string) {} }; @@ -102,4 +105,4 @@ GLuint utilLinkProgram(const std::vector &shaders) { if (success)return program; throw program_error(utilProgramInfoLog(program)); -} \ No newline at end of file +} diff --git a/vis/shaders/stereo-proper.gm.glsl b/vis/shaders/stereo-proper.gm.glsl new file mode 100644 index 0000000..a2fd50c --- /dev/null +++ b/vis/shaders/stereo-proper.gm.glsl @@ -0,0 +1,25 @@ +#version 430 + +#define SUBS 20 + +layout(lines) in; +layout(line_strip, max_vertices = SUBS) out; + +layout(location=0) uniform mat4 proj; + +in vec4 gpos[]; +out vec4 vpos; + +vec4 stereo(vec4 v) { + return vec4(v.xyz / (1 - v.w), 1); +} + +void main() { + for (int i = 0; i < SUBS; i++) { + vpos = mix(gpos[0], gpos[1], i * 1.0f / (SUBS - 1)); + vpos = normalize(vpos); + gl_Position = proj * stereo(vpos); + EmitVertex(); + } + EndPrimitive(); +} diff --git a/vis/shaders/stereo-proper.vs.glsl b/vis/shaders/stereo-proper.vs.glsl new file mode 100644 index 0000000..c286c7e --- /dev/null +++ b/vis/shaders/stereo-proper.vs.glsl @@ -0,0 +1,12 @@ +#version 430 + +layout(location=1) uniform mat4 view; + +layout(location=0) in vec4 pos; + +out vec4 gpos; + +void main() { + gpos = view * pos; + gl_PointSize = 5; +} diff --git a/vis/shaders/stereo.vs.glsl b/vis/shaders/stereo.vs.glsl index c67588e..3829473 100644 --- a/vis/shaders/stereo.vs.glsl +++ b/vis/shaders/stereo.vs.glsl @@ -11,5 +11,5 @@ void main() { int i = gl_VertexID; vpos = view * pos; gl_Position = proj * vec4(vpos.xyz / (1 - vpos.w), 1); - gl_PointSize = 5; + gl_PointSize = 5 * smoothstep(-2, 2, gl_Position.z); } diff --git a/vis/src/main.cpp b/vis/src/main.cpp index b9665c1..0fffb67 100644 --- a/vis/src/main.cpp +++ b/vis/src/main.cpp @@ -17,6 +17,27 @@ __attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x000000 } #endif +std::vector edge_inds(const tc::Group &group, const tc::Cosets &map, const int gen) { + const tc::SubGroup &eg = group.subgroup({gen}); + const tc::Cosets &root = eg.solve({}); + size_t N = root.size(); + + auto edges = root.path.walk(0, eg.gen_map, [map](int a, int gen) { + return map.get(a, gen); + }); + const tc::Cosets &tile = group.solve({gen}); + + edges.resize(N * tile.size()); + for (size_t i = 0; i < tile.size(); ++i) { + auto act = tile.path.get(i); + for (size_t j = 0; j < N; ++j) { + edges[i * N + j] = map.get(edges[act.from_idx * N + j], act.gen); + } + } + + return edges; +} + int main(int argc, char *argv[]) { //region init window @@ -47,22 +68,34 @@ int main(int argc, char *argv[]) { GLuint pgm; try { - GLuint vs = utilCompileFiles(GL_VERTEX_SHADER, {"shaders/ortho.vs.glsl"}); - GLuint fs = utilCompileFiles(GL_FRAGMENT_SHADER, {"shaders/w-axis-hue.fs.glsl"}); +// GLuint vs = utilCompileFiles(GL_VERTEX_SHADER, {"shaders/ortho.vs.glsl"}); +// GLuint vs = utilCompileFiles(GL_VERTEX_SHADER, {"shaders/stereo.vs.glsl"}); +// GLuint fs = utilCompileFiles(GL_FRAGMENT_SHADER, {"shaders/one-color.fs.glsl"}); +// GLuint fs = utilCompileFiles(GL_FRAGMENT_SHADER, {"shaders/w-axis-hue.fs.glsl"}); - pgm = utilLinkProgram({vs, fs}); +// pgm = utilLinkProgram({vs, fs}); + + pgm = utilLinkProgram({ + utilCompileFiles(GL_VERTEX_SHADER, {"shaders/stereo-proper.vs.glsl"}), + utilCompileFiles(GL_GEOMETRY_SHADER, {"shaders/stereo-proper.gm.glsl"}), + utilCompileFiles(GL_FRAGMENT_SHADER, {"shaders/one-color.fs.glsl"}), + }); } catch (const gl_error &e) { std::cerr << e.what() << std::endl; glfwTerminate(); exit(EXIT_FAILURE); } - auto group = tc::group::H(4); + auto group = tc::group::F4(); +// auto group = tc::group::D(4); +// auto group = tc::group::H(4); auto res = group.solve(); auto mirrors = mirror(group); auto corners = plane_intersections(mirrors); - auto start = barycentric(corners, {1.00, 1.00, 1.00, 1.00}); +// auto start = barycentric(corners, {1.00f, 1.00f, 1.00f, 1.00f}); + auto start = barycentric(corners, {0.05, 0.05, 1.00, 3.00}); +// auto start = barycentric(corners, {0, 0, 0, 1}); auto points = res.path.walk(start, mirrors, reflect); GLuint vbo; @@ -73,6 +106,21 @@ int main(int argc, char *argv[]) { glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); + std::vector edge_count; + std::vector edge_ibo; + for (int i = 0; i < group.ngens; ++i) { + const auto data = edge_inds(group, res, i); + edge_count.push_back(data.size()); + + GLuint ibo; + glGenBuffers(1, &ibo); + glBindBuffer(GL_ARRAY_BUFFER, ibo); + glBufferData(GL_ARRAY_BUFFER, sizeof(int) * data.size(), &data[0], GL_STATIC_DRAW); + edge_ibo.push_back(ibo); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + while (!glfwWindowShouldClose(window)) { int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -89,10 +137,11 @@ int main(int argc, char *argv[]) { auto aspect = (float) width / (float) height; auto pheight = 1.4f; auto pwidth = aspect * pheight; - glm::mat4 proj = glm::ortho(-pwidth, pwidth, -pheight, pheight, -100.0f, 100.0f); + glm::mat4 proj = glm::ortho(-pwidth, pwidth, -pheight, pheight, -2.0f, 2.0f); +// glm::mat4 proj = glm::ortho(-pwidth, pwidth, -pheight, pheight, -100.0f, 100.0f); glUniformMatrix4fv(0, 1, false, glm::value_ptr(proj)); - auto t = (float) glfwGetTime() / 5; + auto t = (float) glfwGetTime() / 10; auto view = glm::identity(); view *= utilRotate(0, 1, t * 0.7f); view *= utilRotate(0, 2, t * 0.8f); @@ -106,6 +155,15 @@ int main(int argc, char *argv[]) { glUniform3f(2, 1.0f, 1.0f, 1.0f); glDrawArrays(GL_POINTS, 0, points.size()); + glUniform3f(2, 1.0f, 1.0f, 1.0f); + for (int i = 0; i < group.ngens; ++i) { + auto ibo = edge_ibo[i]; + auto count = edge_count[i]; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + glDrawElements(GL_LINES, count, GL_UNSIGNED_INT, nullptr); + } + glfwSwapBuffers(window); glfwPollEvents();