diff options
author | Tim Kuipers <t.kuipers@ultimaker.com> | 2019-10-21 18:34:23 +0300 |
---|---|---|
committer | Tim Kuipers <t.kuipers@ultimaker.com> | 2020-02-27 18:41:13 +0300 |
commit | fc4c66b62a7173d1260e40c121bc6133fbca6a88 (patch) | |
tree | 5b34b01c2e51fb1412e919d1c89c2add12a9ddb6 /plugins/SolidView | |
parent | b3761c454bba281517f1cd21d3fa4d669c7e39ba (diff) |
show xray errors in solid view
Diffstat (limited to 'plugins/SolidView')
-rw-r--r-- | plugins/SolidView/SolidView.py | 74 | ||||
-rw-r--r-- | plugins/SolidView/xray_composite.shader | 166 | ||||
-rwxr-xr-x | plugins/SolidView/xray_overlay.shader | 50 |
3 files changed, 289 insertions, 1 deletions
diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 4f15bafedb..565a704b0a 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -1,17 +1,29 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import os.path from UM.View.View import View from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.Resources import Resources +from PyQt5.QtGui import QOpenGLContext + from UM.Application import Application -from UM.View.RenderBatch import RenderBatch +from UM.Logger import Logger from UM.Math.Color import Color +from UM.PluginRegistry import PluginRegistry +from UM.Platform import Platform +from UM.Event import Event + +from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL +from cura.CuraApplication import CuraApplication + from cura.Settings.ExtruderManager import ExtruderManager +from cura import XRayPass + import math ## Standard view for mesh models. @@ -27,12 +39,20 @@ class SolidView(View): self._non_printing_shader = None self._support_mesh_shader = None + self._xray_shader = None + self._xray_pass = None + self._xray_composite_shader = None + self._composite_pass = None + self._extruders_model = None self._theme = None self._support_angle = 90 self._global_stack = None + self._old_composite_shader = None + self._old_layer_bindings = None + Application.getInstance().engineCreatedSignal.connect(self._onGlobalContainerChanged) def _onGlobalContainerChanged(self) -> None: @@ -98,6 +118,32 @@ class SolidView(View): self._checkSetup() + if not self._xray_shader: + self._xray_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "xray.shader")) + self._xray_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("xray").getRgb())) + + if not self._xray_composite_shader: + self._xray_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SolidView"), "xray_composite.shader")) + theme = Application.getInstance().getTheme() + self._xray_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb())) + self._xray_composite_shader.setUniformValue("u_error_color", Color(*theme.getColor("xray_error").getRgb())) + self._xray_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) + + if not self.getRenderer().getRenderPass("xray"): + # Currently the RenderPass constructor requires a size > 0 + # This should be fixed in RenderPass's constructor. + self._xray_pass = XRayPass.XRayPass(1, 1) + + self.getRenderer().addRenderPass(self._xray_pass) + + if not self._composite_pass: + self._composite_pass = self.getRenderer().getRenderPass("composite") + + self._old_layer_bindings = self._composite_pass.getLayerBindings() + self._composite_pass.setLayerBindings(["default", "selection", "xray"]) + self._old_composite_shader = self._composite_pass.getCompositeShader() + self._composite_pass.setCompositeShader(self._xray_composite_shader) + global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: if Application.getInstance().getPreferences().getValue("view/show_overhang"): @@ -174,5 +220,31 @@ class SolidView(View): if node.callDecoration("isGroup") and Selection.isSelected(node): renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = RenderBatch.RenderMode.LineLoop) + def endRendering(self): pass + + def event(self, event): + if event.type == Event.ViewActivateEvent: + # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching. + # This can happen when you do the following steps: + # 1. Start Cura + # 2. Load a model + # 3. Switch to Custom mode + # 4. Select the model and click on the per-object tool icon + # 5. Switch view to Layer view or X-Ray + # 6. Cura will very likely crash + # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why. + # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL + # context is None. + if Platform.isOSX(): + if QOpenGLContext.currentContext() is None: + Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later") + CuraApplication.getInstance().callLater(lambda e = event: self.event(e)) + return + + + if event.type == Event.ViewDeactivateEvent: + self.getRenderer().removeRenderPass(self._xray_pass) + self._composite_pass.setLayerBindings(self._old_layer_bindings) + self._composite_pass.setCompositeShader(self._old_composite_shader) diff --git a/plugins/SolidView/xray_composite.shader b/plugins/SolidView/xray_composite.shader new file mode 100644 index 0000000000..e3ac2162a7 --- /dev/null +++ b/plugins/SolidView/xray_composite.shader @@ -0,0 +1,166 @@ +[shaders] +vertex = + uniform highp mat4 u_modelViewProjectionMatrix; + attribute highp vec4 a_vertex; + attribute highp vec2 a_uvs; + + varying highp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment = + #ifdef GL_ES + #ifdef GL_FRAGMENT_PRECISION_HIGH + precision highp float; + #else + precision mediump float; + #endif // GL_FRAGMENT_PRECISION_HIGH + #endif // GL_ES + uniform sampler2D u_layer0; //Default pass. + uniform sampler2D u_layer1; //Selection pass. + uniform sampler2D u_layer2; //X-ray pass. + + uniform vec2 u_offset[9]; + + uniform float u_outline_strength; + uniform vec4 u_outline_color; + uniform vec4 u_error_color; + uniform vec4 u_background_color; + + const vec3 x_axis = vec3(1.0, 0.0, 0.0); + const vec3 y_axis = vec3(0.0, 1.0, 0.0); + const vec3 z_axis = vec3(0.0, 0.0, 1.0); + + varying vec2 v_uvs; + + float kernel[9]; + + void main() + { + kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; + kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; + kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; + + vec4 result = u_background_color; + vec4 layer0 = texture2D(u_layer0, v_uvs); + + result = layer0 * layer0.a + result * (1.0 - layer0.a); + + float intersection_count = (texture2D(u_layer2, v_uvs).r * 255.0) / 5.0; + if(mod(intersection_count, 2.0) >= 1.0) + { + result = u_error_color; + } + + vec4 sum = vec4(0.0); + for (int i = 0; i < 9; i++) + { + vec4 color = vec4(texture2D(u_layer1, v_uvs.xy + u_offset[i]).a); + sum += color * (kernel[i] / u_outline_strength); + } + + vec4 layer1 = texture2D(u_layer1, v_uvs); + if((layer1.rgb == x_axis || layer1.rgb == y_axis || layer1.rgb == z_axis)) + { + gl_FragColor = result; + } + else + { + gl_FragColor = mix(result, u_outline_color, abs(sum.a)); + } + + gl_FragColor.a = gl_FragColor.a > 0.5 ? 1.0 : 0.0; + } + +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + in highp vec4 a_vertex; + in highp vec2 a_uvs; + + out highp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform sampler2D u_layer0; //Default pass. + uniform sampler2D u_layer1; //Selection pass. + uniform sampler2D u_layer2; //X-ray pass. + + uniform vec2 u_offset[9]; + + uniform float u_outline_strength; + uniform vec4 u_outline_color; + uniform vec4 u_error_color; + uniform vec4 u_background_color; + + const vec3 x_axis = vec3(1.0, 0.0, 0.0); + const vec3 y_axis = vec3(0.0, 1.0, 0.0); + const vec3 z_axis = vec3(0.0, 0.0, 1.0); + + in vec2 v_uvs; + out vec4 frag_color; + + float kernel[9]; + + void main() + { + kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; + kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; + kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; + + vec4 result = u_background_color; + vec4 layer0 = texture(u_layer0, v_uvs); + + result = layer0 * layer0.a + result * (1.0 - layer0.a); + + float intersection_count = (texture(u_layer2, v_uvs).r * 255.0) / 5.0; + if(mod(intersection_count, 2.0) >= 1.0) + { + result = u_error_color; + } + + vec4 sum = vec4(0.0); + for (int i = 0; i < 9; i++) + { + vec4 color = vec4(texture(u_layer1, v_uvs.xy + u_offset[i]).a); + sum += color * (kernel[i] / u_outline_strength); + } + + vec4 layer1 = texture(u_layer1, v_uvs); + if((layer1.rgb == x_axis || layer1.rgb == y_axis || layer1.rgb == z_axis)) + { + frag_color = result; + } + else + { + frag_color = mix(result, u_outline_color, abs(sum.a)); + } + + frag_color.a = frag_color.a > 0.5 ? 1.0 : 0.0; + } + +[defaults] +u_layer0 = 0 +u_layer1 = 1 +u_layer2 = 2 +u_background_color = [0.965, 0.965, 0.965, 1.0] +u_outline_strength = 1.0 +u_outline_color = [0.05, 0.66, 0.89, 1.0] +u_error_color = [1.0, 0.0, 0.0, 1.0] + +[bindings] + +[attributes] +a_vertex = vertex +a_uvs = uv + diff --git a/plugins/SolidView/xray_overlay.shader b/plugins/SolidView/xray_overlay.shader new file mode 100755 index 0000000000..ba032b2123 --- /dev/null +++ b/plugins/SolidView/xray_overlay.shader @@ -0,0 +1,50 @@ +[shaders] +vertex = + uniform highp mat4 u_modelViewProjectionMatrix; + + attribute highp vec4 a_vertex; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + } + +fragment = + uniform lowp vec4 u_xray_error; + + void main() + { + gl_FragColor = u_xray_error; + } + +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + + in highp vec4 a_vertex; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + } + +fragment41core = + #version 410 + uniform lowp vec4 u_xray_error; + + out vec4 frag_color; + + void main() + { + + frag_color = u_xray_error; + } + +[defaults] +u_xray_error = [1.0, 1.0, 1.0, 1.0] + +[bindings] +u_modelViewProjectionMatrix = model_view_projection_matrix + +[attributes] +a_vertex = vertex |