Skip to content

Commit

Permalink
fix mesh deletion
Browse files Browse the repository at this point in the history
formatting
  • Loading branch information
p3p committed Apr 25, 2024
1 parent 3866eed commit 6cae7dd
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 56 deletions.
126 changes: 77 additions & 49 deletions src/MarlinSimulator/renderer/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,70 +25,79 @@ struct vertex_data_t {

class BufferBase {
public:
virtual ~BufferBase() {
if (m_vbo) glDeleteBuffers(1, &m_vbo);
if (m_vao) glDeleteBuffers(1, &m_vao);
}
virtual ~BufferBase() { }
virtual void destroy() = 0;
virtual void generate() = 0;
virtual void 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;
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;
bool m_dirty = true;
bool m_generated = false;
std::mutex m_data_mutex {};
};

template <typename ElementType> class Buffer : public BufferBase {
template<typename ElementType> class Buffer : public BufferBase {
public:
virtual void generate() override {
glGenVertexArrays( 1, &m_vao );
glGenBuffers( 1, &m_vbo );
glBindVertexArray( m_vao );
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vbo);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);

size_t index = 0, offset = 0;
for (auto& attrib : ElementType::descriptor) {
glEnableVertexAttribArray(index);
glVertexAttribPointer(index, attrib.elements, attrib.gl_enum, GL_FALSE, sizeof(ElementType), (void *)offset);
glVertexAttribPointer(index, attrib.elements, attrib.gl_enum, GL_FALSE, sizeof(ElementType), (void*)offset);
++index;
offset += attrib.length;
}
m_generated = true;
}

virtual void bind() override {
virtual void destroy() override {
if (m_vbo) glDeleteBuffers(1, &m_vbo);
if (m_vao) glDeleteBuffers(1, &m_vao);
m_vbo = m_vao = 0;
}

virtual bool bind() override {
if (!m_generated) generate();
glBindVertexArray( m_vao );
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
if (m_vao == 0 || m_vbo == 0) return false;
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
return true;
}

virtual void upload() override {
if (m_dirty) {
glBufferData( GL_ARRAY_BUFFER, m_data.size() * sizeof(ElementType), &m_data[0], m_storage_hint );
glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(ElementType), &m_data[0], m_storage_hint);
m_dirty = false;
}
}

virtual void render() override {
bind();
upload();
glDrawArrays( (GLenum)m_geometry_type, m_geometry_offset, m_data.size());
if (bind()) {
upload();
glDrawArrays((GLenum)m_geometry_type, m_geometry_offset, m_data.size());
}
}

static std::shared_ptr<Buffer<ElementType>> create() {
return std::shared_ptr<Buffer<ElementType>>( new Buffer<ElementType>() );
return std::shared_ptr<Buffer<ElementType>>(new Buffer<ElementType>());
}

std::vector<ElementType>& data() {
m_dirty = true;
return m_data;
}

std::vector<ElementType> const & cdata() const {
std::vector<ElementType> const& cdata() const {
return m_data;
}

Expand All @@ -110,80 +119,99 @@ class Mesh {
public:
void render(glm::mat4 global_transform) {
if (!m_visible) return;
if (m_dirty) {
if (m_transform_dirty) {
build_transform();
m_dirty = false;
m_transform_dirty = false;
}
if (m_shader_dirty) {
update_shader_locations();
m_shader_dirty = false;
}
glUseProgram( m_shader_program );
glUseProgram(m_shader_program);
global_transform = global_transform * m_transform;
glUniformMatrix4fv( m_shader_index_mvp, 1, GL_FALSE, glm::value_ptr(global_transform));
glUniformMatrix4fv(m_shader_index_mvp, 1, GL_FALSE, glm::value_ptr(global_transform));
for (auto buffer : m_buffer) {
buffer->render();
}
}

void free_gpu_resources() {
for (auto buffer : m_buffer) {
buffer->destroy();
}
}

void build_transform() {
m_transform = glm::translate(glm::mat4(1.0), m_position);
m_transform = m_transform * glm::mat4_cast(m_rotation);
m_transform = glm::scale(m_transform, m_scale);
m_transform = glm::translate(m_transform, m_origin);
}

template <typename VertexType> static std::shared_ptr<Mesh> create(std::shared_ptr<VertexType> buffer) {
template<typename VertexType> static std::shared_ptr<Mesh> create(std::shared_ptr<VertexType> buffer) {
auto mesh = std::shared_ptr<Mesh>(new Mesh());
mesh->m_buffer.push_back(buffer);
return mesh;
}

template <typename VertexType> static std::shared_ptr<Mesh> create() {
template<typename VertexType> static std::shared_ptr<Mesh> create() {
auto mesh = std::shared_ptr<Mesh>(new Mesh());
mesh->m_buffer.push_back(Buffer<VertexType>::create());
return mesh;
}

template <typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer() {
template<typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer() {
return std::reinterpret_pointer_cast<Buffer<VertexType>>(m_buffer.back());
}

template <typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector() {
template<typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector() {
return *reinterpret_cast<std::vector<std::shared_ptr<Buffer<VertexType>>>*>(&m_buffer);
}

void update_shader_locations() {
m_shader_index_mvp = glGetUniformLocation( m_shader_program, "u_mvp" );
m_shader_index_mvp = glGetUniformLocation(m_shader_program, "u_mvp");
}

void set_shader_program(GLuint program) {
m_shader_program = 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_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_dirty = true;
bool m_shader_dirty = true;
bool m_delete = false;
bool m_visible = true;
bool m_transform_dirty = true;
bool m_shader_dirty = true;
bool m_delete = false;
std::mutex m_buffer_modification_mutex {};
std::vector<std::shared_ptr<BufferBase>> m_buffer {};

GLuint m_shader_program = 0;
GLuint m_shader_program = 0;
GLuint m_shader_index_mvp = 0;

private:
Mesh() {}
Mesh() { }
};

class Renderer {
public:
void render(glm::mat4 global_transform) {
//TODO: mutex for modifying mesh vector
m_mesh.erase(std::remove_if(m_mesh.begin(), m_mesh.end(), [](auto& mesh) { return mesh->m_delete; }), m_mesh.end());
m_mesh.erase(
std::remove_if(
m_mesh.begin(), m_mesh.end(),
[](auto& mesh) {
if (mesh->m_delete) {
mesh->free_gpu_resources();
return true;
}
return false;
}
),
m_mesh.end()
);

for (auto& mesh : m_mesh) {
mesh->render(global_transform);
}
Expand Down
16 changes: 10 additions & 6 deletions src/MarlinSimulator/visualisation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,13 @@ void Visualisation::update() {
auto pos = glm::vec3(ext.position.x, ext.position.y, ext.position.z);
if (m_extruder_mesh[mesh_id]->m_position != pos) {
m_extruder_mesh[mesh_id]->m_position = pos;
m_extruder_mesh[mesh_id]->m_dirty = true;
m_extruder_mesh[mesh_id]->m_transform_dirty = true;
}
m_extruder_mesh[mesh_id]->m_visible = (follow_mode != FOLLOW_Z);
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);
Expand All @@ -225,6 +226,11 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
auto& extruder = extrusion[hotend_index];
glm::vec3 extrude_color = state.color;

if (extruder.mesh != nullptr && extruder.mesh->m_delete) {
extruder.active_mesh_buffer.reset();
extruder.mesh.reset();
}

if (position != extruder.position) {

if (glm::length(glm::vec3(position) - glm::vec3(extruder.last_extrusion_check)) > 0.5f) { // smooths out extrusion over a minimum length to fill in gaps todo: implement an simulation to do this better
Expand All @@ -235,7 +241,7 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
if (extruder.active_mesh_buffer != nullptr && extruder.active_mesh_buffer->size() > 1 && extruder.active_mesh_buffer->size() < renderer::Renderer::MAX_BUFFER_SIZE) {

if (glm::length(glm::vec3(position) - glm::vec3(extruder.last_position)) > 0.05f) { // smooth out the path so the model renders with less geometry, rendering each individual step hurts the fps
if((points_are_collinear(position, extruder.active_mesh_buffer->cdata().end()[-3].position, extruder.active_mesh_buffer->cdata().end()[-2].position) && extruder.extruding == extruder.last_extruding) || ( extruder.extruding == false && extruder.last_extruding == false)) {
if((points_are_collinear(position, extruder.active_mesh_buffer->cdata().end()[-3].position, extruder.active_mesh_buffer->cdata().end()[-2].position, 0.0002) && extruder.extruding == extruder.last_extruding) || ( extruder.extruding == false && extruder.last_extruding == false)) {
// collinear and extrusion state has not changed so we can just change the current point.
extruder.active_mesh_buffer->data().end()[-2].position = position;
extruder.active_mesh_buffer->data().end()[-1].position = position;
Expand Down Expand Up @@ -280,8 +286,8 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
}
}

bool Visualisation::points_are_collinear(glm::vec3 a, glm::vec3 b, glm::vec3 c) {
return glm::length(glm::dot(b - a, c - a) - (glm::length(b - a) * glm::length(c - a))) < 0.0002; // could be increased to further reduce rendered geometry
bool Visualisation::points_are_collinear(const glm::vec3 a, const glm::vec3 b, const glm::vec3 c, const double threshold) const {
return glm::abs(glm::dot(b - a, c - a) - (glm::length(b - a) * glm::length(c - a))) < threshold;
}

void Visualisation::ui_viewport_callback(UiWindow* window) {
Expand Down Expand Up @@ -406,9 +412,7 @@ void Visualisation::ui_info_callback(UiWindow* w) {
if (ImGui::Button("Clear Print Area")) {
for (auto& extruder : extrusion) {
if (extruder.mesh != nullptr) {
extruder.active_mesh_buffer.reset();
extruder.mesh->m_delete = true;
extruder.mesh.reset();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/MarlinSimulator/visualisation.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class Visualisation {

const float filiment_diameter = 1.75;
void set_head_position(size_t hotend_index, extruder_state position);
bool points_are_collinear(glm::vec3 a, glm::vec3 b, glm::vec3 c);
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;
bool render_full_path = true;
Expand Down

0 comments on commit 6cae7dd

Please sign in to comment.