Add wireframe hypercube

This commit is contained in:
2022-02-16 18:07:30 -05:00
parent ae10f00127
commit c302cc03a5
4 changed files with 185 additions and 3 deletions

View File

@@ -13,8 +13,12 @@ namespace ml {
using PointsType = Eigen::MatrixXf; using PointsType = Eigen::MatrixXf;
using CellsType = Eigen::MatrixXi; using CellsType = Eigen::MatrixXi;
[[nodiscard]] virtual Eigen::Index dim() const = 0;
[[nodiscard]] virtual PointsType points() const = 0; [[nodiscard]] virtual PointsType points() const = 0;
[[nodiscard]] virtual Eigen::Index rank() const = 0;
[[nodiscard]] virtual CellsType cells() const = 0; [[nodiscard]] virtual CellsType cells() const = 0;
}; };
@@ -31,6 +35,10 @@ namespace ml {
DynamicMesh(PointsType points, CellsType cells) DynamicMesh(PointsType points, CellsType cells)
: _points(std::move(points)), _cells(std::move(cells)) {} : _points(std::move(points)), _cells(std::move(cells)) {}
Eigen::Index dim() const override {
return _points.rows();
}
[[nodiscard]] PointsType &points() { [[nodiscard]] PointsType &points() {
return _points; return _points;
} }
@@ -39,6 +47,10 @@ namespace ml {
return _points; return _points;
} }
Eigen::Index rank() const override {
return _points.rows();
}
[[nodiscard]] CellsType &cells() { [[nodiscard]] CellsType &cells() {
return _cells; return _cells;
} }
@@ -55,6 +67,10 @@ namespace ml {
explicit CubeMesh(PointsType::Scalar radius = 0.5) explicit CubeMesh(PointsType::Scalar radius = 0.5)
: radius(radius) {} : radius(radius) {}
Eigen::Index dim() const override {
return 3;
}
[[nodiscard]] PointsType points() const override { [[nodiscard]] PointsType points() const override {
PointsType out(3, 8); PointsType out(3, 8);
out.transpose() << out.transpose() <<
@@ -69,6 +85,10 @@ namespace ml {
return out; return out;
} }
Eigen::Index rank() const override {
return 3;
}
CellsType cells() const override { CellsType cells() const override {
CellsType out(3, 12); CellsType out(3, 12);
out.transpose() << out.transpose() <<
@@ -83,4 +103,54 @@ namespace ml {
return out; return out;
} }
}; };
class WireCubeMesh : public MeshBase {
PointsType::Scalar radius;
long _dim;
long _npoints;
long _nlines;
public:
explicit WireCubeMesh(long dim = 3, PointsType::Scalar radius = 0.5)
: _dim(dim), radius(radius) {
_npoints = 1 << _dim;
_nlines = _dim * (_npoints >> 1);
}
Eigen::Index dim() const override {
return _dim;
}
[[nodiscard]] PointsType points() const override {
PointsType out(_dim, _npoints);
out.fill(radius);
for (int i = 0; i < out.cols(); ++i) {
for (int j = 0; j < _dim; ++j) {
if ((i >> j) & 1) {
out(j, i) *= -1;
}
}
}
return out;
}
Eigen::Index rank() const override {
return 2;
}
[[nodiscard]] CellsType cells() const override {
CellsType out(2, _nlines);
int k = 0;
for (int i = 0; i < _npoints; ++i) {
for (int j = 0; j < _dim; ++j) {
if ((i >> j) & 1) {
out(0, k) = i;
out(1, k) = i ^ (1 << j);
k++;
}
}
}
return out;
}
};
} }

40
res/shaders/4d.vert.glsl Normal file
View File

