1 Commits

Author SHA1 Message Date
0afd905051 Create README.md 2020-01-04 02:09:56 -05:00
23 changed files with 708 additions and 674 deletions

View File

@@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.13)
project(vis-cosets)
set(CMAKE_CXX_STANDARD 17)
@@ -15,10 +14,3 @@ option(GLM_TEST_ENABLE OFF)
add_subdirectory(vendor/glm)
add_subdirectory(cosets)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif ()
set(CMAKE_CXX_FLAGS_DEBUG "-O2")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# vis-cosets
Features being merged into https://github.com/JCRaymond/toddcox-faster. Favor that instead.

View File

@@ -1,3 +1,5 @@
project(cosets)
add_custom_target(shaders ALL DEPENDS shader_output)
add_custom_command(
OUTPUT shader_output
@@ -5,16 +7,17 @@ add_custom_command(
COMMENT "copying shaders"
)
add_executable(cosets
src/main.cpp
src/util/files.cpp
src/util/numeric.cpp
src/util/shader.cpp
src/util/window.cpp)
target_include_directories(cosets PRIVATE include)
add_executable(${PROJECT_NAME}
src/main.cpp)
add_dependencies(cosets shaders)
target_link_libraries(cosets
target_link_libraries(${PROJECT_NAME}
PRIVATE glad glm glfw)
target_compile_options(${PROJECT_NAME} PRIVATE -O3)
add_executable(coxeter src/coxeter.cpp)
add_executable(mirror src/mirrors.cpp)
target_link_libraries(mirror PRIVATE glm)
add_executable(mesh src/mesh.cpp)
target_link_libraries(mesh PRIVATE glm)

View File

@@ -1,194 +0,0 @@
#pragma once
#include <map>
#include <vector>
#include <algorithm>
struct Mults;
struct Table;
struct IRow;
struct Mults {
const int dim;
std::map<std::tuple<int, int>, int> mults;
explicit Mults(const int dim) : dim(dim) {
mults = std::map<std::tuple<int, int>, int>();
}
void set(int a, int b, int mult) {
if (a > b) std::swap(a, b);
mults[std::make_tuple(a, b)] = mult;
}
[[nodiscard]] int get(int a, int b) const {
if (a == b) return 1;
if (a > b) std::swap(a, b);
const auto &tup = std::make_tuple(a, b);
const auto &res = mults.find(tup);
if (res == mults.end()) return 2;
return res->second;
}
[[nodiscard]] std::vector<int> irelation(int a, int b) const {
std::vector<int> res{};
int mult = get(a, b);
for (int i = 0; i < mult; ++i) {
res.push_back(a);
res.push_back(b);
}
return res;
}
[[nodiscard]] Mults sub(const std::vector<int> &igens) const {
Mults res(igens.size());
for (int a = 0; a < (int) igens.size(); ++a) {
for (int b = a + 1; b < (int) igens.size(); ++b) {
res.set(a, b, get(igens[a], igens[b]));
}
}
return res;
}
[[nodiscard]] Table *isolve(const std::vector<int> &isubgens) const;
};
struct Table {
const Mults mults;
std::vector<std::vector<int>> fwd;
explicit Table(Mults mults) : mults(mults) {
add_row();
}
void add_row() {
fwd.emplace_back(mults.dim, -1);
}
int add_coset() {
for (int from = 0; from < (int) size(); ++from) {
for (int igen = 0; igen < (int) mults.dim; igen++) {
if (iget(from, igen) < 0) {
int to = (int) size();
add_row();
iset(from, igen, to);
return to;
}
}
}
return 0;
}
[[nodiscard]] unsigned size() const {
return fwd.size();
}
void iset(int from, int igen, int to) {
fwd[from][igen] = to;
fwd[to][igen] = from;
}
[[nodiscard]] int iget(int from, int igen) const {
return fwd[from][igen];
}
[[nodiscard]] int irget(int igen, int to) const {
return fwd[to][igen];
}
};
struct IRow {
std::vector<int>::const_iterator l;
std::vector<int>::const_iterator r;
int from;
int to;
IRow(const std::vector<int> &rel, int cos)
: l(rel.begin()), r(rel.end() - 1), from(cos), to(cos) {
}
[[nodiscard]] bool learn(Table *table) {
if (r - l == 0) {
return false;
}
while (r - l > 0) {
int next = table->iget(from, *l);
if (next < 0) break;
l++;
from = next;
}
while (r - l > 0) {
int next = table->irget(*r, to);
if (next < 0) break;
r--;
to = next;
}
if (r - l == 0) {
table->iset(from, *l, to);
return true;
}
return false;
}
};
Mults schlafli(const std::vector<int> &symbol) {
unsigned int dim = symbol.size();
Mults mults(dim + 1);
for (int i = 0; i < dim; ++i) {
mults.set(i, i + 1, symbol[i]);
}
return mults;
}
Table *Mults::isolve(const std::vector<int> &isubgens) const {
auto *table = new Table(*this);
for (int igen : isubgens)
table->iset(0, igen, 0);
std::vector<std::vector<int>> irels{};
for (unsigned a = 0; a < dim; ++a) {
for (unsigned b = a + 1; b < dim; ++b) {
irels.push_back(irelation(a, b));
}
}
std::vector<IRow> irows;
irows.reserve(irels.size());
for (const auto &irel : irels)
irows.emplace_back(irel, 0);
while (!irows.empty()) {
while (true) {
bool learned = false;
for (int i = (int) irows.size() - 1; i >= 0; i--) {
if (irows[i].learn(table)) {
learned = true;
irows.erase(irows.begin() + i);
}
}
if (!learned)
break;
}
int i = (int) table->size();
if (table->add_coset() > 0) {
for (const auto &irel : irels)
irows.emplace_back(irel, i);
} else {
break;
}
}
return table;
}

View File

@@ -1,5 +0,0 @@
#pragma once
#include <string>
std::string read_all_text(const std::string &file);

View File

@@ -1,135 +0,0 @@
#pragma once
#include <vector>
#include <chrono>
#include <iostream>
#include "coxeter.hpp"
#include "mirrors.hpp"
#include "numeric.hpp"
glm::vec4 identity(const std::vector<glm::vec4> &normals, const std::vector<float> &coords) {
const std::vector<glm::vec4> corners = plane_intersections(normals);
const glm::vec4 identity = barycentric(corners, coords);
return glm::normalize(identity);
}
glm::vec4 identity(const Mults &mults, const std::vector<float> &coords) {
const std::vector<glm::vec4> normals = mirror(mults);
return identity(normals, coords);
}
glm::vec4 center(const Mults &mults) {
const std::vector<glm::vec4> normals = mirror(mults);
const std::vector<glm::vec4> corners = plane_intersections(normals);
std::vector<float> coords{};
for (int i = 0; i < corners.size(); ++i) {
const auto u = (i + 2) % corners.size();
const auto v = (i + 1) % corners.size();
const auto &d = corners[u] - corners[v];
coords.push_back(glm::length(d));
}
const glm::vec4 identity = barycentric(corners, coords);
return glm::normalize(identity);
}
struct Buffer {
GLuint name = 0;
unsigned size = 0;
};
struct Mesh {
const Mults mults;
const Table *t_vert;
const std::vector<glm::vec4> normals;
glm::vec4 *vert_data;
Buffer vert;
Buffer edge;
Buffer face;
explicit Mesh(const Mults &mults) : mults(mults), normals(mirror(mults)) {
auto a = std::chrono::high_resolution_clock::now();
t_vert = mults.isolve({});
auto b = std::chrono::high_resolution_clock::now();
auto delta = (std::chrono::duration<double>) (b - a);
std::cout << "time to solve verts: " << delta.count() << std::endl;
vert.size = t_vert->size();
vert_data = new glm::vec4[vert.size];
glGenBuffers(1, &vert.name);
glGenBuffers(1, &edge.name);
glGenBuffers(1, &face.name);
gen_indices();
}
void gen_vertices(const glm::vec4 root) {
auto a = std::chrono::high_resolution_clock::now();
vert_data[0] = root;
for (unsigned from = 0; from < vert.size; ++from) {
for (unsigned gen = 0; gen < mults.dim; ++gen) {
int to = t_vert->iget((int) from, (int) gen);
vert_data[to] = reflect(vert_data[from], normals[gen]);
}
}
auto b = std::chrono::high_resolution_clock::now();
auto delta = (std::chrono::duration<double>) (b - a);
std::cout << "time to build verts: " << delta.count() << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, vert.name);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * vert.size, vert_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void gen_indices() {
std::vector<int> edge_data;
auto e_table = mults.sub({0, 1}).isolve({});
// std::cout << "building gens" << std::endl;
// const std::vector<int> gens{0, 1};
// std::cout << "built gens" << std::endl;
// const std::vector<int> &igens = gens;
// Mults<2> res{};
// for (int a = 0; a < 2; ++a) {
// for (int b = a + 1; b < 2; ++b) {
// res.set(a, b, t_vert->mults.get(igens[a], igens[b]));
// }
// }
// const auto &mults = res;
// std::cout << "built mults" << std::endl;
// auto *e_table = mults.isolve({});
// std::cout << "built table" << std::endl;
// std::cout << "edge verts:" << e_table->size() << std::endl;
//
//// for (int i = 0; i < e_table->size(); ++i) {
//// edge_data.push_back(i);
//// }
//
// delete e_table;
edge.size = edge_data.size();
glBindBuffer(GL_ARRAY_BUFFER, edge.name);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge.size, &edge_data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
~Mesh() {
delete t_vert;
delete[] vert_data;
// glDeleteBuffers(1, &vert.name);
// glDeleteBuffers(1, &edge.name);
// glDeleteBuffers(1, &face.name);
}
};
std::ostream &operator<<(std::ostream &out, Buffer b);

View File

@@ -1,31 +0,0 @@
#pragma once
#include <vector>
#include <glm/glm.hpp>
#include <cmath>
#include "coxeter.hpp"
#include "numeric.hpp"
std::vector<glm::vec4> mirror(const Mults &mults) {
std::vector<glm::vec4> mirrors{};
for (int p = 0; p < mults.dim; ++p) {
glm::vec4 vp{};
for (int m = 0; m < p; ++m) {
glm::vec4 vq = mirrors[m];
vp[m] = (cos(M_PI / mults.get(p, m)) - dot(m, vp, vq)) / vq[m];
}
vp[p] = std::sqrt(1 - glm::dot(vp, vp));
for (const auto &v : mirrors) {
if (glm::dot(vp, v) > 0) {
vp *= -1;
break;
}
}
mirrors.push_back(round(vp, 15));
}
return mirrors;
}

View File

@@ -1,24 +0,0 @@
#pragma once
#include <glm/glm.hpp>
#include <vector>
#include <algorithm>
glm::vec4 round(glm::vec4 f, int prec);
float dot(int n, glm::vec4 a, glm::vec4 b);
glm::vec4 project(glm::vec4 vec, glm::vec4 target);
glm::vec4 reflect(glm::vec4 vec, glm::vec4 axis);
glm::vec4 gram_schmidt_last(std::vector<glm::vec4> vecs);
glm::vec4 barycentric(std::vector<glm::vec4> basis, std::vector<float> coords);
std::vector<glm::vec4> plane_intersections(std::vector<glm::vec4> normals);
std::vector<std::vector<int>> combinations(int N, int K);
std::vector<std::vector<int>> combinations(std::vector<int> N, int K);

View File

@@ -1,10 +0,0 @@
#pragma once
#include <glad/glad.h>
#include <string>
GLint build_shader(GLenum type, const std::string &name, const std::string &src);
GLint build_shader_file(GLenum type, const std::string &name, const std::string &file);
GLint build_program(const std::string &name, GLint vs, GLint fs);

View File

@@ -1,24 +0,0 @@
#pragma once
#include "glad/glad.h"
#include <GLFW/glfw3.h>
class Window {
protected:
GLFWwindow *_window = nullptr;
public:
virtual void init();
virtual void update();
virtual void render();
virtual void deinit();
void getBounds(int &width, int &height);
void swapbuffers();
void run();
};

View File

@@ -1,38 +0,0 @@
#include <algorithm>
#include <iostream>
#include <vector>
#include <array>
template<class RandIt>
bool next_k_permutation(RandIt first, RandIt mid, RandIt last) {
typedef typename std::iterator_traits<RandIt>::value_type value_type;
std::sort(mid, last, std::greater<value_type>());
return std::next_permutation(first, last);
}
template<class BiDiIt>
bool next_combination(BiDiIt first, BiDiIt mid, BiDiIt last) {
bool result;
do {
result = next_k_permutation(first, mid, last);
} while (std::adjacent_find(first, mid, std::greater<>()) != mid);
return result;
}
int main(int argc, char *argv[]) {
std::vector<int> nums{0, 1, 2, 3, 4, 5};
const auto begin = nums.begin();
const auto mid = begin + 2;
const auto end = nums.end();
do {
for (auto e = begin; e < mid; ++e) {
std::cout << *e << " ";
}
std::cout << std::endl;
} while (next_combination(begin, mid, end));
return 0;
}

27
cosets/src/coxeter.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include "util/coxeter.hpp"
int main(int argc, char *argv[]) {
std::vector<std::vector<int>> ids{
{0, 0},
{1, 1},
{2, 2},
{0, 1, 0, 1, 0, 1, 0, 1},
{1, 2, 1, 2, 1, 2},
{0, 2, 0, 2}
};
Table *table = solve(3, {0, 1}, ids);
std::cout << table->size() << std::endl;
std::cout << *table << std::endl;
for (const auto &v : table->words()) {
std::cout << "[ ";
for (auto e : v) {
std::cout << e << " ";
}
std::cout << "]\n";
}
return 0;
}

View File

@@ -1,181 +1,162 @@
#include "window.hpp"
#include "shader.hpp"
#include "mesh.hpp"
#include "util/window.hpp"
#include "util/shader.hpp"
#include <glm/mat4x4.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include <iostream>
#include <iomanip>
#ifdef _WIN32
extern "C" {
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
}
#endif
#include "util/mesh.hpp"
using namespace std;
class CosetsWindow : public Window {
GLint program{};
GLuint vert_vao{}, edge_vao{}, face_vao{};
GLint program;
GLuint vert_vao, edge_vao, face_vao;
Mesh *figure{};
GLuint verts_buf;
std::vector<glm::vec4> vert_data;
GLint u_proj{}, u_view{}, u_color{};
GLuint edges_buf;
std::vector<int> edge_data;
const std::vector<int> symbol;
GLuint faces_buf;
std::vector<int> face_data;
GLint u_proj, u_view, u_color;
public:
explicit CosetsWindow(std::vector<int> symbol) : symbol(std::move(symbol)) {
}
void init() override {
auto vs = build_shader_file(
GL_VERTEX_SHADER,
"vertex",
"shaders/main.vs.glsl");
void init() override {
std::cout
<< "Graphics Information:" << std::endl
<< "Vendor: " << glGetString(GL_VENDOR) << std::endl
<< "Renderer: " << glGetString(GL_RENDERER) << std::endl
<< "Version: " << glGetString(GL_VERSION) << std::endl
<< "Shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
auto fs = build_shader_file(
GL_FRAGMENT_SHADER,
"fragment",
"shaders/main.fs.glsl");
auto vs = build_shader_file(
GL_VERTEX_SHADER,
"vertex",
"shaders/main.vs.glsl");
program = build_program("main", vs, fs);
auto fs = build_shader_file(
GL_FRAGMENT_SHADER,
"fragment",
"shaders/main.fs.glsl");
u_proj = glGetUniformLocation(program, "proj");
u_view = glGetUniformLocation(program, "view");
u_color = glGetUniformLocation(program, "color");
program = build_program("main", vs, fs);
const int N = 3;
const Mults &mults = schlafli<N>({5, 3});
vert_data = vertices<N>(mults, {10, 1, 1});
edge_data = edges<N>(mults);
face_data = faces<N>(mults);
u_proj = glGetUniformLocation(program, "proj");
u_view = glGetUniformLocation(program, "view");
u_color = glGetUniformLocation(program, "color");
glGenBuffers(1, &verts_buf);
glBindBuffer(GL_ARRAY_BUFFER, verts_buf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * vert_data.size(), &vert_data[0], GL_STATIC_DRAW);
figure = new Mesh(schlafli(symbol));
figure->gen_vertices(identity(figure->t_vert->mults, {10, .5, .5, .5}));
glGenBuffers(1, &edges_buf);
glBindBuffer(GL_ARRAY_BUFFER, edges_buf);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge_data.size(), &edge_data[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &vert_vao);
glBindVertexArray(vert_vao);
glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &faces_buf);
glBindBuffer(GL_ARRAY_BUFFER, faces_buf);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * face_data.size(), &face_data[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &edge_vao);
glBindVertexArray(edge_vao);
glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->edge.name);
glGenVertexArrays(1, &vert_vao);
glBindVertexArray(vert_vao);
glBindBuffer(GL_ARRAY_BUFFER, verts_buf);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &face_vao);
glBindVertexArray(face_vao);
glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->face.name);
glGenVertexArrays(1, &edge_vao);
glBindVertexArray(edge_vao);
glBindBuffer(GL_ARRAY_BUFFER, verts_buf);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edges_buf);
glBindVertexArray(0);
}
glGenVertexArrays(1, &face_vao);
glBindVertexArray(face_vao);
glBindBuffer(GL_ARRAY_BUFFER, verts_buf);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faces_buf);
void render() override {
int w, h;
getBounds(w, h);
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(0);
const auto id = glm::mat4(1);
const auto ax_1 = glm::vec3(0, 0, 1);
const auto ax_2 = glm::vec3(.5, 1, 0.2);
const auto t = glfwGetTime();
const auto angle = (float) t / 3;
std::cout << "verts: " << vert_data.size() << std::endl;
std::cout << "vendor: " << glGetString(GL_VENDOR) << std::endl
<< "renderer: " << glGetString(GL_RENDERER) << std::endl
<< "version: " << glGetString(GL_VERSION) << std::endl
<< "shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
}
const float sc = 1.5f;
const float ar = (float) w / (float) h;
void render() override {
int w, h;
getBounds(w, h);
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const auto c1 = (float) std::cos(angle * 3.0);
const auto s1 = (float) std::sin(angle * 3.0);
const auto c2 = (float) std::cos(angle * 0.2);
const auto s2 = (float) std::sin(angle * 0.2);
const auto id = glm::mat4(1);
const auto ax_1 = glm::vec3(0, 0, 1);
const auto ax_2 = glm::vec3(.5, 1, 0.2);
const auto t = glfwGetTime();
const auto angle = (float) t / 5;
const glm::mat4 proj = glm::ortho(-ar * sc, ar * sc, -sc, sc, -10.f, 10.f);
const glm::mat4 view = glm::rotate(id, angle, ax_1) * glm::rotate(id, angle, ax_2)
* glm::mat4(
c1, 0.0, s1, 0.0,
0.0, c2, 0.0, s2,
-s1, 0.0, c1, 0.0,
0.0, -s2, 0.0, c2
);
const float sc = 1.5f;
const float ar = (float) w / (float) h;
// const float root_x = std::cos((t + 0) * M_PI / 2) / 2 + 0.5;
// const float root_y = std::cos((t + 1) * M_PI / 2) / 2 + 0.5;
// const float root_z = std::cos((t + 2) * M_PI / 2) / 2 + 0.5;
// const float root_w = std::cos((t + 3) * M_PI / 2) / 2 + 0.5;
//
// const glm::vec4 root = identity(figure->mults, {root_x, root_y, root_z, root_w});
// figure->gen_vertices(root);
const glm::mat4 proj = glm::ortho(-ar * sc, ar * sc, -sc, sc, -10.f, 10.f);
const glm::mat4 view = glm::rotate(id, angle, ax_1) * glm::rotate(id, angle, ax_2);
glUseProgram(program);
glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj));
glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view));
glUseProgram(program);
glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj));
glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view));
glEnable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPointSize(10.0f);
glLineWidth(5.0f);
glPointSize(10.0f);
glLineWidth(5.0f);
glBindVertexArray(vert_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawArrays(GL_POINTS, 0, figure->vert.size);
glBindVertexArray(vert_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawArrays(GL_POINTS, 0, vert_data.size());
glBindVertexArray(edge_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawElements(GL_LINES, figure->edge.size, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(edge_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawElements(GL_LINES, edge_data.size(), GL_UNSIGNED_INT, 0);
// glBindVertexArray(face_vao);
// glCullFace(GL_NONE);
// glUniform4f(u_color, 1, 1, 1, 1);
// glDrawElements(GL_TRIANGLES, figure->face.size, GL_UNSIGNED_INT, 0);
glBindVertexArray(face_vao);
glCullFace(GL_BACK);
glUniform4f(u_color, 1, 1, 1, 1);
glDrawElements(GL_TRIANGLES, face_data.size(), GL_UNSIGNED_INT, 0);
// glCullFace(GL_FRONT);
// glUniform4f(u_color, .3, .3, 1, 1);
// glDrawElements(GL_TRIANGLES, figure->face.size, GL_UNSIGNED_INT, 0);
swapbuffers();
}
swapbuffers();
}
void deinit() override {
glDeleteProgram(program);
glDeleteVertexArrays(1, &vert_vao);
}
void deinit() override {
glDeleteProgram(program);
glDeleteVertexArrays(1, &vert_vao);
}
};
int main(int argc, char *argv[]) {
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return EXIT_FAILURE;
}
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return EXIT_FAILURE;
}
std::vector<int> symbol;
symbol.reserve(argc);
for (int i = 1; i < argc; ++i) {
symbol.push_back(std::stoi(argv[i]));
}
Window *window = new CosetsWindow();
window->run();
Window *window = new CosetsWindow(symbol);
window->run();
glfwTerminate();
return EXIT_SUCCESS;
glfwTerminate();
return EXIT_SUCCESS;
}

14
cosets/src/mesh.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "util/mesh.hpp"
int main(int argc, char *argv[]) {
const int N = 3;
const Mults &mults = schlafli<N>({4, 3});
const std::vector<glm::vec4> &vs = vertices<N>(mults, {10, 1, 1});
std::cout << "# verts: " << vs.size() << std::endl;
const auto es = edges<N>(mults);
return 0;
}

14
cosets/src/mirrors.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "util/mirrors.hpp"
int main(int argc, char *argv[]) {
auto normals = mirror<3>(Multiplicities<3>({
{0, 1, 4},
{1, 2, 3}
}));
for (const auto &normal : normals) {
std::cout << glm::to_string(normal) << std::endl;
}
return 0;
}

298
cosets/src/util/coxeter.hpp Normal file
View File

@@ -0,0 +1,298 @@
#pragma once
#include <iostream>
#include <utility>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <map>
#include <tuple>
struct Mults {
std::map<std::tuple<int, int>, int> mults{};
void set(int a, int b, int mult) {
if (a > b) std::swap(a, b);
mults[std::make_tuple(a, b)] = mult;
}
[[nodiscard]] int get(int a, int b) const {
if (a == b) return 1;
if (a > b) std::swap(a, b);
const auto &tup = std::make_tuple(a, b);
const auto &res = mults.find(tup);
if (res == mults.end()) return 2;
return res->second;
}
[[nodiscard]] std::vector<int> relation(int a, int b) const {
std::vector<int> res{};
int mult = get(a, b);
for (int i = 0; i < mult; ++i) {
res.push_back(a);
res.push_back(b);
}
return res;
}
[[nodiscard]] std::vector<std::vector<int>> relations(std::vector<int> gens) const {
std::vector<std::vector<int>> res{};
for (int a = 0; a < gens.size(); ++a) {
for (int b = a; b < gens.size(); ++b) {
res.push_back(relation(gens[a], gens[b]));
}
}
return res;
}
};
template<int N>
Mults schlafli(const int (&symbol)[N - 1]) {
Mults mults{};
for (int i = 0; i < N; ++i) {
mults.set(i, i + 1, symbol[i]);
}
return mults;
}
struct Table {
const std::vector<int> gens;
std::vector<std::vector<int>> fwd{};
std::vector<std::vector<int>> rev{};
explicit Table(const std::vector<int> gens) : gens(gens) {
add_row();
}
[[nodiscard]] int gen_index(int gen) const {
for (unsigned i = 0; i < gens.size(); ++i)
if (gens[i] == gen)
return i;
throw std::logic_error("Referencing nonexistant generator");
}
void add_row() {
int N = gens.size();
fwd.emplace_back(N, -1);
rev.emplace_back(N, -1);
}
int add_coset() {
for (int from = 0; from < (int) size(); ++from) {
for (int gen : gens) {
if (get(from, gen) < 0) {
int to = (int) size();
add_row();
set(from, gen, to);
return to;
}
}
}
return 0;
}
[[nodiscard]] unsigned size() const {
return fwd.size();
}
void set(int from, int gen, int to) {
int i = gen_index(gen);
fwd[from][i] = to;
rev[to][i] = from;
}
[[nodiscard]] int get(int from, int gen) const {
int i = gen_index(gen);
return fwd[from][i];
}
[[nodiscard]] int rget(int gen, int to) const {
int i = gen_index(gen);
return rev[to][i];
}
std::vector<std::vector<int>> words() {
std::vector<std::vector<int> *> vecs(size());
vecs[0] = new std::vector<int>();
while (std::find(vecs.begin(), vecs.end(), nullptr) != vecs.end()) {
for (int from = 0; from < (int) vecs.size(); ++from) {
std::vector<int> *word = vecs[from];
if (word == nullptr) {
continue;
}
for (int gen : gens) {
int to = get(from, gen);
if (vecs[to] != nullptr) {
continue;
}
vecs[to] = new std::vector<int>(*word);
vecs[to]->push_back(gen);
}
}
}
std::vector<std::vector<int>> res(size());
for (int i = 0; i < (int) size(); ++i) {
res[i] = *vecs[i];
delete vecs[i];
}
return res;
}
[[nodiscard]] int apply(int e, const std::vector<int> &word) const {
for (const auto &gen : word) {
e = get(e, gen);
}
return e;
}
[[nodiscard]] int apply(const std::vector<int> &word) const {
return apply(0, word);
}
[[nodiscard]] std::vector<int> apply_each(int e, const std::vector<std::vector<int>> &words) const {
std::vector<int> res{};
for (const auto &word:words) {
res.push_back(apply(e, word));
}
return res;
}
[[nodiscard]] std::vector<int> apply_each(const std::vector<std::vector<int>> &words) const {
return apply_each(0, words);
}
};
struct Row {
std::vector<int>::const_iterator l;
std::vector<int>::const_iterator r;
int from;
int to;
Row(const std::vector<int> &vec, int cos) {
this->l = vec.begin();
this->r = vec.end() - 1;
this->from = cos;
this->to = cos;
}
[[nodiscard]] bool learn(Table *table) {
if (r - l == 0) {
return false;
}
while (r - l > 0) {
int next = table->get(from, *l);
if (next < 0) break;
l++;
from = next;
}
while (r - l > 0) {
int next = table->rget(*r, to);
if (next < 0) break;
r--;
to = next;
}
if (r - l == 0) {
table->set(from, *l, to);
return true;
}
return false;
}
};
std::ostream &operator<<(std::ostream &out, const Row &row) {
out << "[ " << row.from << " | ";
auto it = row.l;
while (row.r - it > 0) {
out << *it << " ";
it++;
}
out << "| " << row.to << " ]";
return out;
}
Table *solve(const std::vector<int> &gens, const std::vector<int> &subgens, const Mults &mults) {
const auto rels = mults.relations(gens);
auto *table = new Table(gens);
for (int gen : subgens)
table->set(0, gen, 0);
std::vector<Row> rows;
rows.reserve(rels.size());
for (const auto &rel : rels)
rows.emplace_back(rel, 0);
while (!rows.empty()) {
while (true) {
bool learned = false;
for (int i = (int) rows.size() - 1; i >= 0; i--) {
if (rows[i].learn(table)) {
learned = true;
rows.erase(rows.begin() + i);
}
}
if (!learned)
break;
}
int i = (int) table->size();
if (table->add_coset() > 0) {
for (const auto &rel : rels)
rows.emplace_back(rel, i);
} else {
break;
}
}
return table;
}
template<int N>
Table *solve(const std::vector<int> &subgens, const Mults &mults) {
std::vector<int> gens{};
for (int i = 0; i < N; ++i) {
gens.push_back(i);
}
return solve(gens, subgens, mults);
}
std::ostream &operator<<(std::ostream &out, const Table &table) {
int k = ceil(log10(table.size()));
out << "[";
for (unsigned j = 0; j < table.size(); ++j) {
auto arr = table.fwd[j];
out << " " << std::setw(k) << j << " [";
for (int i = 0; i < (int) table.gens.size(); ++i) {
out << arr[i];
if (i < table.gens.size() - 1)
out << " ";
}
out << "]";
if (j < table.fwd.size() - 1)
out << "\n ";
}
out << "]\n";
return out;
}

