optimize vertex generation; break edge/face generation

This commit is contained in:
2019-09-19 23:31:53 -04:00
parent 649cec0a9d
commit 583f6fef71
8 changed files with 422 additions and 659 deletions

View File

@@ -9,10 +9,7 @@ add_custom_command(
add_executable(${PROJECT_NAME}
src/main.cpp
src/util/coxeter.cpp
src/util/files.cpp
src/util/mesh.cpp
src/util/mirrors.cpp
src/util/numeric.cpp
src/util/shader.cpp
src/util/window.cpp)

View File

@@ -4,90 +4,233 @@
#include <vector>
#include <algorithm>
template<int NGENS>
struct Mults;
template<int NGENS>
struct Table;
struct IRow;
template<int NGENS>
struct Mults {
int num_gens;
std::map<std::tuple<int, int>, int> mults;
const int dim = NGENS;
std::map<std::tuple<int, int>, int> mults;
Mults();
Mults() {
mults = std::map<std::tuple<int, int>, int>();
}
void set(int a, int b, int mult);
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;
[[nodiscard]] int get(int a, int b) const {
if (a == b) return 1;
if (a > b) std::swap(a, b);
[[nodiscard]] std::vector<int> relation(int a, int b) const;
const auto &tup = std::make_tuple(a, b);
const auto &res = mults.find(tup);
[[nodiscard]] std::vector<std::vector<int>> relations(const std::vector<int> &gens) const;
if (res == mults.end()) return 2;
return res->second;
}
[[nodiscard]] std::vector<std::vector<int>> irelations(const Table *table, const std::vector<int> &gens) const;
[[nodiscard]] std::vector<int> irelation(int a, int b) const {
std::vector<int> res{};
int mult = get(a, b);
[[nodiscard]] Table *solve(const std::vector<int> &subgens) const;
[[nodiscard]] Table *solve(const std::vector<int> &gens, const std::vector<int> &subgens) const;
for (int i = 0; i < mult; ++i) {
res.push_back(a);
res.push_back(b);
}
return res;
}
[[nodiscard]] Table<NGENS> *isolve(const std::vector<int> &isubgens) const;
template<int IGENS>
[[nodiscard]] Table<IGENS> *isolve(const int (&igens)[IGENS], const std::vector<int> &isubgens) const;
};
template<int NGENS>
struct Table {
const std::vector<int> gens;
const Mults mults;
std::vector<int> gen_inds;
std::vector<std::vector<int>> fwd;
std::vector<std::vector<int>> rev;
const Mults<NGENS> mults;
std::vector<std::vector<int>> fwd;
explicit Table(const std::vector<int> &gens, Mults mults);
explicit Table(Mults<NGENS> mults) : mults(mults) {
add_row();
}
[[nodiscard]] int gen_index(int gen) const;
void add_row() {
fwd.emplace_back(NGENS, -1);
}
[[nodiscard]] std::vector<int> gen_index_each(std::vector<int> rel) const;
int add_coset() {
for (int from = 0; from < (int) size(); ++from) {
for (int igen = 0; igen < (int) NGENS; igen++) {
if (iget(from, igen) < 0) {
int to = (int) size();
add_row();
iset(from, igen, to);
return to;
}
}
}
return 0;
}
void add_row();
[[nodiscard]] unsigned size() const {
return fwd.size();
}
int add_coset();
void iset(int from, int igen, int to) {
fwd[from][igen] = to;
fwd[to][igen] = from;
}
[[nodiscard]] unsigned size() const;
[[nodiscard]] int iget(int from, int igen) const {
return fwd[from][igen];
}
void set(int from, int gen, int to);
[[nodiscard]] int irget(int igen, int to) const {
return fwd[to][igen];
}
[[nodiscard]] int get(int from, int gen) const;
[[nodiscard]] int rget(int gen, int to) const;
void iset(int from, int igen, int to);
[[nodiscard]] int iget(int from, int igen) const;
[[nodiscard]] int irget(int igen, int to) const;
[[nodiscard]] std::vector<std::vector<int>> words() const;
[[nodiscard]] int apply(int e, const std::vector<int> &word) const;
[[nodiscard]] int apply(const std::vector<int> &word) const;
[[nodiscard]] std::vector<int> apply_each(int e, const std::vector<std::vector<int>> &words) const;
[[nodiscard]] std::vector<int> apply_each(const std::vector<std::vector<int>> &words) const;
};
struct IRow {
std::vector<int>::const_iterator l;
std::vector<int>::const_iterator r;
std::vector<int>::const_iterator l;
std::vector<int>::const_iterator r;
int from;
int to;
int from;
int to;
IRow(const std::vector<int> &rel, int cos);
IRow(const std::vector<int> &rel, int cos)
: l(rel.begin()), r(rel.end() - 1), from(cos), to(cos) {
}
[[nodiscard]] bool learn(Table *table);
template<int NGENS>
[[nodiscard]] bool learn(Table<NGENS> *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;
}
};
//Table *solve(const std::vector<int> &gens, const std::vector<int> &subgens, const Mults &mults);
//
//Table *solve(const std::vector<int> &subgens, const Mults &mults);
//
//Table *solve_elems(const Mults &mults);
template<int NGENS>
Mults<NGENS> schlafli(const int(&symbol)[NGENS - 1]) {
Mults<NGENS> mults{};
for (int i = 0; i < NGENS; ++i) {
mults.set(i, i + 1, symbol[i]);
}
return mults;
}
Mults schlafli(const std::vector<int> &symbol);
template<int NGENS>
Table<NGENS> *Mults<NGENS>::isolve(const std::vector<int> &isubgens) const {
auto *table = new Table<NGENS>(*this);
for (int igen : isubgens)
table->iset(0, igen, 0);
std::vector<int> all_gens(int N);
std::vector<std::vector<int>> irels{};
for (unsigned a = 0; a < NGENS; ++a) {
for (unsigned b = a + 1; b < NGENS; ++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;
}
template<int NGENS>
template<int IGENS>
Table<IGENS> *Mults<NGENS>::isolve(const int (&igens)[IGENS], const std::vector<int> &isubgens) const {
auto *table = new Table<IGENS>(*this);
for (int igen : isubgens)
table->iset(0, igen, 0);
std::vector<std::vector<int>> irels{};
for (unsigned a = 0; a < igens.size(); ++a) {
for (unsigned b = a + 1; b < igens.size(); ++b) {
irels.push_back(irelation(igens[a], igens[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,43 +1,112 @@
#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);
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);
glm::vec4 center(const Mults &mults);
template<int NGENS>
glm::vec4 identity(const Mults<NGENS> &mults, const std::vector<float> &coords) {
const std::vector<glm::vec4> normals = mirror(mults);
return identity(normals, coords);
}
std::vector<glm::vec4> vertices(const Table *t_vert, const glm::vec4 ident);
std::vector<int> edges(const Table *t_vert);
std::vector<int> faces(const Table *t_vert);
template<int NGENS>
glm::vec4 center(const Mults<NGENS> &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 {
const GLuint name;
const unsigned size;
const float gen_time;
GLuint name = 0;
unsigned size = 0;
};
template<int NGENS>
struct Mesh {
const Mults mults;
const Table *t_vert;
const Mults<NGENS> mults;
const Table<NGENS> *t_vert;
Buffer vert;
Buffer edge;
Buffer face;
const std::vector<glm::vec4> normals;
glm::vec4 *vert_data;
Mesh(Mults mults, const Table *t_vert, Buffer vert, Buffer edge, Buffer face);
Buffer vert;
Buffer edge;
Buffer face;
~Mesh();
explicit Mesh(Mults<NGENS> 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();
std::cout << "time to solve: " << ((std::chrono::duration<double>) (b - a)).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();
}
explicit Mesh(Mults<NGENS> mults, const glm::vec4 root) {
this(mults);
gen_vertices(root);
}
void gen_vertices(const glm::vec4 root) {
vert_data[0] = root;
for (unsigned from = 0; from < vert.size; ++from) {
for (unsigned gen = 0; gen < NGENS; ++gen) {
int to = t_vert->iget((int) from, (int) gen);
vert_data[to] = reflect(vert_data[from], normals[gen]);
}
}
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> edges;
std::vector<int> faces;
glBindBuffer(GL_ARRAY_BUFFER, edge.name);
// glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge.size, edge_data, 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);
}
};
Mesh *mesh(const Mults &mults, glm::vec4 ident);
std::ostream &operator<<(std::ostream &out, Buffer b);

View File

@@ -2,6 +2,31 @@
#include <vector>
#include <glm/glm.hpp>
#include "coxeter.hpp"
#include <cmath>
std::vector<glm::vec4> mirror(const Mults &mults);
#include "coxeter.hpp"
#include "numeric.hpp"
template<int NGENS>
std::vector<glm::vec4> mirror(const Mults<NGENS> &mults) {
std::vector<glm::vec4> mirrors{};
for (int p = 0; p < NGENS; ++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

@@ -13,149 +13,152 @@
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;
Mesh<4> *figure;
GLint u_proj, u_view, u_color;
GLint u_proj, u_view, u_color;
public:
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;
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 vs = build_shader_file(
GL_VERTEX_SHADER,
"vertex",
"shaders/main.vs.glsl");
auto vs = build_shader_file(
GL_VERTEX_SHADER,
"vertex",
"shaders/main.vs.glsl");
auto fs = build_shader_file(
GL_FRAGMENT_SHADER,
"fragment",
"shaders/main.fs.glsl");
auto fs = build_shader_file(
GL_FRAGMENT_SHADER,
"fragment",
"shaders/main.fs.glsl");
program = build_program("main", vs, fs);
program = build_program("main", vs, fs);
u_proj = glGetUniformLocation(program, "proj");
u_view = glGetUniformLocation(program, "view");
u_color = glGetUniformLocation(program, "color");
u_proj = glGetUniformLocation(program, "proj");
u_view = glGetUniformLocation(program, "view");
u_color = glGetUniformLocation(program, "color");
const Mults &mults = schlafli({5, 3, 2});
// const glm::vec4 ident = center(mults);
const glm::vec4 ident = identity(mults, {2, .1, .1, 3});
std::cout << "Dimension: " << mults.num_gens << std::endl;
figure = new Mesh(schlafli<4>({5, 3, 3}));
figure = mesh(mults, ident);
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);
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);
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, &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, &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, &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);
glBindVertexArray(0);
}
glBindVertexArray(0);
}
void render() override {
int w, h;
getBounds(w, h);
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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 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;
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 float sc = 1.5f;
const float ar = (float) w / (float) h;
const float sc = 1.5f;
const float ar = (float) w / (float) h;
const float c1 = std::cos(angle * 3.0);
const float s1 = std::sin(angle * 3.0);
const float c2 = std::cos(angle * 0.2);
const float s2 = std::sin(angle * 0.2);
const float c1 = std::cos(angle * .7);
const float s1 = std::sin(angle * .7);
const float c2 = std::cos(angle * .5);
const float s2 = std::sin(angle * .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 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 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;
glUseProgram(program);
glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj));
glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view));
const glm::vec4 root = identity<4>(figure->mults, {root_x, root_y, root_z, root_w});
figure->gen_vertices(root);
glEnable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glUseProgram(program);
glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj));
glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glPointSize(10.0f);
glLineWidth(5.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindVertexArray(vert_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawArrays(GL_POINTS, 0, figure->vert.size);
glPointSize(10.0f);
glLineWidth(5.0f);
glBindVertexArray(edge_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawElements(GL_LINES, figure->edge.size, GL_UNSIGNED_INT, 0);
glBindVertexArray(vert_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawArrays(GL_POINTS, 0, figure->vert.size);
glBindVertexArray(face_vao);
glCullFace(GL_NONE);
glUniform4f(u_color, 1, 1, 1, 1);
glBindVertexArray(edge_vao);
glUniform4f(u_color, 1, 0, 0, 1);
glDrawElements(GL_LINES, figure->edge.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);
// 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;
}
Window *window = new CosetsWindow();
window->run();
Window *window = new CosetsWindow();
window->run();
glfwTerminate();
return EXIT_SUCCESS;
glfwTerminate();
return EXIT_SUCCESS;
}

View File

@@ -1,281 +0,0 @@
#include "coxeter.hpp"
Mults::Mults() {
num_gens = 0;
mults = std::map<std::tuple<int, int>, int>();
}
void Mults::set(int a, int b, int mult) {
if (a > b) std::swap(a, b);
if (b + 1 > num_gens) num_gens = b + 1;
mults[std::make_tuple(a, b)] = mult;
}
int Mults::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;
}
std::vector<int> Mults::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;
}
std::vector<std::vector<int>> Mults::relations(const std::vector<int> &gens) const {
std::vector<std::vector<int>> res{};
for (int a = 0; a < (int) gens.size(); ++a) {
for (int b = a; b < (int) gens.size(); ++b) {
res.push_back(relation(gens[a], gens[b]));
}
}
return res;
}
std::vector<std::vector<int>> Mults::irelations(const Table *table, const std::vector<int> &gens) const {
std::vector<std::vector<int>> rels = relations(gens);
std::vector<std::vector<int>> irels(rels.size());
for (int i = 0; i < (int) rels.size(); ++i) {
irels[i] = table->gen_index_each(rels[i]);
}
return irels;
}
Table::Table(const std::vector<int> &gens, const Mults mults) : gens(gens), mults(mults) {
add_row();
gen_inds = std::vector<int>(gens[gens.size() - 1] + 1, -1);
for (int i = 0; i < (int) gens.size(); i++) {
gen_inds[gens[i]] = i;
}
}
int Table::gen_index(int gen) const {
if (gen >= gen_inds.size())
throw std::logic_error("Referencing nonexistant generator (too large)");
int i = gen_inds[gen];
if (i < 0)
throw std::logic_error("Referencing nonexistant generator (not present)");
return i;
}
std::vector<int> Table::gen_index_each(std::vector<int> rel) const {
std::vector<int> res(rel.size(), 0);
for (int i = 0; i < (int) rel.size(); ++i) {
res[i] = gen_index(rel[i]);
}
return res;
}
void Table::add_row() {
int N = gens.size();
fwd.emplace_back(N, -1);
rev.emplace_back(N, -1);
}
int Table::add_coset() {
for (int from = 0; from < (int) size(); ++from) {
for (int igen = 0; igen < (int) gens.size(); igen++) {
if (iget(from, igen) < 0) {
int to = (int) size();
add_row();
iset(from, igen, to);
return to;
}
}
}
return 0;
}
unsigned Table::size() const {
return fwd.size();
}
void Table::set(int from, int gen, int to) {
int i = gen_index(gen);
fwd[from][i] = to;
rev[to][i] = from;
}
int Table::get(int from, int gen) const {
int i = gen_index(gen);
return fwd[from][i];
}
int Table::rget(int gen, int to) const {
int i = gen_index(gen);
return rev[to][i];
}
void Table::iset(int from, int igen, int to) {
fwd[from][igen] = to;
rev[to][igen] = from;
}
int Table::iget(int from, int igen) const {
return fwd[from][igen];
}
int Table::irget(int igen, int to) const {
return rev[to][igen];
}
std::vector<std::vector<int>> Table::words() const {
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 igen = 0; igen < gens.size(); igen++) {
int to = iget(from, igen);
if (vecs[to] != nullptr) {
continue;
}
vecs[to] = new std::vector<int>(*word);
vecs[to]->push_back(gens[igen]);
}
}
}
std::vector<std::vector<int>> res(size());
for (int i = 0; i < (int) size(); ++i) {
res[i] = *vecs[i];
delete vecs[i];
}
return res;
}
int Table::apply(int e, const std::vector<int> &word) const {
for (const auto &gen : word) {
e = get(e, gen);
}
return e;
}
int Table::apply(const std::vector<int> &word) const {
return apply(0, word);
}
std::vector<int> Table::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;
}
std::vector<int> Table::apply_each(const std::vector<std::vector<int>> &words) const {
return apply_each(0, words);
}
IRow::IRow(const std::vector<int> &rel, int cos) {
this->l = rel.begin();
this->r = rel.end() - 1;
this->from = cos;
this->to = cos;
}
bool IRow::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;
}
Table *Mults::solve(const std::vector<int> &gens, const std::vector<int> &subgens) const {
auto *table = new Table(gens, *this);
const auto irels = irelations(table, gens);
for (int gen : subgens)
table->set(0, gen, 0);
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;
}
Table *Mults::solve(const std::vector<int> &subgens) const {
return this->solve(all_gens(num_gens), subgens);
}
Mults schlafli(const std::vector<int> &symbol) {
Mults mults{};
for (int i = 0; i < symbol.size(); ++i) {
mults.set(i, i + 1, symbol[i]);
}
return mults;
}
std::vector<int> all_gens(int N) {
std::vector<int> gens(N);
for (int i = 0; i < N; ++i) {
gens[i] = i;
}
return gens;
}

View File

@@ -1,163 +0,0 @@
#include <glad/glad.h>
#include <utility>
#include <chrono>
#include "mesh.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);
}
Mesh::Mesh(Mults mults, const Table *t_vert, Buffer vert, Buffer edge, Buffer face)
: mults(std::move(mults)), t_vert(t_vert), vert(vert), edge(edge), face(face) {
}
Mesh::~Mesh() {
delete t_vert;
glDeleteBuffers(1, &vert.name);
glDeleteBuffers(1, &edge.name);
glDeleteBuffers(1, &face.name);
}
Mesh *mesh(const Mults &mults, glm::vec4 ident) {
GLuint buffers[3];
glGenBuffers(3, buffers);
Table *t_vert = mults.solve({});
auto vert_data = vertices(t_vert, ident);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * vert_data.size(), &vert_data[0], GL_STATIC_DRAW);
Buffer vert{buffers[0], vert_data.size()};
auto edge_data = edges(t_vert);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge_data.size(), &edge_data[0], GL_STATIC_DRAW);
Buffer edge{buffers[1], edge_data.size()};
auto face_data = faces(t_vert);
glBindBuffer(GL_ARRAY_BUFFER, buffers[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * face_data.size(), &face_data[0], GL_STATIC_DRAW);
Buffer face{buffers[2], face_data.size()};
return new Mesh(mults, t_vert, vert, edge, face);
}
std::vector<glm::vec4>
vertices(const Table *t_vert, const glm::vec4 ident) {
const std::vector<glm::vec4> normals = mirror(t_vert->mults);
std::vector<glm::vec4> verts{};
for (const auto &word : t_vert->words()) {
glm::vec4 vert = ident;
for (const auto &gen : word) {
vert = reflect(vert, normals[gen]);
}
verts.push_back(vert);
}
return verts;
}
std::vector<int> edges(const Table *t_vert) {
std::vector<int> res{};
Mults mults = t_vert->mults;
int N = mults.num_gens;
const std::vector<int> &gens = t_vert->gens;
for (const auto &subgens : combinations(N, 1)) {
Table *t_edge = mults.solve(subgens, {});;
std::vector<int> edge = t_vert->apply_each(t_edge->words());
Table *c_edge = mults.solve(gens, subgens);
for (const auto &coset : c_edge->words()) {
for (const auto &e : edge) {
res.push_back(t_vert->apply(e, coset));
}
}
delete t_edge;
delete c_edge;
}
return res;
}
std::vector<int> faces(const Table *t_vert) {
std::vector<int> res{};
const Mults &mults = t_vert->mults;
int N = mults.num_gens;
const std::vector<int> &gens = t_vert->gens;
// for each *kind* of face
for (const auto &sg_face : combinations(N, 2)) {
Table *cs_face = mults.solve(gens, sg_face);
// for each *kind* of edge
for (const auto &sg_edge : combinations(sg_face, 1)) {
Table *cs_edge = mults.solve(sg_face, sg_edge);
// find the vertices of that edge
Table *t_edge = mults.solve(sg_edge, {});
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]);
}
}
}
delete t_edge;
delete cs_edge;
}
delete cs_face;
}
return res;
}

View File

@@ -1,30 +0,0 @@
#include "mirrors.hpp"
#include <cmath>
#include "numeric.hpp"
#include "coxeter.hpp"
std::vector<glm::vec4> mirror(const Mults &mults) {
int N = mults.num_gens;
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;
}