Compare commits
17 Commits
v0-master
...
v0-optimiz
| Author | SHA1 | Date | |
|---|---|---|---|
| dd2e7783eb | |||
| c579edb0a0 | |||
| cc86a71392 | |||
| 3a96d4a875 | |||
| 583f6fef71 | |||
| 649cec0a9d | |||
| cd2cbf85d0 | |||
| 8cb5dd87ad | |||
| 855736ee47 | |||
| f2f723aac8 | |||
| 29097afd13 | |||
| d60ec16cad | |||
| 02611be11a | |||
| cddb3b56dc | |||
| 512aa41a00 | |||
| f9e9d78e88 | |||
| bd3fbf49bd |
@@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(vis-cosets)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
@@ -14,3 +15,10 @@ 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")
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# vis-cosets
|
||||
|
||||
Features being merged into https://github.com/JCRaymond/toddcox-faster. Favor that instead.
|
||||
@@ -1,5 +1,3 @@
|
||||
project(cosets)
|
||||
|
||||
add_custom_target(shaders ALL DEPENDS shader_output)
|
||||
add_custom_command(
|
||||
OUTPUT shader_output
|
||||
@@ -7,17 +5,16 @@ add_custom_command(
|
||||
COMMENT "copying shaders"
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/main.cpp)
|
||||
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_dependencies(cosets shaders)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
|
||||
target_link_libraries(cosets
|
||||
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)
|
||||
|
||||
194
cosets/include/coxeter.hpp
Normal file
194
cosets/include/coxeter.hpp
Normal file
@@ -0,0 +1,194 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
5
cosets/include/files.hpp
Normal file
5
cosets/include/files.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string read_all_text(const std::string &file);
|
||||
135
cosets/include/mesh.hpp
Normal file
135
cosets/include/mesh.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#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);
|
||||
31
cosets/include/mirrors.hpp
Normal file
31
cosets/include/mirrors.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#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;
|
||||
}
|
||||
24
cosets/include/numeric.hpp
Normal file
24
cosets/include/numeric.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#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);
|
||||
10
cosets/include/shader.hpp
Normal file
10
cosets/include/shader.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#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);
|
||||
24
cosets/include/window.hpp
Normal file
24
cosets/include/window.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#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();
|
||||
};
|
||||
38
cosets/src/combos.cpp
Normal file
38
cosets/src/combos.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,162 +1,181 @@
|
||||
#include "util/window.hpp"
|
||||
#include "util/shader.hpp"
|
||||
#include "window.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "mesh.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>
|
||||
|
||||
#include "util/mesh.hpp"
|
||||
#ifdef _WIN32
|
||||
extern "C" {
|
||||
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
#endif
|
||||
|
||||
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{};
|
||||
|
||||
GLuint verts_buf;
|
||||
std::vector<glm::vec4> vert_data;
|
||||
Mesh *figure{};
|
||||
|
||||
GLuint edges_buf;
|
||||
std::vector<int> edge_data;
|
||||
GLint u_proj{}, u_view{}, u_color{};
|
||||
|
||||
GLuint faces_buf;
|
||||
std::vector<int> face_data;
|
||||
|
||||
GLint u_proj, u_view, u_color;
|
||||
const std::vector<int> symbol;
|
||||
|
||||
public:
|
||||
void init() override {
|
||||
auto vs = build_shader_file(
|
||||
GL_VERTEX_SHADER,
|
||||
"vertex",
|
||||
"shaders/main.vs.glsl");
|
||||
explicit CosetsWindow(std::vector<int> symbol) : symbol(std::move(symbol)) {
|
||||
}
|
||||
|
||||
auto fs = build_shader_file(
|
||||
GL_FRAGMENT_SHADER,
|
||||
"fragment",
|
||||
"shaders/main.fs.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;
|
||||
|
||||
program = build_program("main", vs, fs);
|
||||
auto vs = build_shader_file(
|
||||
GL_VERTEX_SHADER,
|
||||
"vertex",
|
||||
"shaders/main.vs.glsl");
|
||||
|
||||
u_proj = glGetUniformLocation(program, "proj");
|
||||
u_view = glGetUniformLocation(program, "view");
|
||||
u_color = glGetUniformLocation(program, "color");
|
||||
auto fs = build_shader_file(
|
||||
GL_FRAGMENT_SHADER,
|
||||
"fragment",
|
||||
"shaders/main.fs.glsl");
|
||||
|
||||
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);
|
||||
program = build_program("main", vs, fs);
|
||||
|
||||
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);
|
||||
u_proj = glGetUniformLocation(program, "proj");
|
||||
u_view = glGetUniformLocation(program, "view");
|
||||
u_color = glGetUniformLocation(program, "color");
|
||||
|
||||
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);
|
||||
figure = new Mesh(schlafli(symbol));
|
||||
figure->gen_vertices(identity(figure->t_vert->mults, {10, .5, .5, .5}));
|
||||
|
||||
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, &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, verts_buf);
|
||||
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, verts_buf);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edges_buf);
|
||||
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, verts_buf);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faces_buf);
|
||||
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);
|
||||
|
||||
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 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;
|
||||
|
||||
void render() override {
|
||||
int w, h;
|
||||
getBounds(w, h);
|
||||
glViewport(0, 0, w, h);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
const float sc = 1.5f;
|
||||
const float ar = (float) w / (float) h;
|
||||
|
||||
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 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 float sc = 1.5f;
|
||||
const float ar = (float) w / (float) h;
|
||||
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);
|
||||
// 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);
|
||||
|
||||
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, vert_data.size());
|
||||
glBindVertexArray(vert_vao);
|
||||
glUniform4f(u_color, 1, 0, 0, 1);
|
||||
glDrawArrays(GL_POINTS, 0, figure->vert.size);
|
||||
|
||||
glBindVertexArray(edge_vao);
|
||||
glUniform4f(u_color, 1, 0, 0, 1);
|
||||
glDrawElements(GL_LINES, edge_data.size(), GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(edge_vao);
|
||||
glUniform4f(u_color, 1, 0, 0, 1);
|
||||
glDrawElements(GL_LINES, figure->edge.size, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glBindVertexArray(face_vao);
|
||||
glCullFace(GL_BACK);
|
||||
glUniform4f(u_color, 1, 1, 1, 1);
|
||||
glDrawElements(GL_TRIANGLES, face_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);
|
||||
|
||||
swapbuffers();
|
||||
}
|
||||
// glCullFace(GL_FRONT);
|
||||
// glUniform4f(u_color, .3, .3, 1, 1);
|
||||
// glDrawElements(GL_TRIANGLES, figure->face.size, GL_UNSIGNED_INT, 0);
|
||||
|
||||
void deinit() override {
|
||||
glDeleteProgram(program);
|
||||
glDeleteVertexArrays(1, &vert_vao);
|
||||
}
|
||||
swapbuffers();
|
||||
}
|
||||
|
||||
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();
|
||||
std::vector<int> symbol;
|
||||
symbol.reserve(argc);
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
symbol.push_back(std::stoi(argv[i]));
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return EXIT_SUCCESS;
|
||||
Window *window = new CosetsWindow(symbol);
|
||||
window->run();
|
||||
|
||||
glfwTerminate();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "files.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <streambuf>
|
||||
|
||||
std::string read_all_text(const std::string &file) {
|
||||
@@ -1,114 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
#include "numeric.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
glm::vec4 round(glm::vec4 f, int prec) {
|
||||
auto dec = (float) pow(10, prec);
|
||||
@@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
#include "shader.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "files.hpp"
|
||||
|
||||
55
cosets/src/util/window.cpp
Normal file
55
cosets/src/util/window.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#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);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user