@@ -0,0 +1,40 @@
#version 440
layout(location=1) uniform float time;
layout(location=2) uniform mat4 proj;
layout(location=0) in vec4 pos;
void main() {
float c2 = cos(time * 0.2);
float s2 = sin(time * 0.2);
float c3 = cos(time * 0.3);
float s3 = sin(time * 0.3);
float c4 = cos(time * 0.25);
float s4 = sin(time * 0.25);
mat4 r1 = mat4(
c2, -s2, 0.0, 0.0,
s2, c2, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 r2 = mat4(
c3, 0.0, -s3, 0.0,
0.0, 1.0, 0.0, 0.0,
s3, 0.0, c3, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 r3 = mat4(
1.0, 0.0, 0.0, 0.0,
0.0, c4, 0.0, -s4,
0.0, 0.0, 1.0, 0.0,
0.0, s4, 0.0, c4
);
vec4 pos = r2 * r1 * r3 * pos;
gl_Position = proj * vec4(pos.xyz / (1 - pos.w), 1.0);
}

View File

@@ -1,6 +1,7 @@
#version 440 #version 440
layout(location=0) uniform vec4 ucol; layout(location=0) uniform vec4 ucol;
layout(location=0) out vec4 col; layout(location=0) out vec4 col;
void main() { void main() {

View File

@@ -75,7 +75,7 @@ void set_style() {
int run(GLFWwindow *window, ImGuiContext *context) { int run(GLFWwindow *window, ImGuiContext *context) {
State state; State state;
auto mesh = ml::CubeMesh(0.5f); auto mesh = ml::CubeMesh(0.25f);
// auto mesh = ml::read("circle.pak"); // auto mesh = ml::read("circle.pak");
auto dynamic = (ml::DynamicMesh) mesh; auto dynamic = (ml::DynamicMesh) mesh;
@@ -113,6 +113,39 @@ int run(GLFWwindow *window, ImGuiContext *context) {
); );
glVertexArrayElementBuffer(vao, ibo); glVertexArrayElementBuffer(vao, ibo);
auto wire_mesh = ml::WireCubeMesh(4, 0.33f);
auto wire_dynamic = (ml::DynamicMesh) wire_mesh;
GLuint wire_vao;
glCreateVertexArrays(1, &wire_vao);
GLuint wire_vbo;
glCreateBuffers(1, &wire_vbo);
glNamedBufferData(
wire_vbo,
(GLsizeiptr) (point_scalar_size * wire_dynamic.points().size()),
wire_dynamic.points().data(),
GL_STATIC_DRAW
);
glEnableVertexArrayAttrib(wire_vao, 0);
glVertexArrayVertexBuffer(wire_vao, 0,
wire_vbo, 0,
(GLsizeiptr) (point_scalar_size * wire_dynamic.points().rows())
);
glVertexArrayAttribFormat(wire_vao, 0, 4, GL_FLOAT, GL_FALSE, 0);
GLuint wire_ibo;
glCreateBuffers(1, &wire_ibo);
glGetError();
glNamedBufferData(
wire_ibo,
(GLsizeiptr) (cell_scalar_size * wire_dynamic.cells().size()),
wire_dynamic.cells().data(),
GL_STATIC_DRAW
);
glVertexArrayElementBuffer(wire_vao, wire_ibo);
std::ifstream vs_file("res/shaders/main.vert.glsl"); std::ifstream vs_file("res/shaders/main.vert.glsl");
std::string vs_src( std::string vs_src(
(std::istreambuf_iterator<char>(vs_file)), (std::istreambuf_iterator<char>(vs_file)),
@@ -125,6 +158,18 @@ int run(GLFWwindow *window, ImGuiContext *context) {
glShaderSource(vs, 1, &vs_str, nullptr); glShaderSource(vs, 1, &vs_str, nullptr);
glCompileShader(vs); glCompileShader(vs);
std::ifstream wire_vs_file("res/shaders/4d.vert.glsl");
std::string wire_vs_src(
(std::istreambuf_iterator<char>(wire_vs_file)),
std::istreambuf_iterator<char>()
);
wire_vs_file.close();
const char *wire_vs_str = wire_vs_src.c_str();
GLuint wire_vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(wire_vs, 1, &wire_vs_str, nullptr);
glCompileShader(wire_vs);
std::ifstream fs_file("res/shaders/main.frag.glsl"); std::ifstream fs_file("res/shaders/main.frag.glsl");
std::string fs_src( std::string fs_src(
(std::istreambuf_iterator<char>(fs_file)), (std::istreambuf_iterator<char>(fs_file)),
@@ -142,6 +187,11 @@ int run(GLFWwindow *window, ImGuiContext *context) {
glAttachShader(pgm, fs); glAttachShader(pgm, fs);
glLinkProgram(pgm); glLinkProgram(pgm);
GLuint wire_pgm = glCreateProgram();
glAttachShader(wire_pgm, wire_vs);
glAttachShader(wire_pgm, fs);
glLinkProgram(wire_pgm);
GLint link_status; GLint link_status;
glGetProgramiv(pgm, GL_LINK_STATUS, &link_status); glGetProgramiv(pgm, GL_LINK_STATUS, &link_status);
if (!link_status) { if (!link_status) {
@@ -154,8 +204,16 @@ int run(GLFWwindow *window, ImGuiContext *context) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
glEnable(GL_BLEND); glGetProgramiv(wire_pgm, GL_LINK_STATUS, &link_status);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (!link_status) {
std::cerr << "Wire program link failed." << std::endl;
GLint vs_comp_status, fs_comp_status;
glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_comp_status);
glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_comp_status);
std::cerr << "vs compiled: " << std::boolalpha << (bool) vs_comp_status << std::endl;
std::cerr << "fs compiled: " << std::boolalpha << (bool) fs_comp_status << std::endl;
return EXIT_FAILURE;
}
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@@ -188,6 +246,15 @@ int run(GLFWwindow *window, ImGuiContext *context) {
glBindVertexArray(0); glBindVertexArray(0);
glUseProgram(0); glUseProgram(0);
glUseProgram(wire_pgm);
glBindVertexArray(wire_vao);
glUniform4fv(0, 1, state.fg);
glUniform1f(1, (GLfloat) glfwGetTime());
glUniformMatrix4fv(2, 1, false, proj.data());
glDrawElements(GL_LINES, (GLsizei) wire_dynamic.cells().size(), GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glUseProgram(0);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
@@ -196,6 +263,10 @@ int run(GLFWwindow *window, ImGuiContext *context) {
glDeleteBuffers(1, &ibo); glDeleteBuffers(1, &ibo);
glDeleteVertexArrays(1, &vao); glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &wire_vbo);
glDeleteBuffers(1, &wire_ibo);
glDeleteVertexArrays(1, &wire_vao);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }