From 6e75eb34afe83c9c57bd3679d2244b42e0cd0bfe Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 12 Mar 2024 23:38:09 +0100 Subject: [PATCH 1/4] Make lines update in real-time in the simulation-view too. This approach does suffer from returning to exactly the same point, which can mess up the view. part of CURA-11521 --- plugins/SimulationView/SimulationPass.py | 10 +++++++++- plugins/SimulationView/layers3d.shader | 8 ++++++++ plugins/SimulationView/layers3d_shadow.shader | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 2099f6c21d..ab876b94cf 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -143,6 +143,7 @@ class SimulationPass(RenderPass): if self._layer_view.getCurrentLayer() > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 + towards_next_vertex = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): # In the current layer, we show just the indicated paths @@ -162,12 +163,19 @@ class SimulationPass(RenderPass): if ratio <= 0.0001 or index + 1 == len(polygon.data): # in case there multiple polygons and polygon changes, the first point has the same value as the last point in the previous polygon head_position = pos_a + node.getWorldPosition() + self._layer_shader.setUniformValue("u_last_vertex", pos_a) + self._layer_shader.setUniformValue("u_next_vertex", pos_a) + self._layer_shader.setUniformValue("u_last_line_ratio", 1.0) else: pos_b = Vector(polygon.data[index + 1][0], polygon.data[index + 1][1], polygon.data[index + 1][2]) vec = pos_a * (1.0 - ratio) + pos_b * ratio head_position = vec + node.getWorldPosition() + towards_next_vertex = 2 + self._layer_shader.setUniformValue("u_last_vertex", pos_a) + self._layer_shader.setUniformValue("u_next_vertex", pos_b) + self._layer_shader.setUniformValue("u_last_line_ratio", ratio) break break if self._layer_view.getMinimumLayer() > layer: @@ -176,7 +184,7 @@ class SimulationPass(RenderPass): # Calculate the range of paths in the last layer current_layer_start = end - current_layer_end = end + int( self._layer_view.getCurrentPath()) * 2 # Because each point is used twice + current_layer_end = end + towards_next_vertex + int( self._layer_view.getCurrentPath()) * 2 # Because each point is used twice # This uses glDrawRangeElements internally to only draw a certain range of lines. # All the layers but the current selected layer are rendered first diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index b43d998690..4b6b53c62f 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -19,6 +19,10 @@ vertex41core = uniform highp mat4 u_normalMatrix; + uniform vec3 u_last_vertex; + uniform vec3 u_next_vertex; + uniform float u_last_line_ratio; + in highp vec4 a_vertex; in lowp vec4 a_color; in lowp vec4 a_material_color; @@ -134,6 +138,10 @@ vertex41core = void main() { vec4 v1_vertex = a_vertex; + if (v1_vertex.xyz == u_next_vertex) + { + v1_vertex.xyz = mix(u_last_vertex, u_next_vertex, u_last_line_ratio); + } v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 88268938c9..03871a9be0 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -10,6 +10,10 @@ vertex41core = uniform highp mat4 u_normalMatrix; + uniform vec3 u_last_vertex; + uniform vec3 u_next_vertex; + uniform float u_last_line_ratio; + in highp vec4 a_vertex; in lowp vec4 a_color; in lowp vec4 a_grayColor; @@ -35,6 +39,10 @@ vertex41core = void main() { vec4 v1_vertex = a_vertex; + if (v1_vertex.xyz == u_next_vertex) + { + v1_vertex.xyz = mix(u_last_vertex, u_next_vertex, u_last_line_ratio); + } v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; @@ -274,6 +282,8 @@ u_viewMatrix = view_matrix u_projectionMatrix = projection_matrix u_normalMatrix = normal_matrix u_lightPosition = light_0_position +u_lastVertex = last_vertex +u_nextVertex = next_vertex [attributes] a_vertex = vertex From d6295171dd817285d962a0c5cf8cf4f3a81529d1 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 13 Mar 2024 08:43:41 +0100 Subject: [PATCH 2/4] Add the last line (when time-sim active) as a separate batch instead. part of CURA-11521 --- plugins/SimulationView/SimulationPass.py | 31 ++++++++++++++----- plugins/SimulationView/layers3d.shader | 4 +++ plugins/SimulationView/layers3d_shadow.shader | 10 ------ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index ab876b94cf..d9aef98385 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -121,6 +121,7 @@ class SimulationPass(RenderPass): disabled_batch = RenderBatch(self._disabled_shader) head_position = None # Indicates the current position of the print head nozzle_node = None + not_a_vector = Vector(math.nan, math.nan, math.nan) for node in DepthFirstIterator(self._scene.getRoot()): @@ -143,6 +144,9 @@ class SimulationPass(RenderPass): if self._layer_view.getCurrentLayer() > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 + vertex_before_head = not_a_vector + vertex_after_head = not_a_vector + last_to_next_ratio = 0.0 towards_next_vertex = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): @@ -160,22 +164,19 @@ class SimulationPass(RenderPass): ratio = self._layer_view.getCurrentPath() - math.floor(self._layer_view.getCurrentPath()) pos_a = Vector(polygon.data[index][0], polygon.data[index][1], polygon.data[index][2]) + vertex_before_head = pos_a + last_to_next_ratio = ratio if ratio <= 0.0001 or index + 1 == len(polygon.data): # in case there multiple polygons and polygon changes, the first point has the same value as the last point in the previous polygon head_position = pos_a + node.getWorldPosition() - self._layer_shader.setUniformValue("u_last_vertex", pos_a) - self._layer_shader.setUniformValue("u_next_vertex", pos_a) - self._layer_shader.setUniformValue("u_last_line_ratio", 1.0) else: pos_b = Vector(polygon.data[index + 1][0], polygon.data[index + 1][1], polygon.data[index + 1][2]) vec = pos_a * (1.0 - ratio) + pos_b * ratio head_position = vec + node.getWorldPosition() + vertex_after_head = pos_b towards_next_vertex = 2 - self._layer_shader.setUniformValue("u_last_vertex", pos_a) - self._layer_shader.setUniformValue("u_next_vertex", pos_b) - self._layer_shader.setUniformValue("u_last_line_ratio", ratio) break break if self._layer_view.getMinimumLayer() > layer: @@ -184,7 +185,7 @@ class SimulationPass(RenderPass): # Calculate the range of paths in the last layer current_layer_start = end - current_layer_end = end + towards_next_vertex + int( self._layer_view.getCurrentPath()) * 2 # Because each point is used twice + current_layer_end = end + int( self._layer_view.getCurrentPath()) * 2 # Because each point is used twice # This uses glDrawRangeElements internally to only draw a certain range of lines. # All the layers but the current selected layer are rendered first @@ -195,6 +196,11 @@ class SimulationPass(RenderPass): self._current_shader = self._layer_shader self._switching_layers = True + # reset 'last vertex' + self._layer_shader.setUniformValue("u_last_vertex", not_a_vector) + self._layer_shader.setUniformValue("u_next_vertex", not_a_vector) + self._layer_shader.setUniformValue("u_last_line_ratio", 1.0) + # The first line does not have a previous line: add a MoveCombingType in front for start detection # this way the first start of the layer can also be drawn prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) @@ -211,6 +217,17 @@ class SimulationPass(RenderPass): current_layer_batch.addItem(node.getWorldTransformation(), layer_data) current_layer_batch.render(self._scene.getActiveCamera()) + # Last line may be partial + if vertex_after_head != not_a_vector and vertex_after_head != not_a_vector: + self._layer_shader.setUniformValue("u_last_vertex", vertex_before_head) + self._layer_shader.setUniformValue("u_next_vertex", vertex_after_head) + self._layer_shader.setUniformValue("u_last_line_ratio", last_to_next_ratio) + last_line_start = current_layer_end + last_line_end = current_layer_end + towards_next_vertex + last_line_batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range = (last_line_start, last_line_end)) + last_line_batch.addItem(node.getWorldTransformation(), layer_data) + last_line_batch.render(self._scene.getActiveCamera()) + self._old_current_layer = self._layer_view.getCurrentLayer() self._old_current_path = self._layer_view.getCurrentPath() diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index 4b6b53c62f..508126e163 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -435,6 +435,10 @@ u_max_feedrate = 1 u_min_thickness = 0 u_max_thickness = 1 +u_last_vertex = [0.0, 0.0, 0.0] +u_next_vertex = [0.0, 0.0, 0.0] +u_last_line_ratio = 1.0 + [bindings] u_modelMatrix = model_matrix u_viewMatrix = view_matrix diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 03871a9be0..88268938c9 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -10,10 +10,6 @@ vertex41core = uniform highp mat4 u_normalMatrix; - uniform vec3 u_last_vertex; - uniform vec3 u_next_vertex; - uniform float u_last_line_ratio; - in highp vec4 a_vertex; in lowp vec4 a_color; in lowp vec4 a_grayColor; @@ -39,10 +35,6 @@ vertex41core = void main() { vec4 v1_vertex = a_vertex; - if (v1_vertex.xyz == u_next_vertex) - { - v1_vertex.xyz = mix(u_last_vertex, u_next_vertex, u_last_line_ratio); - } v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; @@ -282,8 +274,6 @@ u_viewMatrix = view_matrix u_projectionMatrix = projection_matrix u_normalMatrix = normal_matrix u_lightPosition = light_0_position -u_lastVertex = last_vertex -u_nextVertex = next_vertex [attributes] a_vertex = vertex From 5dcab953581b09ba056a4fda47055fada43c87a3 Mon Sep 17 00:00:00 2001 From: Remco Burema <41987080+rburema@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:10:04 +0100 Subject: [PATCH 3/4] Code review: change name to 'vertex_distance_ratio'. To be better in line with the other variables. Done as part of CURA-11521 Co-authored-by: Saumya Jain <70144862+saumyaj3@users.noreply.github.com> --- plugins/SimulationView/SimulationPass.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index d9aef98385..b723403797 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -146,7 +146,7 @@ class SimulationPass(RenderPass): end = 0 vertex_before_head = not_a_vector vertex_after_head = not_a_vector - last_to_next_ratio = 0.0 + vertex_distance_ratio = 0.0 towards_next_vertex = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): @@ -165,7 +165,7 @@ class SimulationPass(RenderPass): pos_a = Vector(polygon.data[index][0], polygon.data[index][1], polygon.data[index][2]) vertex_before_head = pos_a - last_to_next_ratio = ratio + vertex_distance_ratio = ratio if ratio <= 0.0001 or index + 1 == len(polygon.data): # in case there multiple polygons and polygon changes, the first point has the same value as the last point in the previous polygon head_position = pos_a + node.getWorldPosition() @@ -221,7 +221,7 @@ class SimulationPass(RenderPass): if vertex_after_head != not_a_vector and vertex_after_head != not_a_vector: self._layer_shader.setUniformValue("u_last_vertex", vertex_before_head) self._layer_shader.setUniformValue("u_next_vertex", vertex_after_head) - self._layer_shader.setUniformValue("u_last_line_ratio", last_to_next_ratio) + self._layer_shader.setUniformValue("u_last_line_ratio", vertex_distance_ratio) last_line_start = current_layer_end last_line_end = current_layer_end + towards_next_vertex last_line_batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range = (last_line_start, last_line_end)) From 778bd11a71e589a75ec7451fd3d275a466e1421c Mon Sep 17 00:00:00 2001 From: Remco Burema <41987080+rburema@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:13:03 +0100 Subject: [PATCH 4/4] Review comments to add a comment. Done as part of CURA-11521 --- plugins/SimulationView/SimulationPass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index b723403797..efe80162b5 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -176,7 +176,7 @@ class SimulationPass(RenderPass): vec = pos_a * (1.0 - ratio) + pos_b * ratio head_position = vec + node.getWorldPosition() vertex_after_head = pos_b - towards_next_vertex = 2 + towards_next_vertex = 2 # Add two to the index to print the current and next vertices as an 'unfinished' line (to the nozzle). break break if self._layer_view.getMinimumLayer() > layer: