def render(self): self._selection_map = self._toolhandle_selection_map.copy() batch = RenderBatch(self._shader) tool_handle = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) selectable_objects = False for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle.addItem(node.getWorldTransformation(), mesh = node.getSelectionMesh()) continue if node.isSelectable() and node.getMeshData(): selectable_objects = True batch.addItem(transformation = node.getWorldTransformation(), mesh = node.getMeshData(), uniforms = { "selection_color": self._getNodeColor(node)}) self.bind() if selectable_objects: batch.render(self._scene.getActiveCamera()) self._gl.glColorMask(self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_FALSE) self._gl.glDisable(self._gl.GL_DEPTH_TEST) tool_handle.render(self._scene.getActiveCamera()) self._gl.glEnable(self._gl.GL_DEPTH_TEST) self._gl.glColorMask(self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE) self.release()
def test_render(): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch = RenderBatch(mocked_shader) # Render without a camera shouldn't cause any effect. render_batch.render(None) assert mocked_shader.bind.call_count == 0 # Rendering with a camera should cause the shader to be bound and released (even if the batch is empty) mocked_camera = MagicMock() mocked_camera.getWorldTransformation = MagicMock(return_value=Matrix()) mocked_camera.getViewProjectionMatrix = MagicMock(return_value=Matrix()) with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 1 assert mocked_shader.release.call_count == 1 # Actualy render with an item in the batch mb = MeshBuilder() mb.addPyramid(10, 10, 10, color=Color(0.0, 1.0, 0.0, 1.0)) mb.calculateNormals() mesh_data = mb.build() render_batch.addItem(Matrix(), mesh_data, {}) with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 2 assert mocked_shader.release.call_count == 2
def test_addItem(data): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch = RenderBatch(mocked_shader) render_batch.addItem(**data["item"]) if data["should_add"]: assert len(render_batch.items) != 0
def test_render(): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch = RenderBatch(mocked_shader) # Render without a camera shouldn't cause any effect. render_batch.render(None) assert mocked_shader.bind.call_count == 0 # Rendering with a camera should cause the shader to be bound and released (even if the batch is empty) mocked_camera = MagicMock() mocked_camera.getWorldTransformation = MagicMock(return_value = Matrix()) mocked_camera.getViewProjectionMatrix = MagicMock(return_value=Matrix()) with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 1 assert mocked_shader.release.call_count == 1 # Actualy render with an item in the batch mb = MeshBuilder() mb.addPyramid(10, 10, 10, color=Color(0.0, 1.0, 0.0, 1.0)) mb.calculateNormals() mesh_data = mb.build() render_batch.addItem(Matrix(), mesh_data, {}) with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 2 assert mocked_shader.release.call_count == 2
def queueNode(self, node, **kwargs): type = kwargs.pop("type", RenderBatch.RenderType.Solid) if kwargs.pop("transparent", False): type = RenderBatch.RenderType.Transparent elif kwargs.pop("overlay", False): type = RenderBatch.RenderType.Overlay shader = kwargs.pop("shader", self._default_material) batch = RenderBatch(shader, type = type, **kwargs) batch.addItem(node.getWorldTransformation(), kwargs.get("mesh", node.getMeshData()), kwargs.pop("uniforms", None)) self._batches.append(batch)
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "overhang.shader")) self._shader.setUniformValue("u_overhangAngle", 1.0) self._gl.glClearColor(0.0, 0.0, 0.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create a new batch to be rendered batch = RenderBatch(self._shader) # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator(self._scene.getRoot()): if node.callDecoration( "isSliceable") and node.getMeshData() and node.isVisible(): uniforms = {} uniforms["diffuse_color"] = node.getDiffuseColor() batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms=uniforms) self.bind() if self._camera is None: batch.render(Application.getInstance().getController().getScene(). getActiveCamera()) else: batch.render(self._camera) self.release()
def render(self): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("XRayView"), "xray.shader")) batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, backface_cull = False, blend_mode = RenderBatch.BlendMode.Additive) for node in DepthFirstIterator(self._scene.getRoot()): if type(node) is SceneNode and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(), node.getMeshData()) self.bind() self._gl.glDisable(self._gl.GL_DEPTH_TEST) batch.render(self._scene.getActiveCamera()) self._gl.glEnable(self._gl.GL_DEPTH_TEST) self.release()
def createRenderBatch(self, **kwargs): type = kwargs.pop("type", RenderBatch.RenderType.Solid) if kwargs.pop("transparent", False): type = RenderBatch.RenderType.Transparent elif kwargs.pop("overlay", False): type = RenderBatch.RenderType.Overlay shader = kwargs.pop("shader", self._default_material) return RenderBatch(shader, type=type, **kwargs)
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "camera_distance.shader")) width, height = self.getSize() self._gl.glViewport(0, 0, width, height) self._gl.glClearColor(1.0, 1.0, 1.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create a new batch to be rendered batch = RenderBatch(self._shader) # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator(self._scene.getRoot()): if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(), node.getMeshData()) self.bind() batch.render(self._scene.getActiveCamera()) self.release()
def test_createRenderBatch(): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch = RenderBatch(mocked_shader) # Ensure that the proper defaults are set. assert render_batch.renderType == RenderBatch.RenderType.Solid assert render_batch.renderMode == RenderBatch.RenderMode.Triangles assert render_batch.shader == mocked_shader assert not render_batch.backfaceCull assert render_batch.renderRange is None assert render_batch.items == []
def render(self): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath("XRayView"), "xray.shader")) batch = RenderBatch(self._shader, type=RenderBatch.RenderType.NoType, backface_cull=False, blend_mode=RenderBatch.BlendMode.Additive) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance( node, CuraSceneNode) and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(), node.getMeshData()) self.bind() self._gl.glDisable(self._gl.GL_DEPTH_TEST) batch.render(self._scene.getActiveCamera()) self._gl.glEnable(self._gl.GL_DEPTH_TEST) self.release()
def render(self): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "xray.shader")) batch = RenderBatch(self._shader, type=RenderBatch.RenderType.NoType, backface_cull=False, blend_mode=RenderBatch.BlendMode.Additive) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance( node, CuraSceneNode) and node.getMeshData() and node.isVisible(): batch.addItem( node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) self.bind() self._gl.glDisable(self._gl.GL_DEPTH_TEST) batch.render(self._scene.getActiveCamera()) self._gl.glEnable(self._gl.GL_DEPTH_TEST) self.release()
def render(self) -> None: if not self._shader: try: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "camera_distance.shader")) except InvalidShaderProgramError: Logger.error( "Unable to compile shader program: camera_distance.shader") return width, height = self.getSize() self._gl.glViewport(0, 0, width, height) self._gl.glClearColor(1.0, 1.0, 1.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create a new batch to be rendered batch = RenderBatch(self._shader) # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator( self._scene.getRoot() ): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration( "isSliceable") and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(), node.getMeshData()) self.bind() batch.render(self._scene.getActiveCamera()) self.release()
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "object.shader")) # Create a new batch to be rendered batch = RenderBatch(self._shader) # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator(self._scene.getRoot()): if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(), node.getMeshData()) self.bind() if self._camera is None: batch.render(Application.getInstance().getController().getScene().getActiveCamera()) else: batch.render(self._camera) self.release()
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( os.path.join( os.path.dirname(os.path.abspath(__file__)), "resources", "shaders", "coordinates.shader", ) ) self._shader.setUniformValue("u_axisId", self._axis) # Create a new batch to be rendered batch = RenderBatch(self._shader) # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator(self._scene.getRoot()): # type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if ( node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible() ): batch.addItem(node.getWorldTransformation(), node.getMeshData()) z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting buildplate_transform = Matrix() buildplate_transform.setToIdentity() buildplate_transform.translate(Vector(0, z_fight_distance, 0)) buildplate_mesh = CuraApplication.getInstance().getBuildVolume()._grid_mesh batch.addItem(buildplate_transform, buildplate_mesh) width, height = self.getSize() self.bind() self._gl.glViewport(0, 0, width, height) self._gl.glClearColor(1.0, 1.0, 1.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) batch.render(self._scene.getActiveCamera()) self.release()
def _renderFacesMode(self): batch = RenderBatch(self._face_shader) selectable_objects = False for node in Selection.getAllSelectedObjects(): if isinstance(node, ToolHandle): continue # Ignore tool-handles in this mode. if node.isSelectable() and node.getMeshData(): selectable_objects = True batch.addItem(transformation=node.getWorldTransformation(), mesh=node.getMeshData()) self.bind() if selectable_objects: batch.render(self._scene.getActiveCamera()) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" shadow_shader_filename = "layers_shadow.shader" else: shader_filename = "layers3d.shader" shadow_shader_filename = "layers3d_shadow.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath( "SimulationView"), shader_filename)) self._layer_shadow_shader = OpenGL.getInstance( ).createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath( "SimulationView"), shadow_shader_filename)) self._current_shader = self._layer_shader self._updateLayerShaderValues() if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "toolhandle.shader")) if not self._nozzle_shader: self._nozzle_shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "color.shader")) self._nozzle_shader.setUniformValue( "u_color", Color(*Application.getInstance().getTheme().getColor( "layerview_nozzle").getRgb())) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type=RenderBatch.RenderType.Overlay, backface_cull=True) head_position = None # Indicates the current position of the print head nozzle_node = None for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh=node.getSolidMesh()) elif isinstance(node, NozzleNode): nozzle_node = node nozzle_node.setVisible(False) elif isinstance(node, SceneNode) and (node.getMeshData( ) or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ( (not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = self._layer_view.start_elements_index end = self._layer_view.end_elements_index index = self._layer_view._current_path_num offset = 0 for polygon in layer_data.getLayer( self._layer_view._current_layer_num).polygons: # The size indicates all values in the two-dimension array, and the second dimension is # always size 3 because we have 3D points. if index >= polygon.data.size // 3 - offset: index -= polygon.data.size // 3 - offset offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon continue # The head position is calculated and translated head_position = Vector( polygon.data[index + offset][0], polygon.data[index + offset][1], polygon.data[index + offset][2]) + node.getWorldPosition() break # Calculate the range of paths in the last layer current_layer_start = end current_layer_end = end + self._layer_view._current_path_num * 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 if self._old_current_path != self._layer_view._current_path_num: self._current_shader = self._layer_shadow_shader self._switching_layers = False if not self._layer_view.isSimulationRunning( ) and self._old_current_layer != self._layer_view._current_layer_num: self._current_shader = self._layer_shader self._switching_layers = True layers_batch = RenderBatch( self._current_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(start, end), backface_cull=True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) # Current selected layer is rendered current_layer_batch = RenderBatch( self._layer_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(current_layer_start, current_layer_end)) current_layer_batch.addItem(node.getWorldTransformation(), layer_data) current_layer_batch.render(self._scene.getActiveCamera()) self._old_current_layer = self._layer_view._current_layer_num self._old_current_path = self._layer_view._current_path_num # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # The nozzle is drawn when once we know the correct position of the head, # but the user is not using the layer slider, and the compatibility mode is not enabled if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity( ) and nozzle_node is not None: if head_position is not None: nozzle_node.setVisible(True) nozzle_node.setPosition(head_position) nozzle_batch = RenderBatch( self._nozzle_shader, type=RenderBatch.RenderType.Transparent) nozzle_batch.addItem(nozzle_node.getWorldTransformation(), mesh=nozzle_node.getMeshData()) nozzle_batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" shadow_shader_filename = "layers_shadow.shader" else: shader_filename = "layers3d.shader" shadow_shader_filename = "layers3d_shadow.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shader_filename)) self._layer_shadow_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shadow_shader_filename)) self._current_shader = self._layer_shader # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate()) self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate()) self._layer_shader.setUniformValue("u_max_thickness", self._layer_view.getMaxThickness()) self._layer_shader.setUniformValue("u_min_thickness", self._layer_view.getMinThickness()) self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getSimulationViewType()) self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities()) self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves()) self._layer_shader.setUniformValue("u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) else: #defaults self._layer_shader.setUniformValue("u_max_feedrate", 1) self._layer_shader.setUniformValue("u_min_feedrate", 0) self._layer_shader.setUniformValue("u_max_thickness", 1) self._layer_shader.setUniformValue("u_min_thickness", 0) self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) if not self._nozzle_shader: self._nozzle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) self._nozzle_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("layerview_nozzle").getRgb())) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True) active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate head_position = None # Indicates the current position of the print head nozzle_node = None for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) elif isinstance(node, NozzleNode): nozzle_node = node nozzle_node.setVisible(False) elif isinstance(node, SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): # In the current layer, we show just the indicated paths if layer == self._layer_view._current_layer_num: # We look for the position of the head, searching the point of the current path index = self._layer_view._current_path_num offset = 0 for polygon in layer_data.getLayer(layer).polygons: # The size indicates all values in the two-dimension array, and the second dimension is # always size 3 because we have 3D points. if index >= polygon.data.size // 3 - offset: index -= polygon.data.size // 3 - offset offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon continue # The head position is calculated and translated head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition() break break if self._layer_view._minimum_layer_num > layer: start += element_counts[layer] end += element_counts[layer] # Calculate the range of paths in the last layer current_layer_start = end current_layer_end = end + self._layer_view._current_path_num * 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 if self._old_current_path != self._layer_view._current_path_num: self._current_shader = self._layer_shadow_shader self._switching_layers = False if not self._layer_view.isSimulationRunning() and self._old_current_layer != self._layer_view._current_layer_num: self._current_shader = self._layer_shader self._switching_layers = True layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end), backface_cull = True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) # Current selected layer is rendered current_layer_batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (current_layer_start, current_layer_end)) current_layer_batch.addItem(node.getWorldTransformation(), layer_data) current_layer_batch.render(self._scene.getActiveCamera()) self._old_current_layer = self._layer_view._current_layer_num self._old_current_path = self._layer_view._current_path_num # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # The nozzle is drawn when once we know the correct position of the head, # but the user is not using the layer slider, and the compatibility mode is not enabled if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity() and nozzle_node is not None: if head_position is not None: nozzle_node.setVisible(True) nozzle_node.setPosition(head_position) nozzle_batch = RenderBatch(self._nozzle_shader, type = RenderBatch.RenderType.Transparent) nozzle_batch.addItem(nozzle_node.getWorldTransformation(), mesh = nozzle_node.getMeshData()) nozzle_batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" else: shader_filename = "layers3d.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), shader_filename)) # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getLayerViewType()) self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities()) self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves()) self._layer_shader.setUniformValue("u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) else: #defaults self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) elif isinstance(node, SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): if layer > self._layer_view._current_layer_num: break if self._layer_view._minimum_layer_num > layer: start += counts end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end)) batch.addItem(node.getWorldTransformation(), layer_data) batch.render(self._scene.getActiveCamera()) # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def _renderObjectsMode(self): self._selection_map = self._toolhandle_selection_map.copy() batch = RenderBatch(self._shader) tool_handle = RenderBatch(self._tool_handle_shader, type=RenderBatch.RenderType.Overlay) selectable_objects = False for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle.addItem(node.getWorldTransformation(), mesh=node.getSelectionMesh()) continue if node.isSelectable() and node.getMeshData(): selectable_objects = True batch.addItem( transformation=node.getWorldTransformation(), mesh=node.getMeshData(), uniforms={"selection_color": self._getNodeColor(node)}) self.bind() if selectable_objects: batch.render(self._scene.getActiveCamera()) self._gl.glColorMask(self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_FALSE) self._gl.glDisable(self._gl.GL_DEPTH_TEST) tool_handle.render(self._scene.getActiveCamera()) self._gl.glEnable(self._gl.GL_DEPTH_TEST) self._gl.glColorMask(self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE, self._gl.GL_TRUE) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" else: shader_filename = "layers3d.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath("LayerView"), shader_filename)) # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue( "u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue( "u_layer_view_type", self._layer_view.getLayerViewType()) self._layer_shader.setUniformValue( "u_extruder_opacity", self._layer_view.getExtruderOpacities()) self._layer_shader.setUniformValue( "u_show_travel_moves", self._layer_view.getShowTravelMoves()) self._layer_shader.setUniformValue( "u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue( "u_show_infill", self._layer_view.getShowInfill()) else: #defaults self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "toolhandle.shader")) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type=RenderBatch.RenderType.Overlay) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh=node.getSolidMesh()) elif isinstance(node, SceneNode) and (node.getMeshData( ) or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ( (not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): if layer > self._layer_view._current_layer_num: break if self._layer_view._minimum_layer_num > layer: start += element_counts[layer] end += element_counts[layer] # This uses glDrawRangeElements internally to only draw a certain range of lines. batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(start, end)) batch.addItem(node.getWorldTransformation(), layer_data) batch.render(self._scene.getActiveCamera()) # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def render(self): if not self._layer_shader: self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layers.shader")) # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) elif isinstance(node, SceneNode) and node.getMeshData() and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): if layer + self._layerview._solid_layers > self._layerview._current_layer_num: break end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end)) batch.addItem(node.getWorldTransformation(), layer_data) batch.render(self._scene.getActiveCamera()) # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid) if self._layerview._current_layer_mesh: batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh) if self._layerview._current_layer_jumps: batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "overhang.shader")) if self._shader: self._shader.setUniformValue("u_overhangAngle", 1.0) self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0]) self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0]) self._shader.setUniformValue("u_shininess", 20.0) if not self._non_printing_shader: if self._non_printing_shader: self._non_printing_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "transparent_object.shader")) self._non_printing_shader.setUniformValue( "u_diffuseColor", [0.5, 0.5, 0.5, 0.5]) self._non_printing_shader.setUniformValue("u_opacity", 0.6) if not self._support_mesh_shader: self._support_mesh_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "striped.shader")) if self._support_mesh_shader: self._support_mesh_shader.setUniformValue( "u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) self._gl.glClearColor(0.0, 0.0, 0.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create batches to be rendered batch = RenderBatch(self._shader) batch_support_mesh = RenderBatch(self._support_mesh_shader) # Fill up the batch with objects that can be sliced. for node in DepthFirstIterator( self._scene.getRoot() ): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration( "isSliceable") and node.getMeshData() and node.isVisible(): per_mesh_stack = node.callDecoration("getStack") if node.callDecoration("isNonThumbnailVisibleMesh"): # Non printing mesh continue elif per_mesh_stack is not None and per_mesh_stack.getProperty( "support_mesh", "value"): # Support mesh uniforms = {} shade_factor = 0.6 diffuse_color = node.getDiffuseColor() diffuse_color2 = [ diffuse_color[0] * shade_factor, diffuse_color[1] * shade_factor, diffuse_color[2] * shade_factor, 1.0 ] uniforms["diffuse_color"] = prettier_color(diffuse_color) uniforms["diffuse_color_2"] = diffuse_color2 batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms=uniforms) else: # Normal scene node uniforms = {} uniforms["diffuse_color"] = prettier_color( node.getDiffuseColor()) batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms=uniforms) self.bind() if self._camera is None: render_camera = Application.getInstance().getController().getScene( ).getActiveCamera() else: render_camera = self._camera batch.render(render_camera) batch_support_mesh.render(render_camera) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" shadow_shader_filename = "layers_shadow.shader" else: shader_filename = "layers3d.shader" shadow_shader_filename = "layers3d_shadow.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath( "SimulationView"), shader_filename)) self._layer_shadow_shader = OpenGL.getInstance( ).createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath( "SimulationView"), shadow_shader_filename)) self._current_shader = self._layer_shader # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue( "u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if not self._compatibility_mode: self._layer_shader.setUniformValue( "u_starts_color", Color(*Application.getInstance().getTheme().getColor( "layerview_starts").getRgb())) if self._layer_view: self._layer_shader.setUniformValue( "u_max_feedrate", self._layer_view.getMaxFeedrate()) self._layer_shader.setUniformValue( "u_min_feedrate", self._layer_view.getMinFeedrate()) self._layer_shader.setUniformValue( "u_max_thickness", self._layer_view.getMaxThickness()) self._layer_shader.setUniformValue( "u_min_thickness", self._layer_view.getMinThickness()) self._layer_shader.setUniformValue( "u_max_line_width", self._layer_view.getMaxLineWidth()) self._layer_shader.setUniformValue( "u_min_line_width", self._layer_view.getMinLineWidth()) self._layer_shader.setUniformValue( "u_max_flow_rate", self._layer_view.getMaxFlowRate()) self._layer_shader.setUniformValue( "u_min_flow_rate", self._layer_view.getMinFlowRate()) self._layer_shader.setUniformValue( "u_layer_view_type", self._layer_view.getSimulationViewType()) self._layer_shader.setUniformValue( "u_extruder_opacity", self._layer_view.getExtruderOpacities()) self._layer_shader.setUniformValue( "u_show_travel_moves", self._layer_view.getShowTravelMoves()) self._layer_shader.setUniformValue( "u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue( "u_show_infill", self._layer_view.getShowInfill()) self._layer_shader.setUniformValue( "u_show_starts", self._layer_view.getShowStarts()) else: #defaults self._layer_shader.setUniformValue("u_max_feedrate", 1) self._layer_shader.setUniformValue("u_min_feedrate", 0) self._layer_shader.setUniformValue("u_max_thickness", 1) self._layer_shader.setUniformValue("u_min_thickness", 0) self._layer_shader.setUniformValue("u_max_flow_rate", 1) self._layer_shader.setUniformValue("u_min_flow_rate", 0) self._layer_shader.setUniformValue("u_max_line_width", 1) self._layer_shader.setUniformValue("u_min_line_width", 0) self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue( "u_extruder_opacity", [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) self._layer_shader.setUniformValue("u_show_starts", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "toolhandle.shader")) if not self._nozzle_shader: self._nozzle_shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "color.shader")) self._nozzle_shader.setUniformValue( "u_color", Color(*Application.getInstance().getTheme().getColor( "layerview_nozzle").getRgb())) if not self._disabled_shader: self._disabled_shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "striped.shader")) self._disabled_shader.setUniformValue( "u_diffuseColor1", Color(*Application.getInstance().getTheme().getColor( "model_unslicable").getRgb())) self._disabled_shader.setUniformValue( "u_diffuseColor2", Color(*Application.getInstance().getTheme().getColor( "model_unslicable_alt").getRgb())) self._disabled_shader.setUniformValue("u_width", 50.0) self._disabled_shader.setUniformValue("u_opacity", 0.6) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type=RenderBatch.RenderType.Overlay, backface_cull=True) disabled_batch = RenderBatch(self._disabled_shader) head_position = None # Indicates the current position of the print head nozzle_node = None for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh=node.getSolidMesh()) elif isinstance(node, NozzleNode): nozzle_node = node nozzle_node.setVisible( False) # Don't set to true, we render it separately! elif getattr(node, "_outside_buildarea", False) and isinstance( node, SceneNode) and node.getMeshData() and node.isVisible( ) and not node.callDecoration("isNonPrintingMesh"): disabled_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData()) elif isinstance(node, SceneNode) and (node.getMeshData( ) or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ( (not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): # In the current layer, we show just the indicated paths if layer == self._layer_view._current_layer_num: # We look for the position of the head, searching the point of the current path index = self._layer_view._current_path_num offset = 0 for polygon in layer_data.getLayer(layer).polygons: # The size indicates all values in the two-dimension array, and the second dimension is # always size 3 because we have 3D points. if index >= polygon.data.size // 3 - offset: index -= polygon.data.size // 3 - offset offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon continue # The head position is calculated and translated head_position = Vector( polygon.data[index + offset][0], polygon.data[index + offset][1], polygon.data[index + offset] [2]) + node.getWorldPosition() break break if self._layer_view._minimum_layer_num > layer: start += element_counts[layer] end += element_counts[layer] # Calculate the range of paths in the last layer current_layer_start = end current_layer_end = end + self._layer_view._current_path_num * 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 if self._old_current_path != self._layer_view._current_path_num: self._current_shader = self._layer_shadow_shader self._switching_layers = False if not self._layer_view.isSimulationRunning( ) and self._old_current_layer != self._layer_view._current_layer_num: self._current_shader = self._layer_shader self._switching_layers = True # 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"] ]) # Remove the last element prev_line_types = prev_line_types[ 0:layer_data._attributes["line_types"]["value"].size] layer_data._attributes["prev_line_types"] = { 'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type' } layers_batch = RenderBatch( self._current_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(start, end), backface_cull=True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) # Current selected layer is rendered current_layer_batch = RenderBatch( self._layer_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(current_layer_start, current_layer_end)) current_layer_batch.addItem(node.getWorldTransformation(), layer_data) current_layer_batch.render(self._scene.getActiveCamera()) self._old_current_layer = self._layer_view._current_layer_num self._old_current_path = self._layer_view._current_path_num # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # The nozzle is drawn when once we know the correct position of the head, # but the user is not using the layer slider, and the compatibility mode is not enabled if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity( ) and nozzle_node is not None: if head_position is not None: nozzle_node.setPosition(head_position) nozzle_batch = RenderBatch( self._nozzle_shader, type=RenderBatch.RenderType.Transparent) nozzle_batch.addItem(nozzle_node.getWorldTransformation(), mesh=nozzle_node.getMeshData()) nozzle_batch.render(self._scene.getActiveCamera()) if len(disabled_batch.items) > 0: disabled_batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def test_compare(data): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch_1 = RenderBatch(mocked_shader, **data["item1"]) render_batch_2 = RenderBatch(mocked_shader, **data["item2"]) assert render_batch_1 < render_batch_2
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "overhang.shader")) if self._shader: self._shader.setUniformValue("u_overhangAngle", 1.0) self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0]) self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0]) self._shader.setUniformValue("u_shininess", 20.0) self._shader.setUniformValue( "u_renderError", 0.0) # We don't want any error markers!. self._shader.setUniformValue( "u_faceId", -1) # Don't render any selected faces in the preview. else: Logger.error( "Unable to compile shader program: overhang.shader") if not self._non_printing_shader: if self._non_printing_shader: self._non_printing_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "transparent_object.shader")) self._non_printing_shader.setUniformValue( "u_diffuseColor", [0.5, 0.5, 0.5, 0.5]) self._non_printing_shader.setUniformValue("u_opacity", 0.6) if not self._support_mesh_shader: self._support_mesh_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "striped.shader")) if self._support_mesh_shader: self._support_mesh_shader.setUniformValue( "u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) self._gl.glClearColor(0.0, 0.0, 0.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create batches to be rendered batch = RenderBatch(self._shader) batch_support_mesh = RenderBatch(self._support_mesh_shader) # Fill up the batch with objects that can be sliced. for node in DepthFirstIterator(self._scene.getRoot()): if hasattr(node, "_outside_buildarea") and not getattr( node, "_outside_buildarea"): if node.callDecoration("isSliceable") and node.getMeshData( ) and node.isVisible(): per_mesh_stack = node.callDecoration("getStack") if node.callDecoration("isNonThumbnailVisibleMesh"): # Non printing mesh continue elif per_mesh_stack is not None and per_mesh_stack.getProperty( "support_mesh", "value"): # Support mesh uniforms = {} shade_factor = 0.6 diffuse_color = cast(CuraSceneNode, node).getDiffuseColor() diffuse_color2 = [ diffuse_color[0] * shade_factor, diffuse_color[1] * shade_factor, diffuse_color[2] * shade_factor, 1.0 ] uniforms["diffuse_color"] = prettier_color( diffuse_color) uniforms["diffuse_color_2"] = diffuse_color2 batch_support_mesh.addItem( node.getWorldTransformation(copy=False), node.getMeshData(), uniforms=uniforms) else: # Normal scene node uniforms = {} uniforms["diffuse_color"] = prettier_color( cast(CuraSceneNode, node).getDiffuseColor()) batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), uniforms=uniforms) self.bind() if self._camera is None: render_camera = Application.getInstance().getController().getScene( ).getActiveCamera() else: render_camera = self._camera batch.render(render_camera) batch_support_mesh.render(render_camera) self.release()
def render(self): if not self._layer_shader: if self._compatibility_mode: shader_filename = "layers.shader" shadow_shader_filename = "layers_shadow.shader" else: shader_filename = "layers3d.shader" shadow_shader_filename = "layers3d_shadow.shader" self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shader_filename)) self._layer_shadow_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shadow_shader_filename)) self._current_shader = self._layer_shader # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate()) self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate()) self._layer_shader.setUniformValue("u_max_thickness", self._layer_view.getMaxThickness()) self._layer_shader.setUniformValue("u_min_thickness", self._layer_view.getMinThickness()) self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getSimulationViewType()) self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities()) self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves()) self._layer_shader.setUniformValue("u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) else: #defaults self._layer_shader.setUniformValue("u_max_feedrate", 1) self._layer_shader.setUniformValue("u_min_feedrate", 0) self._layer_shader.setUniformValue("u_max_thickness", 1) self._layer_shader.setUniformValue("u_min_thickness", 0) self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) if not self._nozzle_shader: self._nozzle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) self._nozzle_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("layerview_nozzle").getRgb())) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True) active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate head_position = None # Indicates the current position of the print head head_rotation = None#Quaternion(z=1.0) nozzle_node = None for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) elif isinstance(node, NozzleNode): nozzle_node = node nozzle_node.setVisible(False) elif isinstance(node, SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer in sorted(element_counts.keys()): # In the current layer, we show just the indicated paths if layer == self._layer_view._current_layer_num: # We look for the position of the head, searching the point of the current path index = self._layer_view._current_path_num offset = 0 for polygon in layer_data.getLayer(layer).polygons: # The size indicates all values in the two-dimension array, and the second dimension is # always size 3 because we have 3D points. if index >= polygon.data.size // 6 - offset: index -= polygon.data.size // 6 - offset offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon continue # The head position is calculated and translated head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition() if len(polygon.data[index+offset]) > 3: head_rotation = Quaternion.rotationTo(Vector(0,1,0), Vector(polygon.data[index+offset][3], polygon.data[index+offset][4], polygon.data[index+offset][5])) else: head_rotation = Quaternion(y=-1) break break if self._layer_view._minimum_layer_num > layer: start += element_counts[layer] end += element_counts[layer] # Calculate the range of paths in the last layer current_layer_start = end current_layer_end = end + self._layer_view._current_path_num * 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 if self._old_current_path != self._layer_view._current_path_num: self._current_shader = self._layer_shadow_shader self._switching_layers = False if not self._layer_view.isSimulationRunning() and self._old_current_layer != self._layer_view._current_layer_num: self._current_shader = self._layer_shader self._switching_layers = True layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end), backface_cull = True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) # Current selected layer is rendered current_layer_batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (current_layer_start, current_layer_end)) current_layer_batch.addItem(node.getWorldTransformation(), layer_data) current_layer_batch.render(self._scene.getActiveCamera()) self._old_current_layer = self._layer_view._current_layer_num self._old_current_path = self._layer_view._current_path_num # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid) if self._layer_view.getCurrentLayerMesh(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh()) if self._layer_view.getCurrentLayerJumps(): batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps()) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # The nozzle is drawn when once we know the correct position of the head, # but the user is not using the layer slider, and the compatibility mode is not enabled if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity() and nozzle_node is not None: if head_position is not None: nozzle_node.setVisible(True) if head_rotation is not None: nozzle_node.setOrientation(head_rotation, SceneNode.TransformSpace.Local) nozzle_node.setPosition(head_position) nozzle_batch = RenderBatch(self._nozzle_shader, type = RenderBatch.RenderType.Transparent) nozzle_batch.addItem(nozzle_node.getWorldTransformation(), mesh = nozzle_node.getMeshData()) nozzle_batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()
def render(self) -> None: if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader")) if self._shader: self._shader.setUniformValue("u_overhangAngle", 1.0) self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0]) self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0]) self._shader.setUniformValue("u_shininess", 20.0) if not self._non_printing_shader: if self._non_printing_shader: self._non_printing_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "transparent_object.shader")) self._non_printing_shader.setUniformValue("u_diffuseColor", [0.5, 0.5, 0.5, 0.5]) self._non_printing_shader.setUniformValue("u_opacity", 0.6) if not self._support_mesh_shader: self._support_mesh_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader")) if self._support_mesh_shader: self._support_mesh_shader.setUniformValue("u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) self._gl.glClearColor(0.0, 0.0, 0.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) # Create batches to be rendered batch = RenderBatch(self._shader) batch_support_mesh = RenderBatch(self._support_mesh_shader) # Fill up the batch with objects that can be sliced. for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible(): per_mesh_stack = node.callDecoration("getStack") if node.callDecoration("isNonThumbnailVisibleMesh"): # Non printing mesh continue elif per_mesh_stack is not None and per_mesh_stack.getProperty("support_mesh", "value"): # Support mesh uniforms = {} shade_factor = 0.6 diffuse_color = node.getDiffuseColor() diffuse_color2 = [ diffuse_color[0] * shade_factor, diffuse_color[1] * shade_factor, diffuse_color[2] * shade_factor, 1.0] uniforms["diffuse_color"] = prettier_color(diffuse_color) uniforms["diffuse_color_2"] = diffuse_color2 batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms) else: # Normal scene node uniforms = {} uniforms["diffuse_color"] = prettier_color(node.getDiffuseColor()) batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms) self.bind() if self._camera is None: render_camera = Application.getInstance().getController().getScene().getActiveCamera() else: render_camera = self._camera batch.render(render_camera) batch_support_mesh.render(render_camera) self.release()
def render(self): if not self._layer_shader: self._layer_shader = OpenGL.getInstance().createShaderProgram( os.path.join( PluginRegistry.getInstance().getPluginPath("LayerView"), "layers.shader")) # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue( "u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "toolhandle.shader")) self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type=RenderBatch.RenderType.Overlay) for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh=node.getSolidMesh()) elif isinstance(node, SceneNode) and (node.getMeshData( ) or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue # Render all layers below a certain number as line mesh instead of vertices. if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): if layer + self._layerview._solid_layers > self._layerview._current_layer_num: break end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid, mode=RenderBatch.RenderMode.Lines, range=(start, end)) batch.addItem(node.getWorldTransformation(), layer_data) batch.render(self._scene.getActiveCamera()) # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type=RenderBatch.RenderType.Solid) if self._layerview._current_layer_mesh: batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh) if self._layerview._current_layer_jumps: batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) # Render toolhandles on top of the layerview if len(tool_handle_batch.items) > 0: tool_handle_batch.render(self._scene.getActiveCamera()) self.release()