diff options
author | fieldOfView <aldo@fieldofview.com> | 2018-03-13 22:40:41 +0300 |
---|---|---|
committer | fieldOfView <aldo@fieldofview.com> | 2018-03-13 22:40:41 +0300 |
commit | a536da503bf374f5db0fec5180e9989294f77c22 (patch) | |
tree | 48fae0ad211ed0c9cef33ea08231e56df6c4d7d6 /cura/PickingPass.py | |
parent | d88724aff539748dbdb0001bacbe6785cae68ba1 (diff) |
Rename DepthPass to PickingPass
The map created by the shader is not strictly a depth map; not only is the "depth" encoded in the rgb channels, but it is also a distance to the camera instead of a "scene depth".
Diffstat (limited to 'cura/PickingPass.py')
-rw-r--r-- | cura/PickingPass.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/cura/PickingPass.py b/cura/PickingPass.py new file mode 100644 index 0000000000..4bd893e926 --- /dev/null +++ b/cura/PickingPass.py @@ -0,0 +1,70 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. +from UM.Application import Application +from UM.Math.Vector import Vector +from UM.Resources import Resources + +from UM.View.RenderPass import RenderPass +from UM.View.GL.OpenGL import OpenGL +from UM.View.RenderBatch import RenderBatch + +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator + + +## A RenderPass subclass that renders a the distance of selectable objects from the active camera to a texture. +# The texture is used to map a 2d location (eg the mouse location) to a world space position +# +# Note that in order to increase precision, the 24 bit depth value is encoded into all three of the R,G & B channels +class PickingPass(RenderPass): + def __init__(self, width: int, height: int): + super().__init__("picking", width, height) + + self._renderer = Application.getInstance().getRenderer() + + self._shader = None + self._scene = Application.getInstance().getController().getScene() + + + 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() + + ## Get the distance in mm from the camera to at a certain pixel coordinate. + def getPickedDepth(self, x, y) -> float: + output = self.getOutput() + + window_size = self._renderer.getWindowSize() + + px = (0.5 + x / 2.0) * window_size[0] + py = (0.5 + y / 2.0) * window_size[1] + + if px < 0 or px > (output.width() - 1) or py < 0 or py > (output.height() - 1): + return None + + distance = output.pixel(px, py) # distance in micron, from in r, g & b channels + distance = (distance & 0x00ffffff) / 1000. # drop the alpha channel and covert to mm + return distance + + ## Get the world coordinates of a picked point + def getPickedPosition(self, x, y) -> Vector: + distance = self.getPickedDepth(x, y) + ray = self._scene.getActiveCamera().getRay(x, y) + + return ray.getPointAlongRay(distance) |