View File

@@ -1,6 +1,7 @@
#include "files.hpp"
#pragma once
#include <fstream>
#include <string>
#include <streambuf>
std::string read_all_text(const std::string &file) {

114
cosets/src/util/mesh.hpp Normal file
View File

@@ -0,0 +1,114 @@
#pragma once
#include "coxeter.hpp"
#include "mirrors.hpp"
#include "numeric.hpp"
#include <vector>
template<int N>
std::vector<std::vector<int>> coxeter_rels() {
std::vector<std::vector<int>> rels{};
return rels;
}
template<int N>
glm::vec4 identity(const std::vector<glm::vec4> &normals, const float(&coords)[N]) {
const std::vector<glm::vec4> corners = plane_intersections(normals);
const std::vector<float> coords_vec(coords, coords + N);
const glm::vec4 identity = barycentric(corners, coords_vec);
return glm::normalize(identity);
}
template<int N>
std::vector<glm::vec4>
vertices(const Mults &mults, const float (&coords)[N]) {
Table *table = solve<N>({}, mults);
const std::vector<glm::vec4> normals = mirror<N>(mults);
glm::vec4 ident = identity(normals, coords);
std::vector<glm::vec4> verts{};
for (const auto &word : table->words()) {
glm::vec4 vert = ident;
for (const auto &gen : word) {
vert = reflect(vert, normals[gen]);
}
verts.push_back(vert);
}
return verts;
}
template<int N>
std::vector<int> edges(const Mults &mults) {
std::vector<int> res{};
Table *t_vert = solve<N>({}, mults);
for (const auto &subgens : combinations(N, 1)) {
Table *t_edge = solve(subgens, {}, mults);
std::vector<int> edge = t_vert->apply_each(t_edge->words());
Table *c_edge = solve<N>(subgens, mults);
for (const auto &coset : c_edge->words()) {
for (const auto &e : edge) {
res.push_back(t_vert->apply(e, coset));
}
}
}
return res;
}
template<int N>
std::vector<int> faces(const Mults &mults) {
std::vector<int> res{};
Table *t_vert = solve<N>({}, mults);
// for each *kind* of face
for (const auto &sg_face : combinations(N, 2)) {
Table *cs_face = solve<N>(sg_face, mults);
// for each *kind* of edge
for (const auto &sg_edge : combinations(sg_face, 1)) {
Table *cs_edge = solve(sg_face, sg_edge, mults);
// find the vertices of that edge
Table *t_edge = solve(sg_edge, {}, mults);
std::vector<int> edge = t_vert->apply_each(t_edge->words());
// for each face
for (const auto &c_face : cs_face->words()) {
// for each edge
for (const auto &c_edge : cs_edge->words()) {
if (c_edge.empty()) { continue; }
for (auto e : edge) {
e = t_vert->apply(e, c_edge);
e = t_vert->apply(e, c_face);
res.push_back(e);
}
res.push_back(t_vert->apply(0, c_face));
if (c_edge.size() & 1u)
std::swap(res[res.size() - 1], res[res.size() - 2]);
unsigned ro_si1 = (sg_face[0] + sg_face[1]);
unsigned flag = sg_edge[0] == sg_face[0];
unsigned n_mirrors = c_face.size();
if ((n_mirrors + flag + ro_si1) & 1u) {
std::swap(res[res.size() - 1], res[res.size() - 2]);
}
}
}
}
}
return res;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <cmath>
#include <vector>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>
#include <iomanip>
#include "numeric.hpp"
#include "coxeter.hpp"
template<int N>
std::vector<glm::vec4> mirror(const Mults &mults) {
static_assert(1 <= N and N <= 4, "Vector size is unsupported");
std::vector<glm::vec4> mirrors{};
for (int p = 0; p < N; ++p) {
glm::vec4 vp{};
for (int m = 0; m < p; ++m) {
glm::vec4 vq = mirrors[m];
vp[m] = (cos(M_PI / mults.get(p, m)) - dot(m, vp, vq)) / vq[m];
}
vp[p] = std::sqrt(1 - glm::dot(vp, vp));
for (const auto &v : mirrors) {
if (glm::dot(vp, v) > 0) {
vp *= -1;
break;
}
}
mirrors.push_back(round(vp, 15));
}
return mirrors;
}

View File

@@ -1,6 +1,8 @@
#include "numeric.hpp"
#pragma once
#include <string>
#include <glm/glm.hpp>
#include <vector>
#include <algorithm>
glm::vec4 round(glm::vec4 f, int prec) {
auto dec = (float) pow(10, prec);

View File

@@ -1,6 +1,9 @@
#include "shader.hpp"
#pragma once
#include <glad/glad.h>
#include <string>
#include <cstdio>
#include <cstdlib>
#include "files.hpp"

View File

@@ -1,55 +0,0 @@
#include "window.hpp"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <cstdio>
void Window::init() {}
void Window::update() {}
void Window::render() {}
void Window::deinit() {}
void Window::getBounds(int &width, int &height) {
glfwGetFramebufferSize(_window, &width, &height);
}
void Window::swapbuffers() {
glfwSwapBuffers(_window);
}
void Window::run() {
int _gl_major = 4, _gl_minor = 0;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _gl_minor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
_window = glfwCreateWindow(1920, 1080, "GLFW App", nullptr, nullptr);
if (!_window) {
fprintf(stderr, "Failed to create window;");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(_window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(0);
init();
while (!glfwWindowShouldClose(_window)) {
update();
render();
glfwPollEvents();
}
deinit();
glfwDestroyWindow(_window);
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <cstdio>
class Window {
protected:
GLFWwindow *_window = nullptr;
public:
virtual void init() {}
virtual void update() {}
virtual void render() {}
virtual void deinit() {}
void getBounds(int &width, int &height) {
glfwGetFramebufferSize(_window, &width, &height);
}
void swapbuffers() {
glfwSwapBuffers(_window);
}
void run() {
int _gl_major = 4, _gl_minor = 0;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _gl_minor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
_window = glfwCreateWindow(1920, 1080, "GLFW App", nullptr, nullptr);
if (!_window) {
fprintf(stderr, "Failed to create window;");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(_window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(0);
init();
while (!glfwWindowShouldClose(_window)) {
update();
render();
glfwPollEvents();
}
deinit();
glfwDestroyWindow(_window);
}
};