#pragma once #include #include #include #include #include #include #include #include "mirror.hpp" #include "geometry.hpp" #include "solver.hpp" #include namespace vis { template struct Structure { static constexpr auto Rank = R_; static constexpr auto Dim = D_; static constexpr auto Grade = G_; using Affine = Eigen::Transform; using Vertex = Eigen::Vector; using Color = Eigen::Vector; using Cell = Eigen::Array; Points points; Hull hull; std::vector enabled; std::vector colors; Affine transform = Affine::Identity(); template explicit Structure(P &&points_, H &&hull_, Color color_ = Color::Ones()): points(std::forward

(points_)), hull(std::forward(hull_)), enabled(hull.tilings.size(), true), colors(hull.tilings.size(), color_), transform(Affine::Identity()) { } }; template struct VBOs { using Str = Str_; struct Uniform { Eigen::Matrix4f linear; Eigen::Vector4f translation; }; struct Command { unsigned int count, instanceCount, first, baseInstance; }; cgl::Buffer vertices; cgl::Buffer colors; cgl::Buffer indices; cgl::Buffer uniform; cgl::Buffer commands; }; template void upload_structure(entt::registry ®istry) { auto view = registry.view>(); for (auto [entity, structure, vbos]: view.each()) { auto vertices = structure.points.verts.colwise(); auto indices = structure.hull.inds.colwise(); vbos.vertices.put(vertices.begin(), vertices.end()); vbos.indices.put(indices.begin(), indices.end()); } } template void upload_uniforms(entt::registry ®istry) { auto view = registry.view>(); for (auto [entity, structure, vbos]: view.each()) { auto colors = structure.colors; typename VBOs::Uniform uniform{ structure.transform.linear(), structure.transform.translation(), }; vbos.colors.put(colors.begin(), colors.end()); vbos.uniform.put(uniform, GL_STREAM_DRAW); } } template void upload_commands(entt::registry ®istry) { auto view = registry.view>(); for (auto [entity, structure, vbos]: view.each()) { const auto &tilings = structure.hull.tilings; std::vector::Command> commands; for (unsigned int i = 0; i < tilings.size(); ++i) { if (structure.enabled[i]) { auto [first, count] = tilings[i]; commands.push_back({(unsigned int) count, 1, (unsigned int) first, i}); } } vbos.commands.put(commands.begin(), commands.end(), GL_STREAM_DRAW); } } template struct SliceRenderer { using Str = Str_; cgl::pgm::vert defer = cgl::pgm::vert(shaders::deferred_vs_glsl); cgl::pgm::geom slice = cgl::pgm::geom(shaders::slice_gm_glsl); cgl::pgm::frag solid = cgl::pgm::frag(shaders::solid_fs_glsl); cgl::pipeline pipe; cgl::VertexArray vao; SliceRenderer() { pipe.stage(defer); pipe.stage(slice); pipe.stage(solid); vao.iformat(0, 4, GL_UNSIGNED_INT); vao.format(1, 3, GL_FLOAT); glVertexArrayBindingDivisor(vao, 1, 1); } void operator()(entt::registry ®) { auto view = reg.view>(); for (auto [entity, vbos]: view.each()) { glBindProgramPipeline(pipe); glBindBufferBase(GL_UNIFORM_BUFFER, 2, vbos.uniform); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbos.vertices); vao.vertexBuffer(0, vbos.indices); vao.vertexBuffer(1, vbos.colors); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, vbos.commands); glBindVertexArray(vao); glMultiDrawArraysIndirect(GL_POINTS, nullptr, vbos.commands.count(), 0); glBindVertexArray(0); glBindProgramPipeline(0); } } }; }