diff --git a/src/MarlinSimulator/hardware/KinematicSystem.cpp b/src/MarlinSimulator/hardware/KinematicSystem.cpp index 2936a51..ddefabf 100644 --- a/src/MarlinSimulator/hardware/KinematicSystem.cpp +++ b/src/MarlinSimulator/hardware/KinematicSystem.cpp @@ -144,7 +144,7 @@ void KinematicSystem::collect_steppers() { #endif } -CartesianKinematicSystem::CartesianKinematicSystem(std::function on_kinematic_update) : KinematicSystem(on_kinematic_update) { +CartesianKinematicSystem::CartesianKinematicSystem(std::function on_kinematic_update) : KinematicSystem(on_kinematic_update) { collect_steppers(); srand(time(0)); @@ -200,7 +200,7 @@ void CartesianKinematicSystem::kinematic_update() { std::static_pointer_cast(steppers[AxisIndex::Z])->steps() / steps_per_unit[2] * (((INVERT_Z_DIR * 2) - 1) * -1.0) }; - std::vector extruder {}; + extruder.clear(); for (size_t i = 0; i < EXTRUDERS; ++i) { extruder.push_back(std::static_pointer_cast(steppers[AxisIndex::E0 + i])->steps() / steps_per_unit[3 + (i * distinct_e_factors)] * (((extruder_invert_dir[i] * 2) - 1) * -1.0)); } @@ -341,7 +341,7 @@ glm::vec3 DeltaKinematicSystem::forward_kinematics(const double z1, const double }; } -DeltaKinematicSystem::DeltaKinematicSystem(std::function on_kinematic_update) : KinematicSystem(on_kinematic_update) { +DeltaKinematicSystem::DeltaKinematicSystem(std::function on_kinematic_update) : KinematicSystem(on_kinematic_update) { #ifdef DELTA_HEIGHT delta_height = DELTA_HEIGHT; diff --git a/src/MarlinSimulator/hardware/KinematicSystem.h b/src/MarlinSimulator/hardware/KinematicSystem.h index 20c2ed0..f37513d 100644 --- a/src/MarlinSimulator/hardware/KinematicSystem.h +++ b/src/MarlinSimulator/hardware/KinematicSystem.h @@ -23,7 +23,7 @@ struct kinematic_state { class KinematicSystem : public VirtualPrinter::Component { public: - KinematicSystem(std::function on_kinematic_update) : VirtualPrinter::Component("Kinematic System"), on_kinematic_update(on_kinematic_update) {}; + KinematicSystem(std::function on_kinematic_update) : VirtualPrinter::Component("Kinematic System"), on_kinematic_update(on_kinematic_update) {}; virtual void kinematic_update() = 0; void collect_steppers(); @@ -31,19 +31,20 @@ class KinematicSystem : public VirtualPrinter::Component { std::vector hardware_offset {}; std::vector> steppers; kinematic_state state{}; - std::function on_kinematic_update; + std::function on_kinematic_update; }; class CartesianKinematicSystem : public KinematicSystem { public: - CartesianKinematicSystem(std::function on_kinematic_update); + CartesianKinematicSystem(std::function on_kinematic_update); virtual void ui_widget() override; virtual void kinematic_update() override; + std::vector extruder {}; }; class DeltaKinematicSystem : public KinematicSystem { public: - DeltaKinematicSystem(std::function on_kinematic_update); + DeltaKinematicSystem(std::function on_kinematic_update); virtual void ui_widget() override; virtual void kinematic_update() override; diff --git a/src/MarlinSimulator/hardware/SDCard.h b/src/MarlinSimulator/hardware/SDCard.h index f65aeff..82121f3 100644 --- a/src/MarlinSimulator/hardware/SDCard.h +++ b/src/MarlinSimulator/hardware/SDCard.h @@ -31,12 +31,12 @@ class SDCard: public SPISlavePeripheral { virtual ~SDCard() {}; void update() {} - + const std::string file_dialog_key = "ChooseSDFileDlgKey"; void ui_widget() { if (ImGui::Button("Select Image (FAT32)")) { - ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Choose File", "FAT32 Disk Image(*.img){.img},.*", "."); + ImGuiFileDialog::Instance()->OpenDialog(file_dialog_key, "Choose File", "FAT32 Disk Image(*.img){.img},.*", "."); } - if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey", ImGuiWindowFlags_NoDocking)) { + if (ImGuiFileDialog::Instance()->Display(file_dialog_key, ImGuiWindowFlags_NoDocking)) { if (ImGuiFileDialog::Instance()->IsOk()) { image_filename = ImGuiFileDialog::Instance()->GetFilePathName(); sd_present = image_exists(); diff --git a/src/MarlinSimulator/renderer/gl.h b/src/MarlinSimulator/renderer/gl.h index 66ea3c3..0a99972 100644 --- a/src/MarlinSimulator/renderer/gl.h +++ b/src/MarlinSimulator/renderer/gl.h @@ -1,10 +1,40 @@ #pragma once +#include + #include #include namespace renderer { +template struct gl_enum_to_type; +template<> struct gl_enum_to_type { using value_type = float; }; +template<> struct gl_enum_to_type { using value_type = glm::vec2; }; +template<> struct gl_enum_to_type { using value_type = glm::vec3; }; +template<> struct gl_enum_to_type { using value_type = glm::vec4; }; +template<> struct gl_enum_to_type { using value_type = double; }; +template<> struct gl_enum_to_type { using value_type = int; }; +template<> struct gl_enum_to_type { using value_type = glm::ivec2; }; +template<> struct gl_enum_to_type { using value_type = glm::ivec3; }; +template<> struct gl_enum_to_type { using value_type = glm::ivec4; }; +template<> struct gl_enum_to_type { using value_type = unsigned int; }; +template<> struct gl_enum_to_type { using value_type = glm::uvec2; }; +template<> struct gl_enum_to_type { using value_type = glm::uvec3; }; +template<> struct gl_enum_to_type { using value_type = glm::uvec4; }; +template<> struct gl_enum_to_type { using value_type = bool; }; +template<> struct gl_enum_to_type { using value_type = glm::bvec2; }; +template<> struct gl_enum_to_type { using value_type = glm::bvec3; }; +template<> struct gl_enum_to_type { using value_type = glm::bvec4; }; +template<> struct gl_enum_to_type { using value_type = glm::mat2; }; +template<> struct gl_enum_to_type { using value_type = glm::mat3; }; +template<> struct gl_enum_to_type { using value_type = glm::mat4; }; +template<> struct gl_enum_to_type { using value_type = glm::mat2x3; }; +template<> struct gl_enum_to_type { using value_type = glm::mat2x4; }; +template<> struct gl_enum_to_type { using value_type = glm::mat3x2; }; +template<> struct gl_enum_to_type { using value_type = glm::mat3x4; }; +template<> struct gl_enum_to_type { using value_type = glm::mat4x2; }; +template<> struct gl_enum_to_type { using value_type = glm::mat4x3; }; + template struct type_to_gl_enum; template<> struct type_to_gl_enum { static constexpr uint32_t value = GL_FLOAT; }; template<> struct type_to_gl_enum { static constexpr uint32_t value = GL_FLOAT_VEC2; }; @@ -37,6 +67,58 @@ template<> struct type_to_gl_enum { static constexpr uint32_t value = G template<> struct type_to_gl_enum{ static constexpr uint32_t value = GL_UNSIGNED_SHORT; }; template<> struct type_to_gl_enum{ static constexpr uint32_t value = GL_BYTE; }; +template struct gl_uniform; +template<> struct gl_uniform { using value_type = decltype(glUniform1fv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform1fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform2fv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform2fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform3fv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform3fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform4fv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform4fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform1iv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform1iv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform2iv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform2iv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform3iv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform3iv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform4iv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform4iv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform1uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform1uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform2uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform2uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform3uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform3uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform4uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform4uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform1uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform1uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform2uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform2uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform3uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform3uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniform4uiv); static constexpr bool is_matrix = false; gl_enum_to_type::value_type *value; value_type invoke = glUniform4uiv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix2fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix2fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix3fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix3fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix4fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix4fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix2x3fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix2x3fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix2x4fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix2x4fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix3x2fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix3x2fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix3x4fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix3x4fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix4x2fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix4x2fv; }; +template<> struct gl_uniform { using value_type = decltype(glUniformMatrix4x3fv); static constexpr bool is_matrix = true; gl_enum_to_type::value_type *value; value_type invoke = glUniformMatrix4x3fv; }; +using gl_uniform_t = std::variant< + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform, + gl_uniform, gl_uniform, gl_uniform +>; + +template struct gl_texture_parameter; +template<> struct gl_texture_parameter { using value_type = decltype(glTexParameterfv); value_type invoke = glTexParameterfv; }; +template<> struct gl_texture_parameter { using value_type = decltype(glTexParameteriv); value_type invoke = glTexParameteriv; }; +template<> struct gl_texture_parameter { using value_type = decltype(glTexParameterIuiv); value_type invoke = glTexParameterIuiv; }; + +template struct gl_texture_image; +template<> struct gl_texture_image<1> { using value_type = decltype(glTexImage1D); value_type invoke = glTexImage1D; }; +template<> struct gl_texture_image<2> { using value_type = decltype(glTexImage2D); value_type invoke = glTexImage2D; }; +template<> struct gl_texture_image<3> { using value_type = decltype(glTexImage3D); value_type invoke = glTexImage3D; }; + +template struct gl_texture_subimage; +template<> struct gl_texture_subimage<1> { using value_type = decltype(glTexSubImage1D); value_type invoke = glTexSubImage1D; }; +template<> struct gl_texture_subimage<2> { using value_type = decltype(glTexSubImage2D); value_type invoke = glTexSubImage2D; }; +template<> struct gl_texture_subimage<3> { using value_type = decltype(glTexSubImage3D); value_type invoke = glTexSubImage3D; }; + struct data_descriptor_element_t { public: template static constexpr data_descriptor_element_t build(){ return data_descriptor_element_t(T::length(), type_to_gl_enum::value, sizeof(T)); }; @@ -47,7 +129,7 @@ struct data_descriptor_element_t { constexpr data_descriptor_element_t(const uint32_t elements, const uint32_t gl_enum, const uint32_t length) : elements{elements}, gl_enum{gl_enum}, length{length} {}; }; -enum class Primitive : uint32_t { +enum class GeometryPrimitive : uint32_t { POINTS = GL_POINTS, LINE_STRIP = GL_LINE_STRIP, LINE_LOOP = GL_LINE_LOOP, diff --git a/src/MarlinSimulator/renderer/renderer.cpp b/src/MarlinSimulator/renderer/renderer.cpp new file mode 100644 index 0000000..3df90d3 --- /dev/null +++ b/src/MarlinSimulator/renderer/renderer.cpp @@ -0,0 +1,19 @@ +#include "renderer.h" + +namespace renderer { + +template<> void ShaderProgramInstance::set_uniform(std::string name, float* value) { + using gl_uniform_type = gl_uniform::value>; + if (m_program->m_uniforms.count(name)) { + auto uniform = m_program->m_uniforms[name]; + m_uniforms[uniform.location] = shader_uniform_t { + uniform, + gl_uniform_type {value}, + [](shader_attr_t& uniform_desc, gl_uniform_t& uniform_data) { + gl_uniform_type().invoke(uniform_desc.location, uniform_desc.size, std::get(uniform_data).value); + }, + }; + } +} + +} diff --git a/src/MarlinSimulator/renderer/renderer.h b/src/MarlinSimulator/renderer/renderer.h index 61e91b2..20e2cb3 100644 --- a/src/MarlinSimulator/renderer/renderer.h +++ b/src/MarlinSimulator/renderer/renderer.h @@ -1,10 +1,16 @@ #pragma once -#include -#include - #include #include +#include + +#include "../resources/resources.h" +#include +#include +#include +#include +#include +#include #include "gl.h" @@ -17,41 +23,43 @@ struct vertex_data_t { static constexpr std::size_t elements = 3; static constexpr std::array descriptor { - data_descriptor_element_t::build(), - data_descriptor_element_t::build(), - data_descriptor_element_t::build() + data_descriptor_element_t::build(), + data_descriptor_element_t::build(), + data_descriptor_element_t::build(), }; }; -typedef enum t_attrib_id { - attrib_position, - attrib_normal, - attrib_color -} t_attrib_id; +struct shader_attr_t { + uint32_t location; + std::string name; + uint32_t gl_type; + int32_t size; + bool active = true; +}; class ShaderProgram { public: - static GLuint loadProgram(const char* vertex_string, const char* fragment_string, const char* geometry_string = nullptr) { + ShaderProgram(GLuint program_id) : m_program_id {program_id} { } + + static GLuint load_program(char const* vertex_string, char const* fragment_string, char const* geometry_string = nullptr) { GLuint vertex_shader = 0, fragment_shader = 0, geometry_shader = 0; if (vertex_string != nullptr) { - vertex_shader = loadShader(GL_VERTEX_SHADER, vertex_string); + vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_string); } if (fragment_string != nullptr) { - fragment_shader = loadShader(GL_FRAGMENT_SHADER, fragment_string); + fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_string); } if (geometry_string != nullptr) { - geometry_shader = loadShader(GL_GEOMETRY_SHADER, geometry_string); + geometry_shader = load_shader(GL_GEOMETRY_SHADER, geometry_string); } GLuint shader_program = glCreateProgram(); - glAttachShader( shader_program, vertex_shader ); - glAttachShader( shader_program, fragment_shader ); - if (geometry_shader) glAttachShader( shader_program, geometry_shader ); + glAttachShader(shader_program, vertex_shader); + glAttachShader(shader_program, fragment_shader); + if (geometry_shader) glAttachShader(shader_program, geometry_shader); - glBindAttribLocation(shader_program, attrib_position, "i_position"); - glBindAttribLocation(shader_program, attrib_color, "i_color"); - glLinkProgram(shader_program ); - glUseProgram(shader_program ); + glLinkProgram(shader_program); + glUseProgram(shader_program); if (vertex_shader) glDeleteShader(vertex_shader); if (fragment_shader) glDeleteShader(fragment_shader); @@ -59,11 +67,12 @@ class ShaderProgram { return shader_program; } - static GLuint loadShader(GLuint shader_type, const char* shader_string) { - GLuint shader_id = glCreateShader(shader_type);; - int length = strlen(shader_string); - glShaderSource(shader_id, 1, ( const GLchar ** )&shader_string, &length); - glCompileShader(shader_id ); + + static GLuint load_shader(GLuint shader_type, char const* shader_string) { + GLuint shader_id = glCreateShader(shader_type); + int length = strlen(shader_string); + glShaderSource(shader_id, 1, (GLchar const**)&shader_string, &length); + glCompileShader(shader_id); GLint status; glGetShaderiv(shader_id, GL_COMPILE_STATUS, &status); @@ -72,30 +81,119 @@ class ShaderProgram { glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &maxLength); std::vector errorLog(maxLength); glGetShaderInfoLog(shader_id, maxLength, &maxLength, &errorLog[0]); - for (auto c : errorLog) fputc(c, stderr); + for (auto c : errorLog) + fputc(c, stderr); glDeleteShader(shader_id); return 0; } return shader_id; } + + static std::shared_ptr create( + const std::filesystem::path vertex_path, const std::filesystem::path fragment_path, const std::filesystem::path geometry_path = {} + ) { + auto program_id = load_program( + resource::ResourceManager::get_as_cstr(vertex_path), + resource::ResourceManager::get_as_cstr(fragment_path), + resource::ResourceManager::get_as_cstr(geometry_path) + ); + if (program_id == 0) return nullptr; // default shader? + auto program = std::make_shared(program_id); + if (program) program->build_cache(); + return program; + } + + void build_cache() { + GLint size; // size of the variable + GLenum type; // type of the variable (float, vec3 or mat4, etc) + + const GLsizei bufSize = 64; // maximum name length //GL_ACTIVE_UNIFORM_MAX_LENGTH + GLchar name[bufSize]; // variable name in GLSL + GLsizei length; // name length + + GLint attribute_count; + for (auto& attr : m_attributes) { + attr.second.active = false; // disable all current attributes for reload + } + glGetProgramiv(m_program_id, GL_ACTIVE_ATTRIBUTES, &attribute_count); + for (GLint i = 0; i < attribute_count; i++) { + glGetActiveAttrib(m_program_id, (GLuint)i, bufSize, &length, &size, &type, (char*)name); + m_attributes[name] = shader_attr_t {(uint32_t)i, name, type, size}; + } + + GLint uniform_count; + for (auto& uniform : m_uniforms) { + uniform.second.active = false; // disable all current uniforms for reload + } + glGetProgramiv(m_program_id, GL_ACTIVE_UNIFORMS, &uniform_count); + for (GLint i = 0; i < uniform_count; i++) { + glGetActiveUniform(m_program_id, (GLuint)i, bufSize, &length, &size, &type, (char*)name); + m_uniforms[name] = shader_attr_t {(uint32_t)i, name, type, size}; + } + } + + GLuint m_program_id {}; + std::map m_attributes {}; + std::map m_uniforms {}; +}; + +class ShaderProgramInstance { +public: + ShaderProgramInstance(std::shared_ptr program) : m_program {program} { } + + struct shader_uniform_t { + shader_attr_t desc; + gl_uniform_t uniform_data; + std::function gl_uniform_call; + }; + + void bind_immediate() { + glUseProgram(m_program->m_program_id); + for (auto& [location, uniform] : m_uniforms) { + uniform.gl_uniform_call(uniform.desc, uniform.uniform_data); + } + } + + template void set_uniform(std::string name, T* value) { + using gl_uniform_type = gl_uniform::value>; + auto uniform = m_program->m_uniforms[name]; + m_uniforms[uniform.location] = shader_uniform_t { + uniform, + gl_uniform_type {value}, + [](shader_attr_t& uniform_desc, gl_uniform_t& uniform_data) { + if constexpr (gl_uniform_type::is_matrix) { + gl_uniform_type().invoke(uniform_desc.location, uniform_desc.size, GL_FALSE, glm::value_ptr(*std::get(uniform_data).value)); + } else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { + gl_uniform_type().invoke(uniform_desc.location, uniform_desc.size, &(*std::get(uniform_data).value)); + } else { + gl_uniform_type().invoke(uniform_desc.location, uniform_desc.size, glm::value_ptr(*std::get(uniform_data).value)); + } + }, + }; + return; + } + + std::shared_ptr m_program {}; + std::map m_uniforms; }; class BufferBase { public: virtual ~BufferBase() { } + virtual void destroy() = 0; virtual void generate() = 0; virtual bool bind() = 0; virtual void upload() = 0; virtual void render() = 0; - GLuint m_vao = 0; - GLuint m_vbo = 0; - size_t m_geometry_offset = 0; - GLuint m_storage_hint = GL_STATIC_DRAW; - Primitive m_geometry_type = Primitive::TRIANGLES; - bool m_dirty = true; - bool m_generated = false; + GLuint m_vao = 0; + GLuint m_vbo = 0; + size_t m_geometry_offset = 0; + GLuint m_storage_hint = GL_STATIC_DRAW; + GeometryPrimitive m_geometry_type = GeometryPrimitive::TRIANGLES; + bool m_dirty = true; + bool m_generated = false; std::mutex m_data_mutex {}; }; @@ -168,8 +266,9 @@ template class Buffer : public BufferBase { } private: - std::vector m_data {}; Buffer() { } + + std::vector m_data {}; }; class Mesh { @@ -181,12 +280,11 @@ class Mesh { m_transform_dirty = false; } if (m_shader_dirty) { - update_shader_locations(); + m_shader_instance->set_uniform("u_mvp", &m_view_projection_transform); m_shader_dirty = false; } - glUseProgram(m_shader_program); - global_transform = global_transform * m_transform; - glUniformMatrix4fv(m_shader_index_mvp, 1, GL_FALSE, glm::value_ptr(global_transform)); + m_view_projection_transform = global_transform * m_transform; + m_shader_instance->bind_immediate(); for (auto buffer : m_buffer) { buffer->render(); } @@ -225,18 +323,15 @@ class Mesh { return *reinterpret_cast>>*>(&m_buffer); } - void update_shader_locations() { - m_shader_index_mvp = glGetUniformLocation(m_shader_program, "u_mvp"); - } - - void set_shader_program(GLuint program) { - m_shader_program = program; + void set_shader_program(std::shared_ptr program) { + m_shader_instance = std::make_shared(program); } - glm::mat4 m_transform { 1.0 }; - glm::vec3 m_origin { 0.0, 0.0, 0.0 }; - glm::vec3 m_position { 0.0, 0.0, 0.0 }; - glm::vec3 m_scale { 1.0, 1.0, 1.0 }; + glm::mat4 m_view_projection_transform {1.0}; + glm::mat4 m_transform {1.0}; + glm::vec3 m_origin {0.0, 0.0, 0.0}; + glm::vec3 m_position {0.0, 0.0, 0.0}; + glm::vec3 m_scale {1.0, 1.0, 1.0}; glm::quat m_rotation {}; bool m_visible = true; bool m_transform_dirty = true; @@ -245,8 +340,7 @@ class Mesh { std::mutex m_buffer_modification_mutex {}; std::vector> m_buffer {}; - GLuint m_shader_program = 0; - GLuint m_shader_index_mvp = 0; + std::shared_ptr m_shader_instance = 0; private: Mesh() { } @@ -257,7 +351,8 @@ class Renderer { void render(glm::mat4 global_transform) { m_mesh.erase( std::remove_if( - m_mesh.begin(), m_mesh.end(), + m_mesh.begin(), + m_mesh.end(), [](auto& mesh) { if (mesh->m_delete) { mesh->free_gpu_resources(); diff --git a/src/MarlinSimulator/renderer/shader_data.h b/src/MarlinSimulator/resources/resource_data.h similarity index 93% rename from src/MarlinSimulator/renderer/shader_data.h rename to src/MarlinSimulator/resources/resource_data.h index b452d59..353ffeb 100644 --- a/src/MarlinSimulator/renderer/shader_data.h +++ b/src/MarlinSimulator/resources/resource_data.h @@ -1,10 +1,8 @@ #pragma once -namespace renderer { +namespace resource { -// todo : Y axis change fix, worked around by not joining -// todo : very spiky corners after 45 degs, again just worked around by not joining -static const char * geometry_shader = R"SHADERSTR( +static const char * data_shader_extrusion_gs = R"SHADERSTR( #version 330 core layout (lines_adjacency) in; layout (triangle_strip, max_vertices = 28) out; @@ -29,7 +27,7 @@ static const char * geometry_shader = R"SHADERSTR( EndPrimitive(); } - const float epsilon = 0.000001; + const float epsilon = 0.0004; void main() { vec3 prev = gl_in[0].gl_Position.xyz; @@ -118,7 +116,7 @@ static const char * geometry_shader = R"SHADERSTR( //emit(0, 1, 8, 0); //show up normal })SHADERSTR"; -static const char * path_vertex_shader = R"SHADERSTR( +static const char * data_shader_extrusion_vs = R"SHADERSTR( #version 330 core in vec3 i_position; in vec3 i_normal; @@ -131,7 +129,7 @@ static const char * path_vertex_shader = R"SHADERSTR( gl_Position = vec4( i_position, 1.0 ); })SHADERSTR"; -static const char * path_fragment_shader = R"SHADERSTR( +static const char * data_shader_extrusion_fs = R"SHADERSTR( #version 330 core in vec4 v_color; out vec4 o_color; @@ -170,7 +168,7 @@ static const char * path_fragment_shader = R"SHADERSTR( } })SHADERSTR"; -static const char * vertex_shader = R"SHADERSTR( +static const char * data_shader_default_vs = R"SHADERSTR( #version 330 core in vec3 i_position; in vec3 i_normal; @@ -186,7 +184,7 @@ static const char * vertex_shader = R"SHADERSTR( gl_Position = u_mvp * vec4( i_position, 1.0 ); })SHADERSTR"; -static const char * fragment_shader = R"SHADERSTR( +static const char * data_shader_default_fs = R"SHADERSTR( #version 330 core in vec4 v_color; in vec3 v_normal; diff --git a/src/MarlinSimulator/resources/resources.cpp b/src/MarlinSimulator/resources/resources.cpp new file mode 100644 index 0000000..e750021 --- /dev/null +++ b/src/MarlinSimulator/resources/resources.cpp @@ -0,0 +1,57 @@ +#include "resources.h" +#include "resource_data.h" + +#include + +namespace resource { + std::map> ResourceManager::s_loaded_resource = {}; + std::map> ResourceManager::s_embedded_resource = { + {{"null"}, std::make_shared(nullptr)}, + {{"data/shaders/extrusion.gs"}, std::make_shared(data_shader_extrusion_gs)}, + {{"data/shaders/extrusion.vs"}, std::make_shared(data_shader_extrusion_vs)}, + {{"data/shaders/extrusion.fs"}, std::make_shared(data_shader_extrusion_fs)}, + {{"data/shaders/default.vs"}, std::make_shared(data_shader_default_vs)}, + {{"data/shaders/default.fs"}, std::make_shared(data_shader_default_fs)}, + } ; + + FileResource::FileResource(std::filesystem::path path) : m_path{path} { + load(); + } + + void FileResource::load() { + std::ifstream file(m_path, std::ios::binary | std::ios::ate); + m_modified = std::filesystem::last_write_time(m_path); + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + m_data.reserve(size + 1); + if(file.read(m_data.data(), size)) { + m_buffer = m_data.data(); + m_data[size] = 0; + } else { + m_data.clear(); + m_buffer = nullptr; + } + } + + bool FileResource::reload() { + if (m_modified < std::filesystem::last_write_time(m_path)) { + load(); + return true; + } + return false; + } + + const char* ResourceManager::get_as_cstr(std::filesystem::path path) { + if (!path.empty() && std::filesystem::exists(std::filesystem::current_path() / path)) { + if (s_loaded_resource.count(path)) { + s_loaded_resource[path]->reload(); + return s_loaded_resource[path]->m_buffer; + } + auto file_buffer = std::make_shared(path); + s_loaded_resource[path] = file_buffer; + return file_buffer->m_buffer; + } + return s_embedded_resource.count(path) > 0 ? s_embedded_resource[path]->m_buffer : nullptr; + } + +} diff --git a/src/MarlinSimulator/resources/resources.h b/src/MarlinSimulator/resources/resources.h new file mode 100644 index 0000000..a111e98 --- /dev/null +++ b/src/MarlinSimulator/resources/resources.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace resource { + +class Resource { +public: + Resource(const char * buffer = nullptr) : m_buffer { buffer } {} + virtual ~Resource() {} + const char * m_buffer = nullptr; + virtual bool reload() { return false; }; +}; + +class FileResource : public Resource { +public: + FileResource(std::filesystem::path path); + ~FileResource() { } + + void load(); + virtual bool reload() override; + + std::vector m_data; + std::filesystem::path m_path; + std::filesystem::file_time_type m_modified; +}; + +class ResourceManager { +public: + static const char* get_as_cstr(std::filesystem::path path); +private: + static std::map> s_embedded_resource; + static std::map> s_loaded_resource; + ResourceManager(); +}; + +} diff --git a/src/MarlinSimulator/user_interface.h b/src/MarlinSimulator/user_interface.h index b83797b..756c724 100644 --- a/src/MarlinSimulator/user_interface.h +++ b/src/MarlinSimulator/user_interface.h @@ -223,6 +223,11 @@ struct SerialMonitor : public UiWindow { MSerialT& serial_stream; std::ifstream input_file; + uint8_t buffer[HalSerial::receive_buffer_size]{}; + const std::string file_dialog_key = "ChooseFileDlgKey"; + const std::string file_dialog_title = "Choose File"; + const char* file_dialog_filters = "GCode(*.gcode *.gc *.g){.gcode,.gc,.g},.*"; + const std::string file_dialog_path = "."; int input_callback(ImGuiInputTextCallbackData* data) { switch (data->EventFlag) { @@ -270,7 +275,6 @@ struct SerialMonitor : public UiWindow { void show() { // File read into serial port if (input_file.is_open() && serial_stream.receive_buffer.free() && streaming) { - uint8_t buffer[HalSerial::receive_buffer_size]{}; size_t read_size = std::min(serial_stream.receive_buffer.free(), stream_total - stream_sent); input_file.read((char*)buffer, read_size); serial_stream.receive_buffer.write(buffer, read_size); @@ -291,7 +295,7 @@ struct SerialMonitor : public UiWindow { if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Stream")) { if (ImGui::MenuItem("Select GCode File")) { - ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Choose File", "GCode(*.gcode *.gc *.g){.gcode,.gc,.g},.*", "."); + ImGuiFileDialog::Instance()->OpenDialog(file_dialog_key, file_dialog_title, file_dialog_filters, file_dialog_path); } if (input_file.is_open() && streaming) if (ImGui::MenuItem("Pause")) { @@ -319,7 +323,7 @@ struct SerialMonitor : public UiWindow { ImGui::EndMenuBar(); } - if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey", ImGuiWindowFlags_NoDocking)) { + if (ImGuiFileDialog::Instance()->IsOpened() && ImGuiFileDialog::Instance()->Display(file_dialog_key, ImGuiWindowFlags_NoDocking)) { if (ImGuiFileDialog::Instance()->IsOk()) { std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); //printf("Streaming file: %s\n", filePathName.c_str()); @@ -340,7 +344,7 @@ struct SerialMonitor : public UiWindow { auto size = ImGui::GetContentRegionAvail(); size.y -= 25; // TODO: there must be a better way to fill 2 items on a line if (ImGui::BeginChild(child_id, size, true, child_flags)) { - for (auto line : line_buffer) { + for (auto& line : line_buffer) { if (line.count > 1) ImGui::TextWrapped("[%ld] %s", line.count, (char *)line.text.c_str()); else ImGui::TextWrapped("%s", (char *)line.text.c_str()); } diff --git a/src/MarlinSimulator/virtual_printer.cpp b/src/MarlinSimulator/virtual_printer.cpp index 15f0079..f6ce50a 100644 --- a/src/MarlinSimulator/virtual_printer.cpp +++ b/src/MarlinSimulator/virtual_printer.cpp @@ -30,7 +30,7 @@ #define SD_DETECT_STATE HIGH #endif -std::function VirtualPrinter::on_kinematic_update; +std::function VirtualPrinter::on_kinematic_update; std::map> VirtualPrinter::component_map; std::vector> VirtualPrinter::components; std::shared_ptr VirtualPrinter::root; diff --git a/src/MarlinSimulator/virtual_printer.h b/src/MarlinSimulator/virtual_printer.h index 1583f77..baf6884 100644 --- a/src/MarlinSimulator/virtual_printer.h +++ b/src/MarlinSimulator/virtual_printer.h @@ -56,11 +56,11 @@ class VirtualPrinter { } template - static auto get_component(std::string name) { + static std::shared_ptr get_component(std::string name) { return std::static_pointer_cast(component_map[name]); } - static std::function on_kinematic_update; + static std::function on_kinematic_update; private: static std::map> component_map; diff --git a/src/MarlinSimulator/visualisation.cpp b/src/MarlinSimulator/visualisation.cpp index c5a95ff..5529db5 100644 --- a/src/MarlinSimulator/visualisation.cpp +++ b/src/MarlinSimulator/visualisation.cpp @@ -13,15 +13,10 @@ #include #include - -static GLfloat * SetBedVertexAndAdvance(GLfloat * dest, GLfloat x, GLfloat y) { - const GLfloat new_vertex[VERTEX_FLOAT_COUNT] = { BED_VERTEX(x, y) }; - memcpy(dest, new_vertex, sizeof(new_vertex)); - return dest + VERTEX_FLOAT_COUNT; -} +#include "resources/resources.h" Visualisation::Visualisation(VirtualPrinter& virtual_printer) : virtual_printer(virtual_printer) { - virtual_printer.on_kinematic_update = [this](kinematic_state state){ + virtual_printer.on_kinematic_update = [this](kinematic_state& state){ for (size_t i = 0; i < state.effector_position.size(); ++i) { this->set_head_position(i, state.effector_position[i]); } @@ -37,8 +32,8 @@ Visualisation::~Visualisation() { } void Visualisation::create() { - path_program = renderer::ShaderProgram::loadProgram(renderer::path_vertex_shader, renderer::path_fragment_shader, renderer::geometry_shader); - program = renderer::ShaderProgram::loadProgram(renderer::vertex_shader, renderer::fragment_shader); + extrusion_program = renderer::ShaderProgram::create("data/shaders/extrusion.vs", "data/shaders/extrusion.fs", "data/shaders/extrusion.gs"); + default_program = renderer::ShaderProgram::create("data/shaders/default.vs","data/shaders/default.fs"); framebuffer = new opengl_util::MsaaFrameBuffer(); if (!((opengl_util::MsaaFrameBuffer*)framebuffer)->create(100, 100, 4)) { @@ -57,24 +52,24 @@ void Visualisation::create() { auto mesh = renderer::Mesh::create(); auto buffer = mesh->buffer(); buffer->data() = { - renderer::vertex_data_t EFFECTOR_VERTEX2(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), - EFFECTOR_VERTEX2(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), - EFFECTOR_VERTEX2(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), - EFFECTOR_VERTEX2(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), - EFFECTOR_VERTEX2(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), - EFFECTOR_VERTEX2(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), - EFFECTOR_VERTEX2(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), - EFFECTOR_VERTEX2(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), - EFFECTOR_VERTEX2(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), - EFFECTOR_VERTEX2(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), - EFFECTOR_VERTEX2(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), + renderer::vertex_data_t EFFECTOR_VERTEX(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), + EFFECTOR_VERTEX(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), + EFFECTOR_VERTEX(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), + EFFECTOR_VERTEX(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), + EFFECTOR_VERTEX(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), + EFFECTOR_VERTEX(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), + EFFECTOR_VERTEX(0.0, 0.0, 0.0, EFFECTOR_COLOR_1), + EFFECTOR_VERTEX(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), + EFFECTOR_VERTEX(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(-0.5, 0.5, -0.5, EFFECTOR_COLOR_3), + EFFECTOR_VERTEX(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0.5, 0.5, -0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(-0.5, 0.5, 0.5, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0.5, 0.5, 0.5, EFFECTOR_COLOR_3), }; m_extruder_mesh.push_back(mesh); @@ -84,13 +79,13 @@ void Visualisation::create() { } for (auto m : m_extruder_mesh) { - m->set_shader_program(program); + m->set_shader_program(default_program); m->m_scale = effector_scale; m_renderer.m_mesh.push_back(m); } m_bed_mesh = renderer::Mesh::create(); - m_bed_mesh->set_shader_program(program); + m_bed_mesh->set_shader_program(default_program); m_bed_mesh_buffer = m_bed_mesh->buffer(); m_renderer.m_mesh.push_back(m_bed_mesh); @@ -113,15 +108,15 @@ void Visualisation::create() { // |--/ // | / // |/ - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x2, y2)); - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x1, y2)); - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x1, y1)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x2, y2)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x1, y2)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x1, y1)); // /| // / | // /--| - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x2, y2)); - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x1, y1)); - m_bed_mesh_buffer->add_vertex(BED_VERTEX2(x2, y1)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x2, y2)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x1, y1)); + m_bed_mesh_buffer->add_vertex(BED_VERTEX(x2, y1)); } } @@ -204,11 +199,6 @@ void Visualisation::update() { mesh_id ++; } - // TODO: Shaders need this internalised - glUseProgram( path_program ); - glUniform1f( glGetUniformLocation( path_program, "u_layer_thickness" ), extrude_thickness); - glUniform1f( glGetUniformLocation( path_program, "u_layer_width" ), extrude_width); - glUniform3fv( glGetUniformLocation( path_program, "u_view_position" ), 1, glm::value_ptr(camera.position)); m_renderer.render(camera.proj * camera.view); } @@ -219,7 +209,7 @@ void Visualisation::destroy() { } } -void Visualisation::set_head_position(size_t hotend_index, extruder_state state) { +void Visualisation::set_head_position(size_t hotend_index, extruder_state& state) { if (!m_initialised || hotend_index >= extrusion.size()) return; glm::vec4 sim_pos = state.position; glm::vec4 position = {sim_pos.x, sim_pos.z, sim_pos.y * -1.0, sim_pos.w}; // correct for opengl coordinate system @@ -258,10 +248,14 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state) } else { // need to change geometry buffer if (extruder.active_mesh_buffer == nullptr) { auto mesh = renderer::Mesh::create(); - mesh->set_shader_program(path_program); + mesh->set_shader_program(extrusion_program); + mesh->m_shader_instance->set_uniform("u_layer_thickness", &extrude_thickness); + mesh->m_shader_instance->set_uniform("u_layer_width", &extrude_width); + mesh->m_shader_instance->set_uniform("u_view_position", &camera.position); + extruder.active_mesh_buffer = mesh->buffer(); extruder.active_mesh_buffer->data().reserve(renderer::Renderer::MAX_BUFFER_SIZE); - extruder.active_mesh_buffer->m_geometry_type = renderer::Primitive::LINE_STRIP_ADJACENCY; + extruder.active_mesh_buffer->m_geometry_type = renderer::GeometryPrimitive::LINE_STRIP_ADJACENCY; extruder.mesh = mesh; extruder.last_extrusion_check = position; m_renderer.m_mesh.push_back(mesh); @@ -271,7 +265,7 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state) renderer::vertex_data_t last_vertex = extruder.active_mesh_buffer->cdata().back(); auto buffer = renderer::Buffer::create(); buffer->data().reserve(renderer::Renderer::MAX_BUFFER_SIZE); - buffer->m_geometry_type = renderer::Primitive::LINE_STRIP_ADJACENCY; + buffer->m_geometry_type = renderer::GeometryPrimitive::LINE_STRIP_ADJACENCY; extruder.active_mesh_buffer = buffer; extruder.mesh->buffer_vector().push_back(buffer); @@ -414,6 +408,16 @@ void Visualisation::ui_info_callback(UiWindow* w) { } } + if (ImGui::Button("Reload Shaders")) { + // path_program = renderer::ShaderProgram::loadProgram(resource::ResourceManager::get_as_cstr("data/shaders/extrusion.vs"), resource::ResourceManager::get_as_cstr("data/shaders/extrusion.fs"), resource::ResourceManager::get_as_cstr("data/shaders/extrusion.gs")); + // glUniform1f( glGetUniformLocation( path_program, "u_layer_thickness" ), extrude_thickness); + // glUniform1f( glGetUniformLocation( path_program, "u_layer_width" ), extrude_width); + // glUniform3fv( glGetUniformLocation( path_program, "u_view_position" ), 1, glm::value_ptr(camera.position)); + // for (auto& ex : extrusion) { + // ex.mesh->m_shader_program = path_program; + // } + } + ImGui::PushItemWidth(150); ImGui::Text("Extrude Width "); ImGui::PopItemWidth(); diff --git a/src/MarlinSimulator/visualisation.h b/src/MarlinSimulator/visualisation.h index 6eab095..99548a7 100644 --- a/src/MarlinSimulator/visualisation.h +++ b/src/MarlinSimulator/visualisation.h @@ -22,7 +22,6 @@ #include "user_interface.h" #include "renderer/renderer.h" -#include "renderer/shader_data.h" constexpr glm::ivec2 build_plate_dimension{X_BED_SIZE, Y_BED_SIZE}; constexpr glm::ivec2 build_plate_offset{X_MIN_POS, Y_MIN_POS}; @@ -137,7 +136,7 @@ class Visualisation { std::vector extrusion {}; - void set_head_position(size_t hotend_index, extruder_state position); + void set_head_position(size_t hotend_index, extruder_state& position); bool points_are_collinear(const glm::vec3 a, const glm::vec3 b, const glm::vec3 c, const double threshold) const; FollowMode follow_mode = FOLLOW_NONE; @@ -155,8 +154,8 @@ class Visualisation { std::shared_ptr> m_bed_mesh_buffer {}; std::shared_ptr m_bed_mesh; - - GLuint program, path_program; + std::shared_ptr extrusion_program; + std::shared_ptr default_program; bool mouse_captured = false; bool input_state[6] = {}; @@ -170,25 +169,16 @@ class Visualisation { #define EFFECTOR_COLOR_2 0.0, 1.0, 0.0, 1.0 #define EFFECTOR_COLOR_3 0.0, 0.0, 1.0, 1.0 - #define BED_VERTEX(X, Y) X, 0.0, Y, BED_NORMAL, BED_COLOR - #define BED_VERTEX2(X, Y) {{X, 0.0, Y}, {BED_NORMAL}, {BED_COLOR}} - #define EFFECTOR_VERTEX(X, Z, Y, COLOR) X, Z, Y, EFFECTOR_NORMAL, COLOR - - #define EFFECTOR_VERTEX2(X, Z, Y, COLOR) {{X, Z, Y}, {EFFECTOR_NORMAL}, {COLOR}} - - #define VERTEX_FLOAT_COUNT 10 - #define BED_VERTEX_OFFSET 18 + #define BED_VERTEX(X, Y) {{X, 0.0, Y}, {BED_NORMAL}, {BED_COLOR}} + #define EFFECTOR_VERTEX(X, Z, Y, COLOR) {{X, Z, Y}, {EFFECTOR_NORMAL}, {COLOR}} #define BED_NUM_VERTEXES_PER_AXIS 100 - #define BED_NUM_TRIANGES ((BED_NUM_VERTEXES_PER_AXIS - 1) * (BED_NUM_VERTEXES_PER_AXIS - 1) * 2) - #define NUM_VERTEXES (BED_VERTEX_OFFSET + BED_NUM_TRIANGES * 3) - float extrude_width = 0.4; float extrude_thickness = 0.3; - renderer::Renderer m_renderer {}; bool m_initialised = false; visualisation_config m_config {}; + renderer::Renderer m_renderer {}; }; struct Viewport : public UiWindow {