From f184baadf0a396743268b29027a1d4031d73991d Mon Sep 17 00:00:00 2001 From: Johan K Date: Tue, 14 Jun 2016 18:08:35 +0200 Subject: [PATCH 1/6] Formulate layerview logic using numpy to speed up. Also changed layer data packets from engine to make it possible. --- cura/Layer.py | 102 ++++++++------ cura/LayerDataBuilder.py | 12 +- cura/LayerPolygon.py | 128 ++++++++++++++---- plugins/CuraEngineBackend/Cura.proto | 20 +-- .../ProcessSlicedLayersJob.py | 20 ++- plugins/LayerView/LayerView.py | 12 +- 6 files changed, 202 insertions(+), 92 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 904e5528a3..cb64d77c2d 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -35,24 +35,31 @@ class Layer: def setThickness(self, thickness): self._thickness = thickness - def vertexCount(self): + def lineMeshVertexCount(self): result = 0 for polygon in self._polygons: - result += polygon.vertexCount() + result += polygon.lineMeshVertexCount() return result - def build(self, offset, vertices, colors, indices): - result = offset + def lineMeshElementCount(self): + result = 0 for polygon in self._polygons: - if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: - continue + result += polygon.lineMeshElementCount() - polygon.build(result, vertices, colors, indices) - result += polygon.vertexCount() + return result + + def build(self, vertex_offset, index_offset, vertices, colors, indices): + result_vertex_offset = vertex_offset + result_index_offset = index_offset + self._element_count = 0 + for polygon in self._polygons: + polygon.build(result_vertex_offset, result_index_offset, vertices, colors, indices) + result_vertex_offset += polygon.lineMeshVertexCount() + result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount - return result + return (result_vertex_offset,result_index_offset) def createMesh(self): return self.createMeshOrJumps(True) @@ -61,39 +68,58 @@ class Layer: return self.createMeshOrJumps(False) def createMeshOrJumps(self, make_mesh): - builder = MeshBuilder() - + builder = MeshBuilder() # This is never really used, only the mesh_data inside + index_pattern = numpy.array([[0,3,2,0,1,3]],dtype = numpy.int32 ) + + line_count = 0 + if make_mesh: + for polygon in self._polygons: + line_count += polygon._mesh_line_count + else: + for polygon in self._polygons: + line_count += polygon._jump_count + + + # Reserve the neccesary space for the data upfront + builder.reserveFaceAndVerticeCount( 2*line_count, 4*line_count ) + for polygon in self._polygons: - if make_mesh and (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): - continue - if not make_mesh and not (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): - continue + #if make_mesh and (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): + # continue + #if not make_mesh and not (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): + # continue + + index_mask = numpy.logical_not(polygon._jump_mask) if make_mesh else polygon._jump_mask - poly_color = polygon.getColor() + # Create an array with rows [p p+1] and only save those we whant to draw based on make_mesh + points = numpy.concatenate((polygon.data[:-1],polygon.data[1:]),1)[index_mask.ravel()] + # Line types of the points we want to draw + line_types = polygon._types[index_mask] + + + #if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.SkinType or polygon.type == LayerPolygon.SupportInfillType: + # points[:,1] -= 0.01 + #if polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: + # points[:,1] += 0.01 + # Shift the z-axis according to previous implementation. + if make_mesh: + points[polygon._orInfillSkin[line_types],1::3] -= 0.01 + else: + points[:,1::3] += 0.01 - points = numpy.copy(polygon.data) - if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.SkinType or polygon.type == LayerPolygon.SupportInfillType: - points[:,1] -= 0.01 - if polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: - points[:,1] += 0.01 + # Create an array with normals and tile 2 copies to match size of points variable + normals = numpy.tile( polygon.getNormals()[index_mask.ravel()], (1,2)) - normals = polygon.getNormals() + # Scale all normals by the line width of the current line so we can easily offset. + normals *= (polygon.lineWidths[index_mask.ravel()] / 2) - # Scale all by the line width of the polygon so we can easily offset. - normals *= (polygon.lineWidth / 2) + # Create 4 points to draw each line segment, points +- normals results in 2 points each. Reshape to one point per line + f_points = numpy.concatenate((points-normals,points+normals),1).reshape((-1,3)) + # index_pattern defines which points to use to draw the two faces for each lines egment, the following linesegment is offset by 4 + f_indices = ( index_pattern + numpy.arange(0,4*len(normals),4,dtype=numpy.int32).reshape((-1,1)) ).reshape((-1,3)) + f_colors = numpy.repeat(polygon._color_map[line_types], 4, 0) - #TODO: Use numpy magic to perform the vertex creation to speed up things. - for i in range(len(points)): - start = points[i - 1] - end = points[i] + builder.addFacesWithColor(f_points, f_indices, f_colors) - normal = normals[i - 1] - - point1 = Vector(data = start - normal) - point2 = Vector(data = start + normal) - point3 = Vector(data = end + normal) - point4 = Vector(data = end - normal) - - builder.addQuad(point1, point2, point3, point4, color = poly_color) - - return builder.build() + + return builder.build() \ No newline at end of file diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 7e8e0e636b..85f9a23e7b 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -50,18 +50,22 @@ class LayerDataBuilder(MeshBuilder): def build(self): vertex_count = 0 + index_count = 0 for layer, data in self._layers.items(): - vertex_count += data.vertexCount() + vertex_count += data.lineMeshVertexCount() + index_count += data.lineMeshElementCount() vertices = numpy.empty((vertex_count, 3), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) - indices = numpy.empty((vertex_count, 2), numpy.int32) + indices = numpy.empty((index_count, 2), numpy.int32) - offset = 0 + vertex_offset = 0 + index_offset = 0 for layer, data in self._layers.items(): - offset = data.build(offset, vertices, colors, indices) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices) self._element_counts[layer] = data.elementCount + self.clear() self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index c4dc5d4954..f2c84e0d57 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -14,40 +14,96 @@ class LayerPolygon: SupportInfillType = 7 MoveCombingType = 8 MoveRetractionType = 9 - - def __init__(self, mesh, polygon_type, data, line_width): + + __jump_map = numpy.logical_or( numpy.arange(10) == NoneType, numpy.arange(10) >= MoveCombingType ) + + def __init__(self, mesh, line_types, data, line_widths): self._mesh = mesh - self._type = polygon_type + self._types = line_types self._data = data - self._line_width = line_width / 1000 - self._begin = 0 - self._end = 0 + self._line_widths = line_widths / 1000 + + self._vertex_begin = 0 + self._vertex_end = 0 + self._index_begin = 0 + self._index_end = 0 + + self._jump_mask = self.__jump_map[self._types] + self._jump_count = numpy.sum(self._jump_mask) + self._mesh_line_count = len(self._types)-self._jump_count + self._vertex_count = self._mesh_line_count + numpy.sum( self._types[1:] == self._types[:-1]) - self._color = self.__color_map[polygon_type] + # Buffering the colors shouldn't be necessary as it is not + # re-used and can save alot of memory usage. + self._colors = self.__color_map[self._types] + self._color_map = self.__color_map + + # type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType + # Should be generated in better way, not hardcoded. + self._orInfillSkin = numpy.array([0,0,0,1,0,0,1,1,0,0],dtype=numpy.bool) + + self._build_cache_line_mesh_mask = None + self._build_cache_needed_points = None + + def build_cache(self): + #if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: + # continue + self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask,self._types == LayerPolygon.InfillType )) + mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask) + self._index_begin = 0 + self._index_end = mesh_line_count + + self._build_cache_needed_points = numpy.ones((len(self._types),2), dtype=numpy.bool) + # Only if the type of line segment changes do we need to add an extra vertex to change colors + self._build_cache_needed_points[1:,0][:,numpy.newaxis] = self._types[1:] != self._types[:-1] + # Remove points of types we don't want in the line mesh + numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points ) + + self._vertex_begin = 0 + self._vertex_end = numpy.sum( self._build_cache_needed_points ) + - def build(self, offset, vertices, colors, indices): - self._begin = offset - self._end = self._begin + len(self._data) - 1 + def build(self, vertex_offset, index_offset, vertices, colors, indices): + if (self._build_cache_line_mesh_mask == None) or (self._build_cache_needed_points == None ): + self.build_cache() + + line_mesh_mask = self._build_cache_line_mesh_mask + needed_points_list = self._build_cache_needed_points + + index_list = ( numpy.arange(len(self._types)).reshape((-1,1)) + numpy.array([[0,1]]) ).reshape((-1,1))[needed_points_list.reshape((-1,1))] + + self._vertex_begin += vertex_offset + self._vertex_end += vertex_offset + + vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :] + colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors,(1,2)).reshape((-1,4))[needed_points_list.ravel()] + colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) - vertices[self._begin:self._end + 1, :] = self._data[:, :] - colors[self._begin:self._end + 1, :] = numpy.array([self._color.r * 0.5, self._color.g * 0.5, self._color.b * 0.5, self._color.a], numpy.float32) + self._index_begin += index_offset + self._index_end += index_offset + + indices[self._index_begin:self._index_end,:] = numpy.arange(self._index_end-self._index_begin, dtype=numpy.int32).reshape((-1,1)) + # When the line type changes the index needs to be increased by 2. + indices[self._index_begin:self._index_end,:] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(),0],dtype=numpy.int32).reshape((-1,1)) + # Each line segment goes from it's starting point p to p+1, offset by the vertex index. + # The -1 is to compensate for the neccecarily True value of needed_points_list[0,0] which causes an unwanted +1 in cumsum above. + indices[self._index_begin:self._index_end,:] += numpy.array([self._vertex_begin - 1,self._vertex_begin]) + + self._build_cache_line_mesh_mask = None + self._build_cache_needed_points = None - for i in range(self._begin, self._end): - indices[i, 0] = i - indices[i, 1] = i + 1 + def getColors(self): + return self._colors - indices[self._end, 0] = self._end - indices[self._end, 1] = self._begin + def lineMeshVertexCount(self): + return (self._vertex_end - self._vertex_begin) - def getColor(self): - return self._color - - def vertexCount(self): - return len(self._data) + def lineMeshElementCount(self): + return (self._index_end - self._index_begin) @property - def type(self): - return self._type + def types(self): + return self._types @property def data(self): @@ -55,11 +111,11 @@ class LayerPolygon: @property def elementCount(self): - return ((self._end - self._begin) + 1) * 2 # The range of vertices multiplied by 2 since each vertex is used twice + return (self._index_end - self._index_begin) * 2 # The range of vertices multiplied by 2 since each vertex is used twice @property - def lineWidth(self): - return self._line_width + def lineWidths(self): + return self._line_widths # Calculate normals for the entire polygon using numpy. def getNormals(self): @@ -71,7 +127,8 @@ class LayerPolygon: # we end up subtracting each next point from the current, wrapping # around. This gives us the edges from the next point to the current # point. - normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0) + normals = numpy.diff(normals, 1, 0) + # Calculate the length of each edge using standard Pythagoras lengths = numpy.sqrt(normals[:, 0] ** 2 + normals[:, 2] ** 2) # The normal of a 2D vector is equal to its x and y coordinates swapped @@ -85,7 +142,7 @@ class LayerPolygon: return normals - __color_map = { + __color_mapping = { NoneType: Color(1.0, 1.0, 1.0, 1.0), Inset0Type: Color(1.0, 0.0, 0.0, 1.0), InsetXType: Color(0.0, 1.0, 0.0, 1.0), @@ -97,3 +154,16 @@ class LayerPolygon: MoveCombingType: Color(0.0, 0.0, 1.0, 1.0), MoveRetractionType: Color(0.5, 0.5, 1.0, 1.0), } + + # Should be generated in better way, not hardcoded. + __color_map = numpy.array([ + [1.0, 1.0, 1.0, 1.0], + [1.0, 0.0, 0.0, 1.0], + [0.0, 1.0, 0.0, 1.0], + [1.0, 1.0, 0.0, 1.0], + [0.0, 1.0, 1.0, 1.0], + [0.0, 1.0, 1.0, 1.0], + [1.0, 0.74, 0.0, 1.0], + [0.0, 1.0, 1.0, 1.0], + [0.0, 0.0, 1.0, 1.0], + [0.5, 0.5, 1.0, 1.0]]) diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 38753fd804..e40678c6a5 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -44,21 +44,9 @@ message Layer { } message Polygon { - enum Type { - NoneType = 0; - Inset0Type = 1; - InsetXType = 2; - SkinType = 3; - SupportType = 4; - SkirtType = 5; - InfillType = 6; - SupportInfillType = 7; - MoveCombingType = 8; - MoveRetractionType = 9; - } - Type type = 1; // Type of move - bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used) - float line_width = 3; // The width of the line being laid down + bytes line_type = 1; + bytes points = 2; + bytes line_width = 3; } message GCodeLayer { @@ -86,4 +74,4 @@ message GCodePrefix { } message SlicingFinished { -} \ No newline at end of file +} diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index d23f71e874..0aa34b8f3f 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -14,6 +14,7 @@ from UM.Math.Vector import Vector from cura import LayerDataBuilder from cura import LayerDataDecorator +from cura import LayerPolygon import numpy @@ -38,6 +39,12 @@ class ProcessSlicedLayersJob(Job): self._abort_requested = True def run(self): + # This is to prevent small models layer data to be cleared by extra invocation of engine + # Possibly adds an extra bug of layerdata not being removed if platform is cleared. + #TODO: remove need for this check + if len(self._layers) == 0: + return + if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView": self._progress = Message(catalog.i18nc("@info:status", "Processing Layers"), 0, False, -1) self._progress.show() @@ -80,15 +87,22 @@ class ProcessSlicedLayersJob(Job): abs_layer_number = layer.id + abs(min_layer_number) layer_data.addLayer(abs_layer_number) + this_layer = layer_data.getLayer(abs_layer_number) layer_data.setLayerHeight(abs_layer_number, layer.height) layer_data.setLayerThickness(abs_layer_number, layer.thickness) for p in range(layer.repeatedMessageCount("polygons")): polygon = layer.getRepeatedMessage("polygons", p) + line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array + line_types = line_types.reshape((-1,1)) + points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. + line_widths = numpy.fromstring(polygon.line_width, dtype="i4") # Convert bytearray to numpy array + line_widths = line_widths.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. + # Create a new 3D-array, copy the 2D points over and insert the right height. # This uses manual array creation + copy rather than numpy.insert since this is # faster. @@ -99,7 +113,11 @@ class ProcessSlicedLayersJob(Job): new_points /= 1000 - layer_data.addPolygon(abs_layer_number, polygon.type, new_points, polygon.line_width) + this_poly = LayerPolygon.LayerPolygon(layer_data, line_types, new_points, line_widths) + this_poly.build_cache() + + this_layer.polygons.append(this_poly) + Job.yieldThread() Job.yieldThread() current_layer += 1 diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index cd7a17a357..90927ff39d 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -25,6 +25,8 @@ from . import LayerViewProxy from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") +import numpy + ## View used to display g-code paths. class LayerView(View): def __init__(self): @@ -42,7 +44,7 @@ class LayerView(View): self._top_layers_job = None self._activity = False - Preferences.getInstance().addPreference("view/top_layer_count", 1) + Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) @@ -255,12 +257,14 @@ class _CreateTopLayersJob(Job): if not layer or layer.getVertices() is None: continue + layer_mesh.addIndices(layer_mesh._vertex_count+layer.getIndices()) layer_mesh.addVertices(layer.getVertices()) - + # Scale layer color by a brightness factor based on the current layer number # This will result in a range of 0.5 - 1.0 to multiply colors by. - brightness = (2.0 - (i / self._solid_layers)) / 2.0 - layer_mesh.addColors(layer.getColors() * brightness) + brightness = numpy.ones((1,4),dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0 + brightness[0,3] = 1.0; + layer_mesh.addColors(layer.getColors() * brightness ) if self._cancel: return From 788f79f5ba5091dac9e119184321441fc5f602e1 Mon Sep 17 00:00:00 2001 From: Johan K Date: Wed, 15 Jun 2016 23:23:12 +0200 Subject: [PATCH 2/6] Changing the message used from the engine from Layer to LayerOptimized. --- plugins/CuraEngineBackend/Cura.proto | 37 +++++++++++++++++-- .../CuraEngineBackend/CuraEngineBackend.py | 20 +++++++--- .../ProcessSlicedLayersJob.py | 4 +- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index e40678c6a5..48dee7c9c1 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -44,11 +44,40 @@ message Layer { } message Polygon { - bytes line_type = 1; - bytes points = 2; - bytes line_width = 3; + enum Type { + NoneType = 0; + Inset0Type = 1; + InsetXType = 2; + SkinType = 3; + SupportType = 4; + SkirtType = 5; + InfillType = 6; + SupportInfillType = 7; + MoveCombingType = 8; + MoveRetractionType = 9; + } + Type type = 1; // Type of move + bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used) + float line_width = 3; // The width of the line being laid down } +message LayerOptimized { + int32 id = 1; + float height = 2; // Z position + float thickness = 3; // height of a single layer + + repeated PathSegment path_segment = 4; // layer data +} + + +message PathSegment { + int32 ordinal = 1; // The absolute ordinal of this line segment + bytes line_type = 2; // Type of line segment as an unsigned char array of length 1 or N, where N is the number of line segments in this path + bytes points = 3; // The points defining the line segments, bytes of int64[2]? array of length N+1 + bytes line_width = 4; // The widths of the line segments as bytes of a float?/int32? array of length 1 or N +} + + message GCodeLayer { bytes data = 2; } @@ -74,4 +103,4 @@ message GCodePrefix { } message SlicingFinished { -} +} \ No newline at end of file diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index c91e414a13..2edc558ba6 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -56,6 +56,7 @@ class CuraEngineBackend(Backend): Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] + self._stored_optimized_layer_data = [] #Triggers for when to (re)start slicing: self._global_container_stack = None @@ -76,6 +77,7 @@ class CuraEngineBackend(Backend): #Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage + self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage @@ -127,6 +129,7 @@ class CuraEngineBackend(Backend): ## Perform a slice of the scene. def slice(self): self._stored_layer_data = [] + self._stored_optimized_layer_data = [] if not self._enabled or not self._global_container_stack: #We shouldn't be slicing. return @@ -158,6 +161,7 @@ class CuraEngineBackend(Backend): self._slicing = False self._restart = True self._stored_layer_data = [] + self._stored_optimized_layer_data = [] if self._start_slice_job is not None: self._start_slice_job.cancel() @@ -257,6 +261,12 @@ class CuraEngineBackend(Backend): def _onLayerMessage(self, message): self._stored_layer_data.append(message) + ## Called when an optimized sliced layer data message is received from the engine. + # + # \param message The protobuf message containing sliced layer data. + def _onOptimizedLayerMessage(self, message): + self._stored_optimized_layer_data.append(message) + ## Called when a progress message is received from the engine. # # \param message The protobuf message containing the slicing progress. @@ -274,9 +284,9 @@ class CuraEngineBackend(Backend): self._slicing = False if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()): - self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_layer_data) + self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_optimized_layer_data) self._process_layers_job.start() - self._stored_layer_data = [] + self._stored_optimized_layer_data = [] ## Called when a g-code message is received from the engine. # @@ -344,10 +354,10 @@ class CuraEngineBackend(Backend): self._layer_view_active = True # There is data and we're not slicing at the moment # if we are slicing, there is no need to re-calculate the data as it will be invalid in a moment. - if self._stored_layer_data and not self._slicing: - self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_layer_data) + if self._stored_optimized_layer_data and not self._slicing: + self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_optimized_layer_data) self._process_layers_job.start() - self._stored_layer_data = [] + self._stored_optimized_layer_data = [] else: self._layer_view_active = False diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 0aa34b8f3f..9f235c14be 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -91,8 +91,8 @@ class ProcessSlicedLayersJob(Job): layer_data.setLayerHeight(abs_layer_number, layer.height) layer_data.setLayerThickness(abs_layer_number, layer.thickness) - for p in range(layer.repeatedMessageCount("polygons")): - polygon = layer.getRepeatedMessage("polygons", p) + for p in range(layer.repeatedMessageCount("path_segment")): + polygon = layer.getRepeatedMessage("path_segment", p) line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array line_types = line_types.reshape((-1,1)) From 41503d7d5b57a04d18857f4fd539b3978d2a357c Mon Sep 17 00:00:00 2001 From: Johan Kristensen Date: Tue, 28 Jun 2016 23:50:00 +0200 Subject: [PATCH 3/6] Adapting code to merge of simple_convex_hull and code cleanup. --- cura/Layer.py | 45 ++++++-------- cura/LayerDataBuilder.py | 1 - cura/LayerPolygon.py | 59 +++++++++++++------ .../ProcessSlicedLayersJob.py | 2 +- plugins/LayerView/LayerView.py | 8 +-- 5 files changed, 65 insertions(+), 50 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index cb64d77c2d..03b96f4f3a 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -59,7 +59,7 @@ class Layer: result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount - return (result_vertex_offset,result_index_offset) + return (result_vertex_offset, result_index_offset) def createMesh(self): return self.createMeshOrJumps(True) @@ -68,56 +68,47 @@ class Layer: return self.createMeshOrJumps(False) def createMeshOrJumps(self, make_mesh): - builder = MeshBuilder() # This is never really used, only the mesh_data inside - index_pattern = numpy.array([[0,3,2,0,1,3]],dtype = numpy.int32 ) + builder = MeshBuilder() + index_pattern = numpy.array([[0, 3, 2, 0, 1, 3]], dtype = numpy.int32 ) line_count = 0 if make_mesh: for polygon in self._polygons: - line_count += polygon._mesh_line_count + line_count += polygon.meshLineCount else: for polygon in self._polygons: - line_count += polygon._jump_count + line_count += polygon.jumpCount # Reserve the neccesary space for the data upfront - builder.reserveFaceAndVerticeCount( 2*line_count, 4*line_count ) + builder.reserveFaceAndVertexCount(2 * line_count, 4 * line_count) for polygon in self._polygons: - #if make_mesh and (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): - # continue - #if not make_mesh and not (polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType): - # continue - - index_mask = numpy.logical_not(polygon._jump_mask) if make_mesh else polygon._jump_mask + # Filter out the types of lines we are not interesed in depending on whether we are drawing the mesh or the jumps. + index_mask = numpy.logical_not(polygon.jumpMask) if make_mesh else polygon.jumpMask - # Create an array with rows [p p+1] and only save those we whant to draw based on make_mesh - points = numpy.concatenate((polygon.data[:-1],polygon.data[1:]),1)[index_mask.ravel()] + # Create an array with rows [p p+1] and only keep those we whant to draw based on make_mesh + points = numpy.concatenate((polygon.data[:-1], polygon.data[1:]), 1)[index_mask.ravel()] # Line types of the points we want to draw - line_types = polygon._types[index_mask] + line_types = polygon.types[index_mask] - - #if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.SkinType or polygon.type == LayerPolygon.SupportInfillType: - # points[:,1] -= 0.01 - #if polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: - # points[:,1] += 0.01 - # Shift the z-axis according to previous implementation. + # Shift the z-axis according to previous implementation. if make_mesh: - points[polygon._orInfillSkin[line_types],1::3] -= 0.01 + points[polygon.isInfillOrSkinType(line_types), 1::3] -= 0.01 else: - points[:,1::3] += 0.01 + points[:, 1::3] += 0.01 # Create an array with normals and tile 2 copies to match size of points variable - normals = numpy.tile( polygon.getNormals()[index_mask.ravel()], (1,2)) + normals = numpy.tile( polygon.getNormals()[index_mask.ravel()], (1, 2)) # Scale all normals by the line width of the current line so we can easily offset. normals *= (polygon.lineWidths[index_mask.ravel()] / 2) # Create 4 points to draw each line segment, points +- normals results in 2 points each. Reshape to one point per line - f_points = numpy.concatenate((points-normals,points+normals),1).reshape((-1,3)) + f_points = numpy.concatenate((points-normals, points+normals), 1).reshape((-1, 3)) # index_pattern defines which points to use to draw the two faces for each lines egment, the following linesegment is offset by 4 - f_indices = ( index_pattern + numpy.arange(0,4*len(normals),4,dtype=numpy.int32).reshape((-1,1)) ).reshape((-1,3)) - f_colors = numpy.repeat(polygon._color_map[line_types], 4, 0) + f_indices = ( index_pattern + numpy.arange(0, 4 * len(normals), 4, dtype=numpy.int32).reshape((-1, 1)) ).reshape((-1, 3)) + f_colors = numpy.repeat(polygon.mapLineTypeToColor(line_types), 4, 0) builder.addFacesWithColor(f_points, f_indices, f_colors) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 85f9a23e7b..2215ed5f27 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -65,7 +65,6 @@ class LayerDataBuilder(MeshBuilder): ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices) self._element_counts[layer] = data.elementCount - self.clear() self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index f2c84e0d57..b063660198 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -38,25 +38,24 @@ class LayerPolygon: self._colors = self.__color_map[self._types] self._color_map = self.__color_map - # type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType + # When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType # Should be generated in better way, not hardcoded. - self._orInfillSkin = numpy.array([0,0,0,1,0,0,1,1,0,0],dtype=numpy.bool) + self._isInfillOrSkinTypeMap = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0], dtype=numpy.bool) self._build_cache_line_mesh_mask = None self._build_cache_needed_points = None - def build_cache(self): - #if polygon.type == LayerPolygon.InfillType or polygon.type == LayerPolygon.MoveCombingType or polygon.type == LayerPolygon.MoveRetractionType: - # continue - self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask,self._types == LayerPolygon.InfillType )) + def buildCache(self): + # For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out. + self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask, self._types == LayerPolygon.InfillType )) mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask) self._index_begin = 0 self._index_end = mesh_line_count - self._build_cache_needed_points = numpy.ones((len(self._types),2), dtype=numpy.bool) + self._build_cache_needed_points = numpy.ones((len(self._types), 2), dtype=numpy.bool) # Only if the type of line segment changes do we need to add an extra vertex to change colors - self._build_cache_needed_points[1:,0][:,numpy.newaxis] = self._types[1:] != self._types[:-1] - # Remove points of types we don't want in the line mesh + self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1] + # Mark points as unneeded if they are of types we don't want in the line mesh according to the calculated mask numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points ) self._vertex_begin = 0 @@ -65,29 +64,36 @@ class LayerPolygon: def build(self, vertex_offset, index_offset, vertices, colors, indices): if (self._build_cache_line_mesh_mask == None) or (self._build_cache_needed_points == None ): - self.build_cache() + self.buildCache() line_mesh_mask = self._build_cache_line_mesh_mask needed_points_list = self._build_cache_needed_points - - index_list = ( numpy.arange(len(self._types)).reshape((-1,1)) + numpy.array([[0,1]]) ).reshape((-1,1))[needed_points_list.reshape((-1,1))] + # Index to the points we need to represent the line mesh. This is constructed by generating simple + # start and end points for each line. For line segment n these are points n and n+1. Row n reads [n n+1] + # Then then the indices for the points we don't need are thrown away based on the pre-calculated list. + index_list = ( numpy.arange(len(self._types)).reshape((-1, 1)) + numpy.array([[0, 1]]) ).reshape((-1, 1))[needed_points_list.reshape((-1, 1))] + + # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._vertex_begin += vertex_offset self._vertex_end += vertex_offset + # Points are picked based on the index list to get the vertices needed. vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :] - colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors,(1,2)).reshape((-1,4))[needed_points_list.ravel()] + # Create an array with colors for each vertex and remove the color data for the points that has been thrown away. + colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()] colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) + # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._index_begin += index_offset self._index_end += index_offset - indices[self._index_begin:self._index_end,:] = numpy.arange(self._index_end-self._index_begin, dtype=numpy.int32).reshape((-1,1)) + indices[self._index_begin:self._index_end, :] = numpy.arange(self._index_end-self._index_begin, dtype=numpy.int32).reshape((-1, 1)) # When the line type changes the index needs to be increased by 2. - indices[self._index_begin:self._index_end,:] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(),0],dtype=numpy.int32).reshape((-1,1)) + indices[self._index_begin:self._index_end, :] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(), 0], dtype=numpy.int32).reshape((-1, 1)) # Each line segment goes from it's starting point p to p+1, offset by the vertex index. # The -1 is to compensate for the neccecarily True value of needed_points_list[0,0] which causes an unwanted +1 in cumsum above. - indices[self._index_begin:self._index_end,:] += numpy.array([self._vertex_begin - 1,self._vertex_begin]) + indices[self._index_begin:self._index_end, :] += numpy.array([self._vertex_begin - 1, self._vertex_begin]) self._build_cache_line_mesh_mask = None self._build_cache_needed_points = None @@ -95,6 +101,12 @@ class LayerPolygon: def getColors(self): return self._colors + def mapLineTypeToColor(self, line_types): + return self._color_map[line_types] + + def isInfillOrSkinType(self, line_types): + return self._isInfillOrSkinTypeMap[line_types] + def lineMeshVertexCount(self): return (self._vertex_end - self._vertex_begin) @@ -116,6 +128,18 @@ class LayerPolygon: @property def lineWidths(self): return self._line_widths + + @property + def jumpMask(self): + return self._jump_mask + + @property + def meshLineCount(self): + return self._mesh_line_count + + @property + def jumpCount(self): + return self._jump_count # Calculate normals for the entire polygon using numpy. def getNormals(self): @@ -166,4 +190,5 @@ class LayerPolygon: [1.0, 0.74, 0.0, 1.0], [0.0, 1.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0], - [0.5, 0.5, 1.0, 1.0]]) + [0.5, 0.5, 1.0, 1.0] + ]) \ No newline at end of file diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 9f235c14be..44e7de7599 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -114,7 +114,7 @@ class ProcessSlicedLayersJob(Job): new_points /= 1000 this_poly = LayerPolygon.LayerPolygon(layer_data, line_types, new_points, line_widths) - this_poly.build_cache() + this_poly.buildCache() this_layer.polygons.append(this_poly) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 90927ff39d..a993dc3f61 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -259,12 +259,12 @@ class _CreateTopLayersJob(Job): layer_mesh.addIndices(layer_mesh._vertex_count+layer.getIndices()) layer_mesh.addVertices(layer.getVertices()) - + # Scale layer color by a brightness factor based on the current layer number # This will result in a range of 0.5 - 1.0 to multiply colors by. - brightness = numpy.ones((1,4),dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0 - brightness[0,3] = 1.0; - layer_mesh.addColors(layer.getColors() * brightness ) + brightness = numpy.ones((1,4), dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0 + brightness[0, 3] = 1.0; + layer_mesh.addColors(layer.getColors() * brightness) if self._cancel: return From d31516bbb12d98e11c9b78317a10210a6401caa1 Mon Sep 17 00:00:00 2001 From: Johan K Date: Tue, 12 Jul 2016 01:32:46 +0200 Subject: [PATCH 4/6] Code cleanup Changed to "is None" insted of "== None" to test if numpy.array was initialized Added extruder to PathSegment in Cura.proto Changed index_pattern to class variable in Layer.py --- cura/Layer.py | 8 +++++--- cura/LayerPolygon.py | 2 +- plugins/CuraEngineBackend/Cura.proto | 15 ++++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 03b96f4f3a..4e38a6eba9 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -67,9 +67,11 @@ class Layer: def createJumps(self): return self.createMeshOrJumps(False) + # Defines the two triplets of local point indices to use to draw the two faces for each line segment in createMeshOrJump + __index_pattern = numpy.array([[0, 3, 2, 0, 1, 3]], dtype = numpy.int32 ) + def createMeshOrJumps(self, make_mesh): builder = MeshBuilder() - index_pattern = numpy.array([[0, 3, 2, 0, 1, 3]], dtype = numpy.int32 ) line_count = 0 if make_mesh: @@ -106,8 +108,8 @@ class Layer: # Create 4 points to draw each line segment, points +- normals results in 2 points each. Reshape to one point per line f_points = numpy.concatenate((points-normals, points+normals), 1).reshape((-1, 3)) - # index_pattern defines which points to use to draw the two faces for each lines egment, the following linesegment is offset by 4 - f_indices = ( index_pattern + numpy.arange(0, 4 * len(normals), 4, dtype=numpy.int32).reshape((-1, 1)) ).reshape((-1, 3)) + # __index_pattern defines which points to use to draw the two faces for each lines egment, the following linesegment is offset by 4 + f_indices = ( self.__index_pattern + numpy.arange(0, 4 * len(normals), 4, dtype=numpy.int32).reshape((-1, 1)) ).reshape((-1, 3)) f_colors = numpy.repeat(polygon.mapLineTypeToColor(line_types), 4, 0) builder.addFacesWithColor(f_points, f_indices, f_colors) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index b063660198..c534592757 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -63,7 +63,7 @@ class LayerPolygon: def build(self, vertex_offset, index_offset, vertices, colors, indices): - if (self._build_cache_line_mesh_mask == None) or (self._build_cache_needed_points == None ): + if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() line_mesh_mask = self._build_cache_line_mesh_mask diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index af4b40859d..d38f95035f 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -61,7 +61,7 @@ message Polygon { float line_width = 3; // The width of the line being laid down } -message LayerOptimized { +message LayerOptimized { int32 id = 1; float height = 2; // Z position float thickness = 3; // height of a single layer @@ -71,10 +71,15 @@ message LayerOptimized { message PathSegment { - int32 ordinal = 1; // The absolute ordinal of this line segment - bytes line_type = 2; // Type of line segment as an unsigned char array of length 1 or N, where N is the number of line segments in this path - bytes points = 3; // The points defining the line segments, bytes of int64[2]? array of length N+1 - bytes line_width = 4; // The widths of the line segments as bytes of a float?/int32? array of length 1 or N + int32 extruder = 1; // The extruder used for this path segment + enum PointType { + Point2D = 0; + Point3D = 1; + } + PointType point_type = 2; + bytes points = 3; // The points defining the line segments, bytes of int64[2/3]? array of length N+1 + bytes line_type = 4; // Type of line segment as an unsigned char array of length 1 or N, where N is the number of line segments in this path + bytes line_width = 5; // The widths of the line segments as bytes of a float? array of length 1 or N } From 3d413df215ae5cd042b1d9ebaa2096224a46d0ac Mon Sep 17 00:00:00 2001 From: Johan K Date: Thu, 14 Jul 2016 11:08:05 +0200 Subject: [PATCH 5/6] Changed the point data type sent from the backend from int64 to float. Added extruder information to LayerPolygon --- cura/LayerPolygon.py | 9 +++++-- plugins/CuraEngineBackend/Cura.proto | 4 +-- .../ProcessSlicedLayersJob.py | 27 ++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index c534592757..c62113916d 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -17,11 +17,12 @@ class LayerPolygon: __jump_map = numpy.logical_or( numpy.arange(10) == NoneType, numpy.arange(10) >= MoveCombingType ) - def __init__(self, mesh, line_types, data, line_widths): + def __init__(self, mesh, extruder, line_types, data, line_widths): self._mesh = mesh + self._extruder = extruder self._types = line_types self._data = data - self._line_widths = line_widths / 1000 + self._line_widths = line_widths self._vertex_begin = 0 self._vertex_end = 0 @@ -113,6 +114,10 @@ class LayerPolygon: def lineMeshElementCount(self): return (self._index_end - self._index_begin) + @property + def extruder(self): + return self._extruder + @property def types(self): return self._types diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index d38f95035f..0c4803cc19 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -77,9 +77,9 @@ message PathSegment { Point3D = 1; } PointType point_type = 2; - bytes points = 3; // The points defining the line segments, bytes of int64[2/3]? array of length N+1 + bytes points = 3; // The points defining the line segments, bytes of float[2/3] array of length N+1 bytes line_type = 4; // Type of line segment as an unsigned char array of length 1 or N, where N is the number of line segments in this path - bytes line_width = 5; // The widths of the line segments as bytes of a float? array of length 1 or N + bytes line_width = 5; // The widths of the line segments as bytes of a float array of length 1 or N } diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 44e7de7599..5101940c84 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -94,26 +94,35 @@ class ProcessSlicedLayersJob(Job): for p in range(layer.repeatedMessageCount("path_segment")): polygon = layer.getRepeatedMessage("path_segment", p) + extruder = polygon.extruder + line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array line_types = line_types.reshape((-1,1)) - points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array - points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. + points = numpy.fromstring(polygon.points, dtype="f4") # Convert bytearray to numpy array + if polygon.point_type == 0: # Point2D + points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. + else: # Point3D + points = points.reshape((-1,3)) - line_widths = numpy.fromstring(polygon.line_width, dtype="i4") # Convert bytearray to numpy array + line_widths = numpy.fromstring(polygon.line_width, dtype="f4") # Convert bytearray to numpy array line_widths = line_widths.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. # Create a new 3D-array, copy the 2D points over and insert the right height. # This uses manual array creation + copy rather than numpy.insert since this is # faster. new_points = numpy.empty((len(points), 3), numpy.float32) - new_points[:,0] = points[:,0] - new_points[:,1] = layer.height - new_points[:,2] = -points[:,1] + if polygon.point_type == 0: # Point2D + new_points[:,0] = points[:,0] + new_points[:,1] = layer.height/1000 # layer height value is in backend representation + new_points[:,2] = -points[:,1] + else: # Point3D + new_points[:,0] = points[:,0] + new_points[:,1] = points[:,2] + new_points[:,2] = -points[:,1] + - new_points /= 1000 - - this_poly = LayerPolygon.LayerPolygon(layer_data, line_types, new_points, line_widths) + this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths) this_poly.buildCache() this_layer.polygons.append(this_poly) From 4c402e5bb75954fd33c1ff153eee53fd31841a01 Mon Sep 17 00:00:00 2001 From: Johan K Date: Fri, 22 Jul 2016 10:22:07 +0200 Subject: [PATCH 6/6] Removed the layer data empty guard in ProcessSlicedLayers as the problem was solved in the backend. --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 9eb2f3e5cd..c2f73cf5b7 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -40,12 +40,6 @@ class ProcessSlicedLayersJob(Job): self._abort_requested = True def run(self): - # This is to prevent small models layer data to be cleared by extra invocation of engine - # Possibly adds an extra bug of layerdata not being removed if platform is cleared. - #TODO: remove need for this check - if len(self._layers) == 0: - return - start_time = time() if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView": self._progress = Message(catalog.i18nc("@info:status", "Processing Layers"), 0, False, -1)