diff --git a/.gitmodules b/.gitmodules index 18e4562..ecc2720 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "vendor/glm"] path = vendor/glm url = https://github.com/g-truc/glm.git +[submodule "vendor/toddcox"] + path = vendor/toddcox + url = https://github.com/JCRaymond/toddcox-faster.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d43078..505fccf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,11 @@ project(toddcox-faster) set(CMAKE_CXX_STANDARD 17) +add_subdirectory(vendor/toddcox) add_subdirectory(vendor/glad) add_subdirectory(vendor/glfw) add_subdirectory(vendor/glm) -add_subdirectory(tc) add_subdirectory(vis) -add_subdirectory(example) + +add_subdirectory(examples) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt deleted file mode 100644 index 8d87503..0000000 --- a/example/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_executable(bench bench.cpp) -target_link_libraries(bench PRIVATE tc) - -add_executable(path path.cpp) -target_link_libraries(path PRIVATE tc) diff --git a/example/bench.cpp b/example/bench.cpp deleted file mode 100644 index 51e7a98..0000000 --- a/example/bench.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "tc/solver.h" -#include "tc/groups.h" - -#include -#include - -int main() { - std::vector groups = { - tc::group::H(2), - tc::group::H(3), - tc::group::H(4), - tc::group::T(100), - tc::group::T(500), - tc::group::T(1000), - tc::group::E(6), - tc::group::E(7), - }; - - for (const auto &group : groups) { - auto s = std::clock(); // to measure CPU time - auto cosets = tc::solve(group); - auto e = std::clock(); - - double diff = (double) (e - s) / CLOCKS_PER_SEC; - int order = cosets.len; - - std::cout << group.name << "," << order << "," << diff << std::endl; - } - - return 0; -} diff --git a/example/path.cpp b/example/path.cpp deleted file mode 100644 index 53029c0..0000000 --- a/example/path.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "tc/solver.h" -#include "tc/groups.h" - -#include -#include - -int main() { - auto cube = tc::group::B(3); - auto vars = tc::solve(cube, {}); - - for (int target = 1; target < vars.len; target++) { - auto &action = vars.path[target]; - std::cout << action.coset << " " << action.gen << " " << target << std::endl; - } - - return 0; -} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..1608af9 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(memo memotest.cpp) +target_link_libraries(memo PRIVATE tc vis-util) diff --git a/examples/memotest.cpp b/examples/memotest.cpp new file mode 100644 index 0000000..8900b02 --- /dev/null +++ b/examples/memotest.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +int main() { + tc::Group g = tc::group::B(3); + CosetMemo m(g); + + m.solve({}, {}); + m.solve({0}, {}); + m.solve({0}, {0}); + m.solve({1}, {}); + m.solve({1}, {1}); + m.solve({2}, {}); + m.solve({2}, {2}); + m.solve({0, 1}, {}); + m.solve({0, 1}, {0}); + m.solve({0, 1}, {1}); + m.solve({0, 1}, {0, 1}); + m.solve({1, 2}, {}); + m.solve({1, 2}, {1}); + m.solve({1, 2}, {2}); + m.solve({1, 2}, {1, 2}); + m.solve({0, 2}, {}); + m.solve({0, 2}, {0}); + m.solve({0, 2}, {2}); + m.solve({0, 2}, {0, 2}); + m.solve({0, 1, 2}, {}); + m.solve({0, 1, 2}, {0}); + m.solve({0, 1, 2}, {1}); + m.solve({0, 1, 2}, {2}); + m.solve({0, 1, 2}, {0, 1}); + m.solve({0, 1, 2}, {1, 2}); + m.solve({0, 1, 2}, {0, 2}); + m.solve({0, 1, 2}, {0, 1, 2}); + + tc::Group big = tc::group::B(8); + CosetMemo mbig(big); + + auto s1 = clock(); + m.solve({0, 1, 2, 3, 4, 5, 6, 7}, {}); + auto e1 = clock(); + + double t1 = (double) (e1 - s1) / (double) CLOCKS_PER_SEC; + std::cout << t1 << std::endl; + + auto s2 = clock(); + m.solve({0, 1, 2, 3, 4, 5, 6, 7}, {}); + auto e2 = clock(); + + double t2 = (double) (e2 - s2) / (double) CLOCKS_PER_SEC; + std::cout << t2 << std::endl; +} diff --git a/tc/CMakeLists.txt b/tc/CMakeLists.txt deleted file mode 100644 index b7ef511..0000000 --- a/tc/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_library(tc STATIC - src/groups.cpp - src/solver.cpp - src/cosets.cpp) - -target_include_directories(tc PUBLIC include) diff --git a/tc/include/tc/cosets.h b/tc/include/tc/cosets.h deleted file mode 100644 index 552e330..0000000 --- a/tc/include/tc/cosets.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "groups.h" -#include - -namespace tc { - struct Action { - int coset = -1; - int gen = -1; - int target = -1; - }; - - struct Cosets { - int ngens; - std::vector data; - std::vector path; - int len; - - explicit Cosets(int ngens); - - void add_row(); - - void put(int coset, int gen, int target); - - void put(int idx, int target); - - [[nodiscard]] int get(int coset, int gen) const; - - [[nodiscard]] int get(int idx) const; - - [[nodiscard]] int size() const; - }; -} \ No newline at end of file diff --git a/tc/include/tc/groups.h b/tc/include/tc/groups.h deleted file mode 100644 index 5bfad37..0000000 --- a/tc/include/tc/groups.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include - -namespace tc { - struct Rel { - std::array gens; - int mult; - }; - - /** - * A presentation of a coxeter group. Contains a number of generators and some relations of the form (ab)^n = e - */ - struct Group { - const int ngens; - std::vector> _mults; // lookup table for multiplicities - std::string name; - - explicit Group(int ngens, const std::vector &rels = {}, std::string name = "G"); - - void setmult(Rel rel); - - [[nodiscard]] Rel rel(int a, int b) const; - - [[nodiscard]] std::vector get_rels() const; - - [[nodiscard]] Group product(const Group &other) const; - - [[nodiscard]] Group power(int p) const; - - [[nodiscard]] bool trivial() const; - }; - - Group operator*(const Group &g, const Group &h); - - Group operator^(const Group &g, const int &p); - - /** - * Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c] - * @param mults: The sequence of multiplicites between adjacent generators. - */ - Group schlafli(const std::vector &mults); - - namespace group { - /** - * Simplex - */ - Group A(int dim); - - /** - * Cube, Orthoplex - */ - Group B(int dim); - - /** - * Demicube, Orthoplex - */ - Group D(int dim); - - /** - * E groups - */ - Group E(int dim); - - /** - * 24 Cell - */ - Group F4(); - - /** - * Hexagon - */ - Group G2(); - - /** - * Icosahedron - */ - Group H(int dim); - - /** - * Polygonal - */ - Group I2(int n); - - /** - * Toroidal. I2(n) * I2(m) - */ - Group T(int n, int m); - - /** - * Toroidal. T(n, n) - */ - Group T(int n); - } -} \ No newline at end of file diff --git a/tc/include/tc/solver.h b/tc/include/tc/solver.h deleted file mode 100644 index d4f8424..0000000 --- a/tc/include/tc/solver.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "cosets.h" - -namespace tc { - Cosets solve(const Group &g, const std::vector &sub_gens = {}); -} diff --git a/tc/src/cosets.cpp b/tc/src/cosets.cpp deleted file mode 100644 index 5815fa9..0000000 --- a/tc/src/cosets.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "tc/cosets.h" - -namespace tc { - Cosets::Cosets(int ngens) : ngens(ngens), len(0) { - } - - void Cosets::add_row() { - len++; - data.resize(data.size() + ngens, -1); - path.resize(path.size() + 1); - } - - void Cosets::put(int coset, int gen, int target) { - data[coset * ngens + gen] = target; - data[target * ngens + gen] = coset; - - if (path[target].coset == -1) { - path[target] = {coset, gen, target}; - } - } - - void Cosets::put(int idx, int target) { - int coset = idx / ngens; - int gen = idx % ngens; - data[idx] = target; - data[target * ngens + gen] = coset; - - if (path[target].coset == -1) { - path[target] = {coset, gen, target}; - } - } - - int Cosets::get(int coset, int gen) const { - return data[coset * ngens + gen]; - } - - int Cosets::get(int idx) const { - return data[idx]; - } - - int Cosets::size() const { - return len; - } -} \ No newline at end of file diff --git a/tc/src/groups.cpp b/tc/src/groups.cpp deleted file mode 100644 index b1896d4..0000000 --- a/tc/src/groups.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "tc/groups.h" - -#include -#include - -namespace tc { - Group::Group(int ngens, const std::vector &rels, std::string name) : ngens(ngens), name(std::move(name)) { - _mults.resize(ngens); - for (int i = 0; i < ngens; i++) { - _mults[i].resize(ngens, 2); - } - - for (Rel rel : rels) { - setmult(rel); - } - } - - void Group::setmult(Rel rel) { - _mults[rel.gens[0]][rel.gens[1]] = rel.mult; - _mults[rel.gens[1]][rel.gens[0]] = rel.mult; - } - - Rel Group::rel(int a, int b) const { - return {a, b, _mults[a][b]}; - } - - std::vector Group::get_rels() const { - std::vector rels; - for (int i = 0; i < ngens - 1; i++) { - for (int j = i + 1; j < ngens; j++) { - rels.push_back({i, j, _mults[i][j]}); - } - } - return rels; - } - - Group Group::product(const Group &other) const { - int off = ngens; - - Group g(ngens + other.ngens, get_rels()); - - for (Rel rel : other.get_rels()) { - g.setmult({off + rel.gens[0], off + rel.gens[1], rel.mult}); - } - - std::stringstream ss; - ss << name << "*" << other.name; - g.name = ss.str(); - - return g; - } - - Group Group::power(int p) const { - Group g(ngens * p); - - for (Rel rel : get_rels()) { - for (int off = 0; off < g.ngens; off += ngens) { - g.setmult({off + rel.gens[0], off + rel.gens[1], rel.mult}); - } - } - - std::stringstream ss; - ss << name << "^" << p; - g.name = ss.str(); - - return g; - } - - bool Group::trivial() const { - for (int i = 0; i < ngens; ++i) { - for (int j = 0; j < ngens; ++j) { - if (_mults[i][j] != 2) { - return false; - } - } - } - - return true; - } - - Group operator*(const Group &g, const Group &h) { - return g.product(h); - } - - Group operator^(const Group &g, const int &p) { - return g.power(p); - } - - Group schlafli(const std::vector &mults, const std::string &name) { - int ngens = (int) mults.size() + 1; - - Group g(ngens, {}, name); - - for (int i = 0; i < (int) mults.size(); i++) { - g.setmult({i, i + 1, mults[i]}); - } - - return g; - } - - Group schlafli(const std::vector &mults) { - std::stringstream ss; - ss << "["; - if (!mults.empty()) { - copy(mults.begin(), mults.end() - 1, std::ostream_iterator(ss, ",")); - ss << mults.back(); - } - ss << "]"; - - return schlafli(mults, ss.str()); - } - - namespace group { - Group A(const int dim) { - if (dim == 0) - return Group(0, {}, "A(0)"); - - const std::vector &mults = std::vector(dim - 1, 3); - - std::stringstream ss; - ss << "A(" << dim << ")"; - - return schlafli(mults, ss.str()); - } - - Group B(const int dim) { - std::vector mults(dim - 1, 3); - mults[0] = 4; - - std::stringstream ss; - ss << "B(" << dim << ")"; - - return schlafli(mults, ss.str()); - } - - Group D(const int dim) { - std::vector mults(dim - 1, 3); - mults[dim - 2] = 2; - Group g = schlafli(mults); - g.setmult({1, dim - 1, 3}); - - std::stringstream ss; - ss << "D(" << dim << ")"; - g.name = ss.str(); - - return g; - } - - Group E(const int dim) { - std::vector mults(dim - 1, 3); - mults[dim - 2] = 2; - Group g = schlafli(mults); - g.setmult({2, dim - 1, 3}); - - std::stringstream ss; - ss << "E(" << dim << ")"; - g.name = ss.str(); - - return g; - } - - Group F4() { - return schlafli({3, 4, 3}, "F4"); - } - - Group G2() { - return schlafli({6}, "G2"); - } - - Group H(const int dim) { - std::vector mults(dim - 1, 3); - mults[0] = 5; - - std::stringstream ss; - ss << "H(" << dim << ")"; - - return schlafli(mults, ss.str()); - } - - Group I2(const int n) { - std::stringstream ss; - ss << "I2(" << n << ")"; - - return schlafli({n}, ss.str()); - } - - Group T(const int n, const int m) { - Group g = I2(n) * I2(m); - - std::stringstream ss; - ss << "T(" << n << "," << m << ")"; - g.name = ss.str(); - - return g; - } - - Group T(const int n) { - Group g = I2(n) ^2; - - std::stringstream ss; - ss << "T(" << n << ")"; - g.name = ss.str(); - - return g; - } - } -} \ No newline at end of file diff --git a/tc/src/solver.cpp b/tc/src/solver.cpp deleted file mode 100644 index f03ae21..0000000 --- a/tc/src/solver.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "tc/solver.h" - -#include - -namespace tc { - struct RelTable { - Rel rel; - - std::vector lst_ptr; - std::vector gen; - - int &mult = rel.mult; - std::array &gens = rel.gens; - - explicit RelTable(Rel rel) : rel(rel) { - } - - int add_row() { - int idx = lst_ptr.size(); - lst_ptr.push_back(nullptr); - gen.push_back(-1); - return idx; - } - }; - - struct RelationSet { - const Cosets &cosets; - - std::vector tables; - std::vector> gen_map; // which relations involve which generators - - explicit RelationSet(const Group &g, const Cosets &cosets) : gen_map(g.ngens), cosets(cosets) { - const std::vector &rels = g.get_rels(); - tables.reserve(rels.size()); - for (const auto &rel : rels) { - RelTable &table = tables.emplace_back(rel); - gen_map[rel.gens[0]].push_back(&table); - gen_map[rel.gens[1]].push_back(&table); - } - } - - void add_row() { - for (auto &table : tables) { - table.add_row(); - } - } - - void fill_row(int idx) { - for (auto &table : tables) { - if (table.lst_ptr[idx] != nullptr) continue; - - table.lst_ptr[idx] = new int; - - if ((cosets.get(idx, table.gens[0]) != idx) and - (cosets.get(idx, table.gens[1]) != idx)) { - table.gen[idx] = 0; - } else { - table.gen[idx] = -1; - } - } - } - }; - - Cosets solve(const Group &group, const std::vector &sub_gens) { - Cosets cosets(group.ngens); - cosets.add_row(); - for (const auto &i : sub_gens) { - cosets.put(0, i, 0); - } - - RelationSet rels(group, cosets); - rels.add_row(); - rels.fill_row(0); - - int idx = 0; - int coset, gen, target, fact_idx, lst, gen_; - while (true) { - while (idx < cosets.data.size() and cosets.get(idx) >= 0) - idx++; - - if (idx == cosets.data.size()) - break; - - target = cosets.len; - - cosets.add_row(); - rels.add_row(); - - std::vector facts = {idx}; - - while (!facts.empty()) { - fact_idx = facts.back(); - facts.pop_back(); - - if (cosets.get(fact_idx) != -1) - continue; - - cosets.put(fact_idx, target); - - coset = fact_idx / group.ngens; - gen = fact_idx % group.ngens; - - for (RelTable *pTable : rels.gen_map[gen]) { - RelTable &table = *pTable; - - if (table.lst_ptr[target] == nullptr) { - table.lst_ptr[target] = table.lst_ptr[coset]; - table.gen[target] = table.gen[coset] + 1; - - if (table.gen[coset] < 0) - table.gen[target] -= 2; - - if (table.gen[target] == table.rel.mult) { - lst = *(table.lst_ptr[target]); - delete table.lst_ptr[target]; - gen_ = table.gens[table.gens[0] == gen]; - facts.push_back(lst * group.ngens + gen_); - } else if (table.gen[target] == -table.mult) { - gen_ = table.gens[table.gens[0] == gen]; - facts.push_back(target * group.ngens + gen_); - } else if (table.gen[target] == table.mult - 1) { - *(table.lst_ptr[target]) = target; - } - } - } - - std::sort(facts.begin(), facts.end(), std::greater<>()); - } - - rels.fill_row(target); - } - - return cosets; - } -} \ No newline at end of file diff --git a/vendor/toddcox b/vendor/toddcox new file mode 160000 index 0000000..4fd22f3 --- /dev/null +++ b/vendor/toddcox @@ -0,0 +1 @@ +Subproject commit 4fd22f343ec17192bbab112d14faffa4a5e00aa6 diff --git a/vis/CMakeLists.txt b/vis/CMakeLists.txt index 9b9faae..488387d 100644 --- a/vis/CMakeLists.txt +++ b/vis/CMakeLists.txt @@ -10,3 +10,6 @@ add_custom_command( ) add_dependencies(vis shaders) + +add_library(vis-util INTERFACE) +target_include_directories(vis-util INTERFACE include) diff --git a/vis/include/geometry.hpp b/vis/include/geometry.hpp new file mode 100644 index 0000000..4775a64 --- /dev/null +++ b/vis/include/geometry.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +size_t key(const std::vector &gens) { + size_t bits = 0; + for (const auto &gen : gens) { + bits |= 1U << gen; + } + return bits; +} + +struct CosetMemo { + const tc::Group &parent; + std::vector>> results; + + explicit CosetMemo(const tc::Group &parent) + : parent(parent) { + size_t W = std::pow(2, parent.ngens); + + for (size_t i = 0; i < W; ++i) { + results.emplace_back(W, std::nullopt); + } + } + + tc::Cosets solve(const std::vector &group_gens, const std::vector &sub_gens) { + size_t group_key = key(group_gens); + size_t sub_key = key(sub_gens); + + if (!results[group_key][sub_key]) { + results[group_key][sub_key] = parent.subgroup(group_gens).solve(sub_gens); + } + + return results[group_key][sub_key].value(); + } +}; diff --git a/vis/include/geom.h b/vis/include/mirror.hpp similarity index 95% rename from vis/include/geom.h rename to vis/include/mirror.hpp index 153ad36..948f360 100644 --- a/vis/include/geom.h +++ b/vis/include/mirror.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -27,7 +27,7 @@ std::vector mirror(const tc::Group &group) { glm::vec4 vp{}; for (int m = 0; m < p; ++m) { glm::vec4 vq = mirrors[m]; - vp[m] = (cos(M_PI / group.rel(p, m).mult) - dot(m, vp, vq)) / vq[m]; + vp[m] = (cos(M_PI / group.get(p, m)) - dot(m, vp, vq)) / vq[m]; } vp[p] = std::sqrt(1 - glm::dot(vp, vp)); diff --git a/vis/include/util.hpp b/vis/include/util.hpp new file mode 100644 index 0000000..260f6d6 --- /dev/null +++ b/vis/include/util.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +#include + +void utilShaderSource(GLuint shader, const std::vector &sources) { + char const *ptrs[sources.size()]; + for (size_t i = 0; i < sources.size(); ++i) { + ptrs[i] = sources[i].c_str(); + } + glShaderSource(shader, sources.size(), ptrs, nullptr); +} + +std::string utilShaderInfoLog(GLuint shader) { + int len; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); + char buffer[len]; + glGetShaderInfoLog(shader, len, nullptr, buffer); + return std::string(buffer); +} + +std::string utilProgramInfoLog(GLuint program) { + int len; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); + char buffer[len]; + glGetProgramInfoLog(program, len, nullptr, buffer); + return std::string(buffer); +} + +std::string utilInfo() { + std::stringstream ss; + ss + << "Graphics Information:" << std::endl + << " Vendor: " << glGetString(GL_VENDOR) << std::endl + << " Renderer: " << glGetString(GL_RENDERER) << std::endl + << " OpenGL version: " << glGetString(GL_VERSION) << std::endl + << " Shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + return ss.str(); +} \ No newline at end of file diff --git a/vis/src/main.cpp b/vis/src/main.cpp index 32dccd9..ff10aca 100644 --- a/vis/src/main.cpp +++ b/vis/src/main.cpp @@ -2,106 +2,24 @@ #include #include -#include -#include - -#include "geom.h" - #include #include +#include + +#include "util.hpp" +#include "mirror.hpp" +#include "geometry.hpp" + #ifdef _WIN32 extern "C" { __attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001; } #endif -void utilShaderSource(GLuint shader, const std::vector &sources) { - char const *ptrs[sources.size()]; - for (size_t i = 0; i < sources.size(); ++i) { - ptrs[i] = sources[i].c_str(); - } - glShaderSource(shader, sources.size(), ptrs, nullptr); -} - -std::string utilShaderInfoLog(GLuint shader) { - int len; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); - char buffer[len]; - glGetShaderInfoLog(shader, len, nullptr, buffer); - return std::string(buffer); -} - -std::string utilProgramInfoLog(GLuint program) { - int len; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); - char buffer[len]; - glGetProgramInfoLog(program, len, nullptr, buffer); - return std::string(buffer); -} - - -template -tc::Group shrink(const tc::Group &g, const std::array &sub) { - tc::Group h(D); - for (int i = 0; i < D; ++i) { - for (int j = 0; j < D; ++j) { - h.setmult({i, j, g.rel(sub[i], sub[j]).mult}); - } - } - return h; -} - -template -std::vector raise( - const tc::Cosets &g_res, - const tc::Cosets &h_res, - const std::array &gen_map, - const std::vector &path -) { - std::vector res(path.size(), 0); - for (size_t i = 1; i < path.size(); ++i) { - auto action = h_res.path[path[i]]; - - res[i] = g_res.get(res[action.coset], gen_map[action.gen]); - } - return res; -} - -std::vector targets(const std::vector &path) { - std::vector res(path.size(), 0); - for (size_t i = 0; i < path.size(); ++i) { - res[i] = path[i].target; - } - return res; -} - -std::vector tile(const tc::Cosets &map, std::vector geom) { - int K = geom.size(); - geom.resize(K * map.size()); - for (int i = 1; i < map.size(); ++i) { // tile - auto gaction = map.path[i]; - for (int j = 0; j < K; ++j) { - geom[i * K + j] = map.get(geom[gaction.coset * K + j], gaction.gen); - } - } - return geom; -} - -template -std::vector build(const tc::Group &g, const std::array &sub) { - tc::Group h = shrink(g, sub); - auto hres = tc::solve(h); // recursion would happen here - - auto gres = tc::solve(g); - std::vector geom = targets(hres.path); - geom = raise(gres, hres, sub, geom); - - return tile(gres, geom); -} - - int main(int argc, char *argv[]) { + //region init window + if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return EXIT_FAILURE; @@ -122,46 +40,12 @@ int main(int argc, char *argv[]) { gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); glfwSwapInterval(0); - std::cout - << "Graphics Information:" << std::endl - << " Vendor: " << glGetString(GL_VENDOR) << std::endl - << " Renderer: " << glGetString(GL_RENDERER) << std::endl - << " OpenGL version: " << glGetString(GL_VERSION) << std::endl - << " Shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + //endregion - auto group = tc::group::B(2); - auto res = tc::solve(group); - auto mirrors = mirror(group); - auto corners = plane_intersections(mirrors); - - auto points = std::vector(res.size()); - points[0] = barycentric(corners, {1.00f, 0.50f, 0.50f, 0.50f}); - for (int i = 1; i < res.size(); ++i) { - auto action = res.path[i]; - points[i] = reflect(points[action.coset], mirrors[action.gen]); - } - - auto h = shrink<2>(group, {0, 1}); - auto i = shrink<1>(h, {0}); - - auto g_map = res; - auto h_map = tc::solve(h); - auto i_map = tc::solve(i); - - auto g0 = targets(i_map.path); - g0 = raise<1>(h_map, i_map, {0}, g0); - g0 = tile(h_map, g0); - g0 = raise<2>(g_map, h_map, {0, 1}, g0); - -// auto g0 = build<2>(group, {0}); -// auto g1 = build<2>(group, {1}); -// auto g2 = build<2>(group, {2}); -// auto g3 = build<2>(group, {3}); - - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - utilShaderSource(vs, { - "#version 430\n", + std::cout << utilInfo(); + const std::string VS_SOURCE = + "#version 430\n" "layout(location=0) uniform mat4 proj;" "layout(location=1) uniform mat4 view;" "" @@ -175,14 +59,10 @@ int main(int argc, char *argv[]) { // " gl_Position = proj * vec4(vpos.xyz / (1), 1);" " gl_Position = proj * vec4(vpos.xyz / (1 - vpos.w), 1);" " gl_PointSize = 5;" - "}" - }); - glCompileShader(vs); - - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - utilShaderSource(fs, { - "#version 430\n", + "}"; + const std::string FS_SOURCE = + "#version 430\n" "layout(location=2) uniform vec3 c;" "" "in vec4 vpos;" @@ -192,8 +72,15 @@ int main(int argc, char *argv[]) { "void main() {" " float d = smoothstep(-2, 2, vpos.z);" " color = vec4(c * d, 1);" - "}" - }); + "}"; + + //region init shaders + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + utilShaderSource(vs, {VS_SOURCE}); + glCompileShader(vs); + + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + utilShaderSource(fs, {FS_SOURCE}); GLuint pgm = glCreateProgram(); glAttachShader(pgm, vs); @@ -218,6 +105,15 @@ int main(int argc, char *argv[]) { glfwTerminate(); return EXIT_FAILURE; } + //endregion + + auto group = tc::group::B(4); + auto res = group.solve(); + auto mirrors = mirror(group); + auto corners = plane_intersections(mirrors); + + auto start = barycentric(corners, {1.00f, 0.50f, 0.50f, 0.50f}); + auto points = res.path.walk(start, mirrors, reflect); GLuint vbo; glGenBuffers(1, &vbo); @@ -227,27 +123,11 @@ int main(int argc, char *argv[]) { glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); - GLuint ibo0; - glGenBuffers(1, &ibo0); - glBindBuffer(GL_ARRAY_BUFFER, ibo0); - glBufferData(GL_ARRAY_BUFFER, sizeof(int) * g0.size(), &g0[0], GL_STATIC_DRAW); - -// GLuint ibo1; -// glGenBuffers(1, &ibo1); -// glBindBuffer(GL_ARRAY_BUFFER, ibo1); -// glBufferData(GL_ARRAY_BUFFER, sizeof(int) * g1.size(), &g1[0], GL_STATIC_DRAW); -// -// GLuint ibo2; -// glGenBuffers(1, &ibo2); -// glBindBuffer(GL_ARRAY_BUFFER, ibo2); -// glBufferData(GL_ARRAY_BUFFER, sizeof(int) * g2.size(), &g2[0], GL_STATIC_DRAW); -// -// GLuint ibo3; -// glGenBuffers(1, &ibo3); -// glBindBuffer(GL_ARRAY_BUFFER, ibo3); -// glBufferData(GL_ARRAY_BUFFER, sizeof(int) * g3.size(), &g3[0], GL_STATIC_DRAW); - while (!glfwWindowShouldClose(window)) { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + glViewport(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(pgm); @@ -255,9 +135,7 @@ int main(int argc, char *argv[]) { glEnable(GL_POINT_SMOOTH); glEnable(GL_DEPTH_TEST); - int width, height; - glfwGetFramebufferSize(window, &width, &height); - glViewport(0, 0, width, height); + //region uniforms auto aspect = (float) width / (float) height; auto pheight = 1.4f; auto pwidth = aspect * pheight; @@ -270,27 +148,11 @@ int main(int argc, char *argv[]) { view = glm::rotate(view, t / 3, glm::vec3(0, 0, 1)); view = glm::rotate(view, t / 4, glm::vec3(1, 0, 0)); glUniformMatrix4fv(1, 1, false, glm::value_ptr(view)); + //endregion glUniform3f(2, 1.0f, 1.0f, 1.0f); glDrawArrays(GL_POINTS, 0, points.size()); - glLineWidth(2.0f); - glUniform3f(2, 1.0f, 0.0f, 0.0f); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo0); - glDrawElements(GL_LINES, g0.size(), GL_UNSIGNED_INT, nullptr); - -// glUniform3f(2, 0.0f, 1.0f, 0.0f); -// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo1); -// glDrawElements(GL_LINES, g1.size(), GL_UNSIGNED_INT, nullptr); -// -// glUniform3f(2, 0.0f, 0.0f, 1.0f); -// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo2); -// glDrawElements(GL_LINES, g2.size(), GL_UNSIGNED_INT, nullptr); -// -// glUniform3f(2, 0.7f, 0.7f, 0.0f); -// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo3); -// glDrawElements(GL_LINES, g3.size(), GL_UNSIGNED_INT, nullptr); - glfwSwapBuffers(window); glfwPollEvents();