optimize vertex generation; break edge/face generation
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user