mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 12:02:47 -05:00
Serializable mesh with nlohmann_json
Displays a cube generated by meshlib.hpp (serialtest)
This commit is contained in:
@@ -9,6 +9,10 @@ include(External/glfw.cmake)
|
|||||||
include(External/imgui.cmake)
|
include(External/imgui.cmake)
|
||||||
include(External/eigen.cmake)
|
include(External/eigen.cmake)
|
||||||
include(External/glad.cmake)
|
include(External/glad.cmake)
|
||||||
|
include(External/json.cmake)
|
||||||
|
|
||||||
add_executable(vis main.cpp)
|
add_executable(vis main.cpp)
|
||||||
target_link_libraries(vis glfw glad imgui eigen)
|
target_link_libraries(vis glfw glad imgui eigen nlohmann_json)
|
||||||
|
|
||||||
|
add_executable(serial serialtest.cpp)
|
||||||
|
target_link_libraries(serial eigen nlohmann_json)
|
||||||
|
|||||||
7
External/json.cmake
vendored
Normal file
7
External/json.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FetchContent_Declare(
|
||||||
|
json
|
||||||
|
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
||||||
|
GIT_TAG v3.10.5
|
||||||
|
)
|
||||||
|
SET(JSON_ImplicitConversions OFF CACHE INTERNAL "")
|
||||||
|
FetchContent_MakeAvailable(json)
|
||||||
72
include/ml/meshlib_json.hpp
Normal file
72
include/ml/meshlib_json.hpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "meshlib.hpp"
|
||||||
|
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
template<class Derived>
|
||||||
|
void to_json(nlohmann::json &json, const Eigen::PlainObjectBase<Derived> &mat) {
|
||||||
|
using Scalar = typename Derived::Scalar;
|
||||||
|
|
||||||
|
auto rows = mat.rows();
|
||||||
|
auto cols = mat.cols();
|
||||||
|
|
||||||
|
std::vector<Scalar> vals(mat.size());
|
||||||
|
Map<Derived>(vals.data(), rows, cols) = mat;
|
||||||
|
|
||||||
|
json = {
|
||||||
|
{"rows", rows},
|
||||||
|
{"cols", cols},
|
||||||
|
{"vals", vals},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Derived>
|
||||||
|
void from_json(const nlohmann::json &j, Derived &mat) {
|
||||||
|
using Scalar = typename Derived::Scalar;
|
||||||
|
|
||||||
|
auto rows = j["rows"].get<Eigen::Index>();
|
||||||
|
auto cols = j["cols"].get<Eigen::Index>();
|
||||||
|
auto vals = j["vals"].get<std::vector<Scalar>>();
|
||||||
|
|
||||||
|
mat = Eigen::Map<Derived>(vals.data(), rows, cols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ml {
|
||||||
|
static void to_json(nlohmann::json &json, const ml::MeshBase &mesh) {
|
||||||
|
json = {
|
||||||
|
{"points", mesh.points()},
|
||||||
|
{"cells", mesh.cells()},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const nlohmann::json &j, ml::DynamicMesh &mesh) {
|
||||||
|
mesh = {
|
||||||
|
j["points"].get<DynamicMesh::PointsType>(),
|
||||||
|
j["cells"].get<DynamicMesh::CellsType>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const ml::MeshBase &mesh, std::ostream &out) {
|
||||||
|
nlohmann::json json = mesh;
|
||||||
|
nlohmann::json::to_msgpack(json, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const ml::MeshBase &mesh, const std::string &path) {
|
||||||
|
std::ofstream file(path, std::ios::out | std::ios::binary);
|
||||||
|
write(mesh, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ml::DynamicMesh read(std::istream &in) {
|
||||||
|
nlohmann::json json = nlohmann::json::from_msgpack(in);
|
||||||
|
return json.get<ml::DynamicMesh>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ml::DynamicMesh read(const std::string &path) {
|
||||||
|
std::ifstream file(path, std::ios::in | std::ios::binary);
|
||||||
|
return read(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
97
meshlib.hpp
Normal file
97
meshlib.hpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
|
namespace ml {
|
||||||
|
class MeshBase {
|
||||||
|
public:
|
||||||
|
using PointsType = Eigen::MatrixXf;
|
||||||
|
using CellsType = Eigen::MatrixXi;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual PointsType points() const = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual CellsType cells() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DynamicMesh : public MeshBase {
|
||||||
|
PointsType _points;
|
||||||
|
CellsType _cells;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DynamicMesh() = default;
|
||||||
|
|
||||||
|
explicit DynamicMesh(const MeshBase &mesh)
|
||||||
|
: _points(mesh.points()), _cells(mesh.cells()) {}
|
||||||
|
|
||||||
|
DynamicMesh(PointsType points, CellsType cells)
|
||||||
|
: _points(std::move(points)), _cells(std::move(cells)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] PointsType &points() {
|
||||||
|
return _points;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] PointsType points() const override {
|
||||||
|
return _points;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] CellsType &cells() {
|
||||||
|
return _cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] CellsType cells() const override {
|
||||||
|
return _cells;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CubeMesh : public MeshBase {
|
||||||
|
PointsType::Scalar radius;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CubeMesh(PointsType::Scalar radius = 0.5)
|
||||||
|
: radius(radius) {}
|
||||||
|
|
||||||
|
[[nodiscard]] PointsType points() const override {
|
||||||
|
PointsType out(3, 8);
|
||||||
|
out.transpose() <<
|
||||||
|
+radius, +radius, +radius,
|
||||||
|
+radius, +radius, -radius,
|
||||||
|
+radius, -radius, +radius,
|
||||||
|
+radius, -radius, -radius,
|
||||||
|
-radius, +radius, +radius,
|
||||||
|
-radius, +radius, -radius,
|
||||||
|
-radius, -radius, +radius,
|
||||||
|
-radius, -radius, -radius;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellsType cells() const override {
|
||||||
|
CellsType out(3, 12);
|
||||||
|
out.transpose() <<
|
||||||
|
0b000, 0b001, 0b010, 0b001, 0b010, 0b011,
|
||||||
|
0b100, 0b101, 0b110, 0b101, 0b110, 0b111,
|
||||||
|
|
||||||
|
0b000, 0b001, 0b100, 0b001, 0b100, 0b101,
|
||||||
|
0b010, 0b011, 0b110, 0b011, 0b110, 0b111,
|
||||||
|
|
||||||
|
0b000, 0b010, 0b100, 0b010, 0b100, 0b110,
|
||||||
|
0b001, 0b011, 0b101, 0b011, 0b101, 0b111;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// class CubeMesh : public MeshBase<Eigen::MatrixXf, Eigen::MatrixXi> {
|
||||||
|
// public:
|
||||||
|
// const Eigen::MatrixBase<PointsType> &points() const override {
|
||||||
|
// return PointsType::Random(3, 8);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const Eigen::MatrixBase<CellsType> &cells() const override {
|
||||||
|
// return <#initializer#>;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
}
|
||||||
@@ -4,10 +4,19 @@
|
|||||||
#include <backends/imgui_impl_glfw.h>
|
#include <backends/imgui_impl_glfw.h>
|
||||||
#include <backends/imgui_impl_opengl3.h>
|
#include <backends/imgui_impl_opengl3.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "gldebug.hpp"
|
#include "gldebug.hpp"
|
||||||
|
|
||||||
void show_overlay(float* clear_color) {
|
#include "meshlib.hpp"
|
||||||
|
#include "meshlib_json.hpp"
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
float bg[4] = {0.45f, 0.55f, 0.60f, 1.00f};
|
||||||
|
float fg[4] = {0.19f, 0.86f, 0.33f, 1.00f};
|
||||||
|
};
|
||||||
|
|
||||||
|
void show_overlay(State &state) {
|
||||||
static std::string gl_vendor = (const char *) glGetString(GL_VENDOR);
|
static std::string gl_vendor = (const char *) glGetString(GL_VENDOR);
|
||||||
static std::string gl_renderer = (const char *) glGetString(GL_RENDERER);
|
static std::string gl_renderer = (const char *) glGetString(GL_RENDERER);
|
||||||
static std::string gl_version = (const char *) glGetString(GL_VERSION);
|
static std::string gl_version = (const char *) glGetString(GL_VERSION);
|
||||||
@@ -48,7 +57,7 @@ void show_overlay(float* clear_color) {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImGui::ColorEdit3("Background", state.bg, ImGuiColorEditFlags_Float);
|
ImGui::ColorEdit3("Background", state.bg, ImGuiColorEditFlags_Float);
|
||||||
ImGui::SliderFloat("Alpha", &state.fg[3], 0.0f, 1.0f, "%.2f");
|
ImGui::ColorEdit3("Foreground", state.fg, ImGuiColorEditFlags_Float);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@@ -66,17 +75,10 @@ void set_style() {
|
|||||||
int run(GLFWwindow *window, ImGuiContext *context) {
|
int run(GLFWwindow *window, ImGuiContext *context) {
|
||||||
State state;
|
State state;
|
||||||
|
|
||||||
float points[]{
|
auto mesh = ml::CubeMesh(0.5f);
|
||||||
+0.5f, +0.5f, 0.0f, 1.0f,
|
// auto mesh = ml::read("circle.pak");
|
||||||
+0.5f, -0.5f, 0.0f, 1.0f,
|
|
||||||
-0.5f, +0.5f, 0.0f, 1.0f,
|
|
||||||
-0.5f, -0.5f, 0.0f, 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int inds[]{
|
auto dynamic = (ml::DynamicMesh) mesh;
|
||||||
0, 1, 2,
|
|
||||||
1, 2, 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
glCreateVertexArrays(1, &vao);
|
glCreateVertexArrays(1, &vao);
|
||||||
@@ -84,21 +86,55 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
|||||||
GLuint vbo;
|
GLuint vbo;
|
||||||
glCreateBuffers(1, &vbo);
|
glCreateBuffers(1, &vbo);
|
||||||
|
|
||||||
glNamedBufferData(vbo, sizeof(points), (void *) points, GL_STATIC_DRAW);
|
constexpr size_t point_scalar_size = sizeof(ml::DynamicMesh::PointsType::Scalar);
|
||||||
|
constexpr size_t cell_scalar_size = sizeof(ml::DynamicMesh::CellsType::Scalar);
|
||||||
|
|
||||||
|
glNamedBufferData(
|
||||||
|
vbo,
|
||||||
|
(GLsizeiptr) (point_scalar_size * dynamic.points().size()),
|
||||||
|
dynamic.points().data(),
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
);
|
||||||
glEnableVertexArrayAttrib(vao, 0);
|
glEnableVertexArrayAttrib(vao, 0);
|
||||||
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(float) * 4);
|
glVertexArrayVertexBuffer(vao, 0,
|
||||||
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);
|
vbo, 0,
|
||||||
|
(GLsizeiptr) (point_scalar_size * dynamic.points().rows())
|
||||||
|
);
|
||||||
|
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
|
||||||
|
|
||||||
GLuint ibo;
|
GLuint ibo;
|
||||||
glCreateBuffers(1, &ibo);
|
glCreateBuffers(1, &ibo);
|
||||||
glGetError();
|
glGetError();
|
||||||
glNamedBufferData(ibo, sizeof(inds), (void *) inds, GL_STATIC_DRAW);
|
glNamedBufferData(
|
||||||
|
ibo,
|
||||||
|
(GLsizeiptr) (cell_scalar_size * dynamic.cells().size()),
|
||||||
|
dynamic.cells().data(),
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
);
|
||||||
glVertexArrayElementBuffer(vao, ibo);
|
glVertexArrayElementBuffer(vao, ibo);
|
||||||
|
|
||||||
const char *vs_src = "#version 440\n"
|
const char *vs_src = "#version 440\n"
|
||||||
"layout(location=0) in vec4 pos;"
|
"layout(location=1) uniform float time;"
|
||||||
|
"layout(location=2) uniform mat4 proj;"
|
||||||
|
"layout(location=0) in vec3 pos;"
|
||||||
"void main() {"
|
"void main() {"
|
||||||
" gl_Position = pos;"
|
" float c2 = cos(time * 0.2);"
|
||||||
|
" float s2 = sin(time * 0.2);"
|
||||||
|
" float c3 = cos(time * 0.3);"
|
||||||
|
" float s3 = sin(time * 0.3);"
|
||||||
|
" 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"
|
||||||
|
");"
|
||||||
|
" gl_Position = proj * r2 * r1 * vec4(pos, 1.0);"
|
||||||
"}";
|
"}";
|
||||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vs, 1, &vs_src, nullptr);
|
glShaderSource(vs, 1, &vs_src, nullptr);
|
||||||
@@ -108,7 +144,10 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
|||||||
"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() {"
|
||||||
|
" float d = 1.0 - gl_FragCoord.z;"
|
||||||
|
" d = (d - 0.5) / 0.7 + 0.5;"
|
||||||
" col = ucol;"
|
" col = ucol;"
|
||||||
|
" col.xyz *= d;"
|
||||||
"}";
|
"}";
|
||||||
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(fs, 1, &fs_src, nullptr);
|
glShaderSource(fs, 1, &fs_src, nullptr);
|
||||||
@@ -119,6 +158,10 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
|||||||
glAttachShader(pgm, fs);
|
glAttachShader(pgm, fs);
|
||||||
glLinkProgram(pgm);
|
glLinkProgram(pgm);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
Eigen::Projective3f proj;
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
@@ -132,12 +175,17 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
|||||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||||
glViewport(0, 0, display_w, display_h);
|
glViewport(0, 0, display_w, display_h);
|
||||||
glClearColor(state.bg[0], state.bg[1], state.bg[2], state.bg[3]);
|
glClearColor(state.bg[0], state.bg[1], state.bg[2], state.bg[3]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
auto aspect = (float) display_h / (float) display_w;
|
||||||
|
proj = Eigen::AlignedScaling3f(aspect, 1.0, -1.0);
|
||||||
|
|
||||||
glUseProgram(pgm);
|
glUseProgram(pgm);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
glUniform4fv(0, 1, state.fg);
|
glUniform4fv(0, 1, state.fg);
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
|
glUniform1f(1, (GLfloat) glfwGetTime());
|
||||||
|
glUniformMatrix4fv(2, 1, false, proj.data());
|
||||||
|
glDrawElements(GL_TRIANGLES, (GLsizei) dynamic.cells().size(), GL_UNSIGNED_INT, nullptr);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
53
src/serialtest.cpp
Normal file
53
src/serialtest.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "meshlib.hpp"
|
||||||
|
#include "meshlib_json.hpp"
|
||||||
|
|
||||||
|
class Circle : public ml::MeshBase {
|
||||||
|
public:
|
||||||
|
PointsType::Scalar radius;
|
||||||
|
|
||||||
|
Circle(PointsType::Scalar radius) : radius(radius) {}
|
||||||
|
|
||||||
|
PointsType points() const override {
|
||||||
|
PointsType t(1, 32);
|
||||||
|
for (int i = 0; i < t.size(); ++i) {
|
||||||
|
t(i) = 6.28318f * (float) i / 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointsType out(3, 32);
|
||||||
|
out.array().row(0) = t.array().sin();
|
||||||
|
out.array().row(1) = t.array().cos();
|
||||||
|
out.array().row(2).setZero();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellsType cells() const override {
|
||||||
|
CellsType t(1, 31);
|
||||||
|
for (int i = 0; i < t.size(); ++i) {
|
||||||
|
t(i) = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellsType out(3, 31);
|
||||||
|
out.array().row(0) = 0;
|
||||||
|
out.array().row(1) = t.array();
|
||||||
|
out.array().row(2) = t.array() + 1;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto omesh = Circle(1.0f);
|
||||||
|
|
||||||
|
ml::write(omesh, "circle.pak");
|
||||||
|
|
||||||
|
auto imesh = ml::read("circle.pak");
|
||||||
|
|
||||||
|
std::cout << "= points ===============" << std::endl;
|
||||||
|
std::cout << imesh.points() << std::endl;
|
||||||
|
std::cout << "= cells ================" << std::endl;
|
||||||
|
std::cout << imesh.cells() << std::endl;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user