mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 12:02:47 -05:00
Simplify mesh class
This commit is contained in:
@@ -8,91 +8,37 @@
|
|||||||
#include <Eigen/Eigen>
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
namespace ml {
|
namespace ml {
|
||||||
class MeshBase {
|
using Matrix2Xui = Eigen::Matrix<unsigned int, 2, Eigen::Dynamic>;
|
||||||
|
using Matrix3Xui = Eigen::Matrix<unsigned int, 3, Eigen::Dynamic>;
|
||||||
|
using Matrix4Xui = Eigen::Matrix<unsigned int, 4, Eigen::Dynamic>;
|
||||||
|
|
||||||
|
template<typename PT_, typename CT_>
|
||||||
|
class Mesh {
|
||||||
public:
|
public:
|
||||||
using PointsType = Eigen::MatrixXf;
|
using Points = PT_;
|
||||||
using CellsType = Eigen::MatrixXi;
|
using Cells = CT_;
|
||||||
|
|
||||||
[[nodiscard]] virtual Eigen::Index dim() const = 0;
|
Points points;
|
||||||
|
Cells cells;
|
||||||
|
|
||||||
[[nodiscard]] virtual PointsType points() const = 0;
|
Mesh(Points points, Cells cells)
|
||||||
|
: points(std::move(points)), cells(std::move(cells)) {}
|
||||||
[[nodiscard]] virtual Eigen::Index rank() const = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual CellsType cells() const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DynamicMesh : public MeshBase {
|
auto make_cube(float radius) {
|
||||||
PointsType _points;
|
Eigen::Matrix3Xf points(3, 8);
|
||||||
CellsType _cells;
|
points.fill(radius);
|
||||||
|
for (int i = 0; i < points.cols(); ++i) {
|
||||||
public:
|
for (int j = 0; j < 3; ++j) {
|
||||||
DynamicMesh() = default;
|
if ((i >> j) & 1) {
|
||||||
|
points(j, i) *= -1;
|
||||||
explicit DynamicMesh(const MeshBase &mesh)
|
}
|
||||||
: _points(mesh.points()), _cells(mesh.cells()) {}
|
}
|
||||||
|
|
||||||
DynamicMesh(PointsType points, CellsType cells)
|
|
||||||
: _points(std::move(points)), _cells(std::move(cells)) {}
|
|
||||||
|
|
||||||
Eigen::Index dim() const override {
|
|
||||||
return _points.rows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] PointsType &points() {
|
Matrix3Xui cells(3, 12);
|
||||||
return _points;
|
cells.transpose()
|
||||||
}
|
<< 0b000, 0b001, 0b010, 0b001, 0b010, 0b011,
|
||||||
|
|
||||||
[[nodiscard]] PointsType points() const override {
|
|
||||||
return _points;
|
|
||||||
}
|
|
||||||
|
|
||||||
Eigen::Index rank() const override {
|
|
||||||
return _points.rows();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[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) {}
|
|
||||||
|
|
||||||
Eigen::Index dim() const override {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Eigen::Index rank() const override {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
CellsType cells() const override {
|
|
||||||
CellsType out(3, 12);
|
|
||||||
out.transpose() <<
|
|
||||||
0b000, 0b001, 0b010, 0b001, 0b010, 0b011,
|
|
||||||
0b100, 0b101, 0b110, 0b101, 0b110, 0b111,
|
0b100, 0b101, 0b110, 0b101, 0b110, 0b111,
|
||||||
|
|
||||||
0b000, 0b001, 0b100, 0b001, 0b100, 0b101,
|
0b000, 0b001, 0b100, 0b001, 0b100, 0b101,
|
||||||
@@ -100,57 +46,37 @@ namespace ml {
|
|||||||
|
|
||||||
0b000, 0b010, 0b100, 0b010, 0b100, 0b110,
|
0b000, 0b010, 0b100, 0b010, 0b100, 0b110,
|
||||||
0b001, 0b011, 0b101, 0b011, 0b101, 0b111;
|
0b001, 0b011, 0b101, 0b011, 0b101, 0b111;
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class WireCubeMesh : public MeshBase {
|
return Mesh(points, cells);
|
||||||
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 {
|
template<size_t Dim>
|
||||||
return _dim;
|
auto make_cube_wire(float radius) {
|
||||||
}
|
constexpr size_t NPoints = 1 << Dim;
|
||||||
|
constexpr size_t NCells = Dim * (NPoints >> 1);
|
||||||
|
|
||||||
[[nodiscard]] PointsType points() const override {
|
Eigen::Matrix<float, Dim, NPoints> points;
|
||||||
PointsType out(_dim, _npoints);
|
points.fill(radius);
|
||||||
out.fill(radius);
|
for (int i = 0; i < points.cols(); ++i) {
|
||||||
for (int i = 0; i < out.cols(); ++i) {
|
for (int j = 0; j < Dim; ++j) {
|
||||||
for (int j = 0; j < _dim; ++j) {
|
|
||||||
if ((i >> j) & 1) {
|
if ((i >> j) & 1) {
|
||||||
out(j, i) *= -1;
|
points(j, i) *= -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Eigen::Index rank() const override {
|
Eigen::Matrix<unsigned int, 2, NCells> cells;
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] CellsType cells() const override {
|
|
||||||
CellsType out(2, _nlines);
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int i = 0; i < _npoints; ++i) {
|
for (int i = 0; i < NPoints; ++i) {
|
||||||
for (int j = 0; j < _dim; ++j) {
|
for (int j = 0; j < Dim; ++j) {
|
||||||
if ((i >> j) & 1) {
|
if ((i >> j) & 1) {
|
||||||
out(0, k) = i;
|
cells(0, k) = i;
|
||||||
out(1, k) = i ^ (1 << j);
|
cells(1, k) = i ^ (1 << j);
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
|
||||||
|
return Mesh(points, cells);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,49 +24,45 @@ namespace Eigen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
void from_json(const nlohmann::json &j, Derived &mat) {
|
void from_json(const nlohmann::json &j, Derived &d) {
|
||||||
using Scalar = typename Derived::Scalar;
|
using Scalar = typename Derived::Scalar;
|
||||||
|
|
||||||
auto rows = j["rows"].get<Eigen::Index>();
|
auto rows = j["rows"].get<Index>();
|
||||||
auto cols = j["cols"].get<Eigen::Index>();
|
auto cols = j["cols"].get<Index>();
|
||||||
auto vals = j["vals"].get<std::vector<Scalar>>();
|
auto vals = j["vals"].get<std::vector<Scalar>>();
|
||||||
|
|
||||||
mat = Eigen::Map<Derived>(vals.data(), rows, cols);
|
d = Map<Derived>(vals.data(), rows, cols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace nlohmann {
|
||||||
|
template<typename PT_, typename CT_>
|
||||||
|
struct adl_serializer<ml::Mesh<PT_, CT_>> {
|
||||||
|
static void to_json(json &j, const ml::Mesh<PT_, CT_> &m) {
|
||||||
|
j = {
|
||||||
|
{"points", m.points},
|
||||||
|
{"cells", m.cells},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static ml::Mesh<PT_, CT_> from_json(const json &j) {
|
||||||
|
return ml::Mesh<PT_, CT_>(
|
||||||
|
j["points"].get<PT_>(),
|
||||||
|
j["cells"].get<CT_>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace ml {
|
namespace ml {
|
||||||
static void to_json(nlohmann::json &json, const ml::MeshBase &mesh) {
|
template<typename PT_, typename CT_>
|
||||||
json = {
|
void write(const ml::Mesh<PT_, CT_> &mesh, std::ostream &&out) {
|
||||||
{"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 json = mesh;
|
||||||
nlohmann::json::to_msgpack(json, out);
|
nlohmann::json::to_msgpack(json, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const ml::MeshBase &mesh, const std::string &path) {
|
template<typename M_>
|
||||||
std::ofstream file(path, std::ios::out | std::ios::binary);
|
M_ read(std::istream &&in) {
|
||||||
write(mesh, file);
|
return nlohmann::json::from_msgpack(in).get<M_>();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ public:
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GLuint upload(const T& data, GLenum mode = GL_STATIC_DRAW) {
|
||||||
|
return upload(data.begin(), data.end(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
~Buffer() {
|
~Buffer() {
|
||||||
// delete silently ignores 0.
|
// delete silently ignores 0.
|
||||||
glDeleteBuffers(1, &id);
|
glDeleteBuffers(1, &id);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <Eigen/Eigen>
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
template<class T_>
|
template<typename T_>
|
||||||
struct Buffer;
|
struct Buffer;
|
||||||
|
|
||||||
template<class ...Fmt_>
|
template<class ...Fmt_>
|
||||||
@@ -66,18 +66,23 @@ struct AutoFormat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AutoFormat<double> {
|
struct AutoFormat<GLdouble> {
|
||||||
using Fmt = LFormat<double, GL_DOUBLE, 1>;
|
using Fmt = LFormat<GLdouble, GL_DOUBLE, 1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AutoFormat<float> {
|
struct AutoFormat<GLfloat> {
|
||||||
using Fmt = Format<float, GL_FLOAT, 1>;
|
using Fmt = Format<GLfloat, GL_FLOAT, 1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AutoFormat<int> {
|
struct AutoFormat<GLint> {
|
||||||
using Fmt = IFormat<int, GL_INT, 1>;
|
using Fmt = IFormat<GLint, GL_INT, 1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AutoFormat<GLuint> {
|
||||||
|
using Fmt = IFormat<GLuint, GL_UNSIGNED_INT, 1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar, int Dim>
|
template<typename Scalar, int Dim>
|
||||||
|
|||||||
40
src/main.cpp
40
src/main.cpp
@@ -128,45 +128,23 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
|||||||
|
|
||||||
Buffer<GLuint> ind_buf;
|
Buffer<GLuint> ind_buf;
|
||||||
Buffer<Eigen::Vector3f> vert_buf;
|
Buffer<Eigen::Vector3f> vert_buf;
|
||||||
Buffer<Eigen::Vector3f> vert2_buf;
|
|
||||||
|
Buffer<GLuint> ind4d_buf;
|
||||||
|
Buffer<Eigen::Vector4f> vert4d_buf;
|
||||||
|
|
||||||
VertexArray<Eigen::Vector3f> vao(vert_buf);
|
VertexArray<Eigen::Vector3f> vao(vert_buf);
|
||||||
glVertexArrayElementBuffer(vao, ind_buf);
|
glVertexArrayElementBuffer(vao, ind_buf);
|
||||||
|
|
||||||
auto mesh = ml::CubeMesh(0.25f);
|
|
||||||
|
|
||||||
auto ind_data = mesh.cells();
|
|
||||||
auto ind_flat = ind_data.reshaped();
|
|
||||||
auto elements = ind_buf.upload(ind_flat.begin(), ind_flat.end(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// todo add <Dim, Rank> to DynamicMesh
|
|
||||||
// need to do weird piping because dynamicmesh returns dynamic-sized matrix, VertexArray requires a static-sized matrix
|
|
||||||
auto vert_data_dyn = mesh.points();
|
|
||||||
Eigen::Ref<Eigen::Matrix3Xf> vert_data(vert_data_dyn);
|
|
||||||
auto vert_flat = vert_data.colwise();
|
|
||||||
vert_buf.upload(vert_flat.begin(), vert_flat.end(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
auto mesh2 = ml::CubeMesh(0.5f);
|
|
||||||
auto vert2_data_dyn = mesh2.points();
|
|
||||||
Eigen::Ref<Eigen::Matrix3Xf> vert2_data(vert2_data_dyn);
|
|
||||||
auto vert2_flat = vert2_data.colwise();
|
|
||||||
vert2_buf.upload(vert2_flat.begin(), vert2_flat.end(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
auto mesh4d = ml::WireCubeMesh(4, 0.33f);
|
|
||||||
|
|
||||||
Buffer<GLuint> ind4d_buf;
|
|
||||||
Buffer<Eigen::Vector4f> vert4d_buf;
|
|
||||||
VertexArray<Eigen::Vector4f> vao4d(vert4d_buf);
|
VertexArray<Eigen::Vector4f> vao4d(vert4d_buf);
|
||||||
glVertexArrayElementBuffer(vao4d, ind4d_buf);
|
glVertexArrayElementBuffer(vao4d, ind4d_buf);
|
||||||
|
|
||||||
auto ind4d_data = mesh4d.cells();
|
auto mesh = ml::make_cube(0.22f);
|
||||||
auto ind4d_flat = ind4d_data.reshaped();
|
auto elements = (GLint) ind_buf.upload(mesh.cells.reshaped());
|
||||||
auto elements4d = ind4d_buf.upload(ind4d_flat.begin(), ind4d_flat.end(), GL_STATIC_DRAW);
|
vert_buf.upload(mesh.points.colwise());
|
||||||
|
|
||||||
auto vert4d_data_dyn = mesh4d.points();
|
auto mesh4d = ml::make_cube_wire<4>(0.33f);
|
||||||
Eigen::Ref<Eigen::Matrix4Xf> vert4d_data(vert4d_data_dyn);
|
auto elements4d = (GLint) ind4d_buf.upload(mesh4d.cells.reshaped());
|
||||||
auto vert4d_flat = vert4d_data.colwise();
|
vert4d_buf.upload(mesh4d.points.colwise());
|
||||||
vert4d_buf.upload(vert4d_flat.begin(), vert4d_flat.end(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
VertexShader vs(std::ifstream("res/shaders/main.vert.glsl"));
|
VertexShader vs(std::ifstream("res/shaders/main.vert.glsl"));
|
||||||
VertexShader vs4d(std::ifstream("res/shaders/4d.vert.glsl"));
|
VertexShader vs4d(std::ifstream("res/shaders/4d.vert.glsl"));
|
||||||
|
|||||||
@@ -6,48 +6,40 @@
|
|||||||
#include <ml/meshlib.hpp>
|
#include <ml/meshlib.hpp>
|
||||||
#include <ml/meshlib_json.hpp>
|
#include <ml/meshlib_json.hpp>
|
||||||
|
|
||||||
class Circle : public ml::MeshBase {
|
auto make_circle(float radius, size_t npoints = 32) {
|
||||||
public:
|
Eigen::Array<float, 1, Eigen::Dynamic> theta(1, npoints);
|
||||||
PointsType::Scalar radius;
|
for (int i = 0; i < theta.size(); ++i) {
|
||||||
|
theta(i) = (float) M_PI * 2.0f * (float) i / (float) npoints;
|
||||||
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);
|
Eigen::Array<float, 3, Eigen::Dynamic> points(3, npoints);
|
||||||
out.array().row(0) = t.array().sin();
|
points.row(0) = theta.sin();
|
||||||
out.array().row(1) = t.array().cos();
|
points.row(1) = theta.cos();
|
||||||
out.array().row(2).setZero();
|
points.row(2).setZero();
|
||||||
return out;
|
|
||||||
|
Eigen::Array<unsigned int, 1, Eigen::Dynamic> idx(1, npoints - 1);
|
||||||
|
for (int i = 0; i < idx.size(); ++i) {
|
||||||
|
idx(i) = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellsType cells() const override {
|
Eigen::Array<unsigned int, 3, Eigen::Dynamic> cells(3, npoints - 1);
|
||||||
CellsType t(1, 31);
|
cells.row(0) = 0;
|
||||||
for (int i = 0; i < t.size(); ++i) {
|
cells.row(1) = idx;
|
||||||
t(i) = i;
|
cells.row(2) = idx + 1;
|
||||||
}
|
|
||||||
|
|
||||||
CellsType out(3, 31);
|
return ml::Mesh(points, cells);
|
||||||
out.array().row(0) = 0;
|
}
|
||||||
out.array().row(1) = t.array();
|
|
||||||
out.array().row(2) = t.array() + 1;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto omesh = Circle(1.0f);
|
std::string path = "circle.pak";
|
||||||
|
|
||||||
ml::write(omesh, "circle.pak");
|
auto omesh = make_circle(1.0f);
|
||||||
|
using MT = decltype(omesh);
|
||||||
|
|
||||||
auto imesh = ml::read("circle.pak");
|
ml::write(omesh, std::ofstream(path, std::ios::out | std::ios::binary));
|
||||||
|
|
||||||
std::cout << "= points ===============" << std::endl;
|
auto imesh = ml::read<MT>(std::ifstream(path, std::ios::in | std::ios::binary));
|
||||||
std::cout << imesh.points() << std::endl;
|
|
||||||
std::cout << "= cells ================" << std::endl;
|
std::cout << imesh.points << std::endl;
|
||||||
std::cout << imesh.cells() << std::endl;
|
std::cout << imesh.cells << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user