diff --git a/plugins/XRayView/XRayPass.py b/plugins/XRayView/XRayPass.py new file mode 100644 index 0000000000..e49fcef22c --- /dev/null +++ b/plugins/XRayView/XRayPass.py @@ -0,0 +1,41 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import os.path + +from UM.Application import Application +from UM.PluginRegistry import PluginRegistry + +from UM.View.RenderPass import RenderPass +from UM.View.RenderBatch import RenderBatch +from UM.View.GL.OpenGL import OpenGL + +from UM.Scene.SceneNode import SceneNode +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator + +class XRayPass(RenderPass): + def __init__(self, width, height): + super().__init__("xray", width, height) + + self._shader = None + self._gl = OpenGL.getInstance().getBindingsObject() + self._scene = Application.getInstance().getController().getScene() + + 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) + 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) + self._gl.glEnable(self._gl.GL_BLEND) + self._gl.glBlendFunc(self._gl.GL_SRC_ALPHA, self._gl.GL_ONE) + batch.render(self._scene.getActiveCamera()) + self._gl.glEnable(self._gl.GL_DEPTH_TEST) + + self.release() diff --git a/plugins/XRayView/XRayView.py b/plugins/XRayView/XRayView.py new file mode 100644 index 0000000000..ec3174d1f5 --- /dev/null +++ b/plugins/XRayView/XRayView.py @@ -0,0 +1,57 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import os.path + +from UM.PluginRegistry import PluginRegistry +from UM.Event import Event +from UM.View.View import View +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator + +from UM.View.GL.OpenGL import OpenGL + +from . import XRayPass + +## View used to display g-code paths. +class XRayView(View): + def __init__(self): + super().__init__() + self._shader = None + + self._xray_pass = None + self._xray_composite_shader = None + self._composite_pass = None + self._old_composite_shader = None + self._old_layer_bindings = None + + def beginRendering(self): + scene = self.getController().getScene() + renderer = self.getRenderer() + + for node in DepthFirstIterator(scene.getRoot()): + node.render(renderer) + + def endRendering(self): + pass + + def event(self, event): + renderer = self.getRenderer() + if event.type == Event.ViewActivateEvent: + if not self._xray_pass: + self._xray_pass = XRayPass.XRayPass(1280, 720) + renderer.addRenderPass(self._xray_pass) + + if not self._xray_composite_shader: + self._xray_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("XRayView"), "xray_composite.shader")) + + if not self._composite_pass: + self._composite_pass = renderer.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) + + if event.type == Event.ViewDeactivateEvent: + self._composite_pass.setLayerBindings(self._old_layer_bindings) + self._composite_pass.setCompositeShader(self._old_composite_shader) diff --git a/plugins/XRayView/__init__.py b/plugins/XRayView/__init__.py new file mode 100644 index 0000000000..7d9b108f1e --- /dev/null +++ b/plugins/XRayView/__init__.py @@ -0,0 +1,24 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from . import XRayView + +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +def getMetaData(): + return { + "plugin": { + "name": catalog.i18nc("@label", "X-Ray View"), + "author": "Ultimaker", + "version": "1.0", + "description": catalog.i18nc("@info:whatsthis", "Provides the X-Ray view."), + "api": 2 + }, + "view": { + "name": catalog.i18nc("@item:inlistbox", "X-Ray") + } + } + +def register(app): + return { "view": XRayView.XRayView() } diff --git a/plugins/XRayView/xray.shader b/plugins/XRayView/xray.shader new file mode 100644 index 0000000000..b42b3e056a --- /dev/null +++ b/plugins/XRayView/xray.shader @@ -0,0 +1,27 @@ +[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_color; + + void main() + { + gl_FragColor = u_color; + } + +[defaults] +u_color = [0.02, 0.02, 0.02, 1.0] + +[bindings] +u_modelViewProjectionMatrix = model_view_projection_matrix + +[attributes] +a_vertex = vertex diff --git a/plugins/XRayView/xray_composite.shader b/plugins/XRayView/xray_composite.shader new file mode 100644 index 0000000000..118f106d7d --- /dev/null +++ b/plugins/XRayView/xray_composite.shader @@ -0,0 +1,78 @@ +[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 = + uniform sampler2D u_layer0; + uniform sampler2D u_layer1; + uniform sampler2D u_layer2; + uniform sampler2D u_layer3; + + uniform float u_imageWidth; + uniform float u_imageHeight; + + uniform vec2 u_offset[9]; + + uniform float u_outline_strength; + uniform vec4 u_outline_color; + uniform vec4 u_error_color; + + 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 = vec4(0.965, 0.965, 0.965, 1.0); + vec4 layer0 = texture2D(u_layer0, v_uvs); + + result = layer0 * layer0.a + result * (1.0 - layer0.a); + + vec4 layer2 = texture2D(u_layer2, v_uvs); + + float intersection_count = (layer2.r * 255.0) / 5.0; + if(mod(intersection_count, 2.0) == 1.0) + { + layer2 = u_error_color; + } + result = layer2 * layer2.a + result * (1.0 - layer2.a); + + 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); + } + + gl_FragColor = mix(result, vec4(abs(sum.a)) * u_outline_color, abs(sum.a)); + } + +[defaults] +u_layer0 = 0 +u_layer1 = 1 +u_layer2 = 2 +u_layer3 = 3 +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 +