Skip to content

Commit 6cae7dd

Browse files
committedApr 25, 2024
fix mesh deletion
formatting
1 parent 3866eed commit 6cae7dd

File tree

3 files changed

+88
-56
lines changed

3 files changed

+88
-56
lines changed
 

‎src/MarlinSimulator/renderer/renderer.h

+77-49
Original file line numberDiff line numberDiff line change
@@ -25,70 +25,79 @@ struct vertex_data_t {
2525

2626
class BufferBase {
2727
public:
28-
virtual ~BufferBase() {
29-
if (m_vbo) glDeleteBuffers(1, &m_vbo);
30-
if (m_vao) glDeleteBuffers(1, &m_vao);
31-
}
28+
virtual ~BufferBase() { }
29+
virtual void destroy() = 0;
3230
virtual void generate() = 0;
33-
virtual void bind() = 0;
34-
virtual void upload() = 0;
35-
virtual void render() = 0;
36-
GLuint m_vao = 0;
37-
GLuint m_vbo = 0;
38-
size_t m_geometry_offset = 0;
39-
GLuint m_storage_hint = GL_STATIC_DRAW;
31+
virtual bool bind() = 0;
32+
virtual void upload() = 0;
33+
virtual void render() = 0;
34+
35+
GLuint m_vao = 0;
36+
GLuint m_vbo = 0;
37+
size_t m_geometry_offset = 0;
38+
GLuint m_storage_hint = GL_STATIC_DRAW;
4039
Primitive m_geometry_type = Primitive::TRIANGLES;
41-
bool m_dirty = true;
42-
bool m_generated = false;
40+
bool m_dirty = true;
41+
bool m_generated = false;
42+
std::mutex m_data_mutex {};
4343
};
4444

45-
template <typename ElementType> class Buffer : public BufferBase {
45+
template<typename ElementType> class Buffer : public BufferBase {
4646
public:
4747
virtual void generate() override {
48-
glGenVertexArrays( 1, &m_vao );
49-
glGenBuffers( 1, &m_vbo );
50-
glBindVertexArray( m_vao );
51-
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
48+
glGenVertexArrays(1, &m_vao);
49+
glGenBuffers(1, &m_vbo);
50+
glBindVertexArray(m_vao);
51+
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
5252

5353
size_t index = 0, offset = 0;
5454
for (auto& attrib : ElementType::descriptor) {
5555
glEnableVertexAttribArray(index);
56-
glVertexAttribPointer(index, attrib.elements, attrib.gl_enum, GL_FALSE, sizeof(ElementType), (void *)offset);
56+
glVertexAttribPointer(index, attrib.elements, attrib.gl_enum, GL_FALSE, sizeof(ElementType), (void*)offset);
5757
++index;
5858
offset += attrib.length;
5959
}
6060
m_generated = true;
6161
}
6262

63-
virtual void bind() override {
63+
virtual void destroy() override {
64+
if (m_vbo) glDeleteBuffers(1, &m_vbo);
65+
if (m_vao) glDeleteBuffers(1, &m_vao);
66+
m_vbo = m_vao = 0;
67+
}
68+
69+
virtual bool bind() override {
6470
if (!m_generated) generate();
65-
glBindVertexArray( m_vao );
66-
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
71+
if (m_vao == 0 || m_vbo == 0) return false;
72+
glBindVertexArray(m_vao);
73+
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
74+
return true;
6775
}
6876

6977
virtual void upload() override {
7078
if (m_dirty) {
71-
glBufferData( GL_ARRAY_BUFFER, m_data.size() * sizeof(ElementType), &m_data[0], m_storage_hint );
79+
glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(ElementType), &m_data[0], m_storage_hint);
7280
m_dirty = false;
7381
}
7482
}
7583

7684
virtual void render() override {
77-
bind();
78-
upload();
79-
glDrawArrays( (GLenum)m_geometry_type, m_geometry_offset, m_data.size());
85+
if (bind()) {
86+
upload();
87+
glDrawArrays((GLenum)m_geometry_type, m_geometry_offset, m_data.size());
88+
}
8089
}
8190

8291
static std::shared_ptr<Buffer<ElementType>> create() {
83-
return std::shared_ptr<Buffer<ElementType>>( new Buffer<ElementType>() );
92+
return std::shared_ptr<Buffer<ElementType>>(new Buffer<ElementType>());
8493
}
8594

8695
std::vector<ElementType>& data() {
8796
m_dirty = true;
8897
return m_data;
8998
}
9099

91-
std::vector<ElementType> const & cdata() const {
100+
std::vector<ElementType> const& cdata() const {
92101
return m_data;
93102
}
94103

@@ -110,80 +119,99 @@ class Mesh {
110119
public:
111120
void render(glm::mat4 global_transform) {
112121
if (!m_visible) return;
113-
if (m_dirty) {
122+
if (m_transform_dirty) {
114123
build_transform();
115-
m_dirty = false;
124+
m_transform_dirty = false;
116125
}
117126
if (m_shader_dirty) {
118127
update_shader_locations();
119128
m_shader_dirty = false;
120129
}
121-
glUseProgram( m_shader_program );
130+
glUseProgram(m_shader_program);
122131
global_transform = global_transform * m_transform;
123-
glUniformMatrix4fv( m_shader_index_mvp, 1, GL_FALSE, glm::value_ptr(global_transform));
132+
glUniformMatrix4fv(m_shader_index_mvp, 1, GL_FALSE, glm::value_ptr(global_transform));
124133
for (auto buffer : m_buffer) {
125134
buffer->render();
126135
}
127136
}
128137

138+
void free_gpu_resources() {
139+
for (auto buffer : m_buffer) {
140+
buffer->destroy();
141+
}
142+
}
143+
129144
void build_transform() {
130145
m_transform = glm::translate(glm::mat4(1.0), m_position);
131146
m_transform = m_transform * glm::mat4_cast(m_rotation);
132147
m_transform = glm::scale(m_transform, m_scale);
133148
m_transform = glm::translate(m_transform, m_origin);
134149
}
135150

136-
template <typename VertexType> static std::shared_ptr<Mesh> create(std::shared_ptr<VertexType> buffer) {
151+
template<typename VertexType> static std::shared_ptr<Mesh> create(std::shared_ptr<VertexType> buffer) {
137152
auto mesh = std::shared_ptr<Mesh>(new Mesh());
138153
mesh->m_buffer.push_back(buffer);
139154
return mesh;
140155
}
141156

142-
template <typename VertexType> static std::shared_ptr<Mesh> create() {
157+
template<typename VertexType> static std::shared_ptr<Mesh> create() {
143158
auto mesh = std::shared_ptr<Mesh>(new Mesh());
144159
mesh->m_buffer.push_back(Buffer<VertexType>::create());
145160
return mesh;
146161
}
147162

148-
template <typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer() {
163+
template<typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer() {
149164
return std::reinterpret_pointer_cast<Buffer<VertexType>>(m_buffer.back());
150165
}
151166

152-
template <typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector() {
167+
template<typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector() {
153168
return *reinterpret_cast<std::vector<std::shared_ptr<Buffer<VertexType>>>*>(&m_buffer);
154169
}
155170

156171
void update_shader_locations() {
157-
m_shader_index_mvp = glGetUniformLocation( m_shader_program, "u_mvp" );
172+
m_shader_index_mvp = glGetUniformLocation(m_shader_program, "u_mvp");
158173
}
159174

160175
void set_shader_program(GLuint program) {
161176
m_shader_program = program;
162177
}
163178

164-
glm::mat4 m_transform {1.0};
165-
glm::vec3 m_origin {0.0, 0.0, 0.0};
166-
glm::vec3 m_position {0.0, 0.0, 0.0};
167-
glm::vec3 m_scale {1.0, 1.0, 1.0};
179+
glm::mat4 m_transform { 1.0 };
180+
glm::vec3 m_origin { 0.0, 0.0, 0.0 };
181+
glm::vec3 m_position { 0.0, 0.0, 0.0 };
182+
glm::vec3 m_scale { 1.0, 1.0, 1.0 };
168183
glm::quat m_rotation {};
169-
bool m_visible = true;
170-
bool m_dirty = true;
171-
bool m_shader_dirty = true;
172-
bool m_delete = false;
184+
bool m_visible = true;
185+
bool m_transform_dirty = true;
186+
bool m_shader_dirty = true;
187+
bool m_delete = false;
188+
std::mutex m_buffer_modification_mutex {};
173189
std::vector<std::shared_ptr<BufferBase>> m_buffer {};
174190

175-
GLuint m_shader_program = 0;
191+
GLuint m_shader_program = 0;
176192
GLuint m_shader_index_mvp = 0;
177193

178194
private:
179-
Mesh() {}
195+
Mesh() { }
180196
};
181197

182198
class Renderer {
183199
public:
184200
void render(glm::mat4 global_transform) {
185-
//TODO: mutex for modifying mesh vector
186-
m_mesh.erase(std::remove_if(m_mesh.begin(), m_mesh.end(), [](auto& mesh) { return mesh->m_delete; }), m_mesh.end());
201+
m_mesh.erase(
202+
std::remove_if(
203+
m_mesh.begin(), m_mesh.end(),
204+
[](auto& mesh) {
205+
if (mesh->m_delete) {
206+
mesh->free_gpu_resources();
207+
return true;
208+
}
209+
return false;
210+
}
211+
),
212+
m_mesh.end()
213+
);
214+
187215
for (auto& mesh : m_mesh) {
188216
mesh->render(global_transform);
189217
}

‎src/MarlinSimulator/visualisation.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,13 @@ void Visualisation::update() {
198198
auto pos = glm::vec3(ext.position.x, ext.position.y, ext.position.z);
199199
if (m_extruder_mesh[mesh_id]->m_position != pos) {
200200
m_extruder_mesh[mesh_id]->m_position = pos;
201-
m_extruder_mesh[mesh_id]->m_dirty = true;
201+
m_extruder_mesh[mesh_id]->m_transform_dirty = true;
202202
}
203203
m_extruder_mesh[mesh_id]->m_visible = (follow_mode != FOLLOW_Z);
204204
mesh_id ++;
205205
}
206206

207+
// TODO: Shaders need this internalised
207208
glUseProgram( path_program );
208209
glUniform1f( glGetUniformLocation( path_program, "u_layer_thickness" ), extrude_thickness);
209210
glUniform1f( glGetUniformLocation( path_program, "u_layer_width" ), extrude_width);
@@ -225,6 +226,11 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
225226
auto& extruder = extrusion[hotend_index];
226227
glm::vec3 extrude_color = state.color;
227228

229+
if (extruder.mesh != nullptr && extruder.mesh->m_delete) {
230+
extruder.active_mesh_buffer.reset();
231+
extruder.mesh.reset();
232+
}
233+
228234
if (position != extruder.position) {
229235

230236
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
@@ -235,7 +241,7 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
235241
if (extruder.active_mesh_buffer != nullptr && extruder.active_mesh_buffer->size() > 1 && extruder.active_mesh_buffer->size() < renderer::Renderer::MAX_BUFFER_SIZE) {
236242

237243
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
238-
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)) {
244+
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)) {
239245
// collinear and extrusion state has not changed so we can just change the current point.
240246
extruder.active_mesh_buffer->data().end()[-2].position = position;
241247
extruder.active_mesh_buffer->data().end()[-1].position = position;
@@ -280,8 +286,8 @@ void Visualisation::set_head_position(size_t hotend_index, extruder_state state)
280286
}
281287
}
282288

283-
bool Visualisation::points_are_collinear(glm::vec3 a, glm::vec3 b, glm::vec3 c) {
284-
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
289+
bool Visualisation::points_are_collinear(const glm::vec3 a, const glm::vec3 b, const glm::vec3 c, const double threshold) const {
290+
return glm::abs(glm::dot(b - a, c - a) - (glm::length(b - a) * glm::length(c - a))) < threshold;
285291
}
286292

287293
void Visualisation::ui_viewport_callback(UiWindow* window) {
@@ -406,9 +412,7 @@ void Visualisation::ui_info_callback(UiWindow* w) {
406412
if (ImGui::Button("Clear Print Area")) {
407413
for (auto& extruder : extrusion) {
408414
if (extruder.mesh != nullptr) {
409-
extruder.active_mesh_buffer.reset();
410415
extruder.mesh->m_delete = true;
411-
extruder.mesh.reset();
412416
}
413417
}
414418
}

‎src/MarlinSimulator/visualisation.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class Visualisation {
192192

193193
const float filiment_diameter = 1.75;
194194
void set_head_position(size_t hotend_index, extruder_state position);
195-
bool points_are_collinear(glm::vec3 a, glm::vec3 b, glm::vec3 c);
195+
bool points_are_collinear(const glm::vec3 a, const glm::vec3 b, const glm::vec3 c, const double threshold) const;
196196

197197
FollowMode follow_mode = FOLLOW_NONE;
198198
bool render_full_path = true;

0 commit comments

Comments
 (0)
Please sign in to comment.