예제 #1
0
    def drawAll(self, axes, zposes, xforms):
        """Calls the version-dependent ``drawAll`` function. """

        opts = self.opts
        outline = opts.outline
        owidth = float(opts.outlineWidth)
        rtex = self.renderTexture
        w, h = self.canvas.GetSize()
        lo, hi = self.canvas.getViewport()
        xax = axes[0]
        yax = axes[1]
        xmin, xmax = lo[xax], hi[xax]
        ymin, ymax = lo[yax], hi[yax]
        offsets = [owidth / w, owidth / h]

        # draw all slices to the offscreen texture
        with glroutines.disabled(gl.GL_BLEND), rtex.target(xax, yax, lo, hi):
            fslgl.gllabel_funcs.drawAll(self, axes, zposes, xforms)

        # run it through the edge filter
        self.edgeFilter.set(offsets=offsets, outline=outline)
        self.edgeFilter.apply(rtex,
                              max(zposes),
                              xmin,
                              xmax,
                              ymin,
                              ymax,
                              xax,
                              yax,
                              textureUnit=gl.GL_TEXTURE2)
예제 #2
0
    def draw2D(self, zpos, axes, xform=None, bbox=None):
        """Calls the version-dependent ``draw2D`` function, then applies
        the edge filter if necessary.
        """

        opts = self.opts

        if not opts.outline:
            fslgl.glmask_funcs.draw2D(self, zpos, axes, xform, bbox)
            return

        owidth     = float(opts.outlineWidth)
        rtex       = self.renderTexture
        w, h       = self.canvas.GetSize()
        lo, hi     = self.canvas.getViewport()
        xax        = axes[0]
        yax        = axes[1]
        xmin, xmax = lo[xax], hi[xax]
        ymin, ymax = lo[yax], hi[yax]
        offsets    = [owidth / w, owidth / h]

        # Draw the mask to the off-screen texture
        with glroutines.disabled(gl.GL_BLEND), rtex.target(xax, yax, lo, hi):
            fslgl.glmask_funcs.draw2D(self, zpos, axes, xform, bbox)

        # Run the texture through an edge detection
        # filter, drawing the result to screen
        self.edgeFilter.set(offsets=offsets, outline=1)
        self.edgeFilter.apply(
            rtex, zpos, xmin, xmax, ymin, ymax, xax, yax,
            textureUnit=gl.GL_TEXTURE1)
예제 #3
0
    def __refreshTexture(self, tex, idx):
        """Refreshes the given :class:`.RenderTexture`.

        :arg tex: The ``RenderTexture`` to refresh.
        :arg idx: Index of the ``RenderTexture``.
        """

        globj = self.__globj
        zpos  = self.__indexToZpos(idx)
        xax   = self.__xax
        yax   = self.__yax
        axes  = (self.__xax, self.__yax, self.__zax)

        if not globj.ready():
            return

        lo, hi = globj.getDisplayBounds()
        res    = globj.getDataResolution(xax, yax)

        if res is not None:
            width  = res[xax]
            height = res[yax]
        else:
            width  = self.__defaultWidth
            height = self.__defaultHeight

        if width  > self.__maxWidth:  width  = self.__maxWidth
        if height > self.__maxHeight: height = self.__maxHeight

        log.debug('Refreshing render texture for slice {} (zpos {}, '
                  'zax {}): {} x {}'.format(idx, zpos, self.__zax,
                                            width, height))

        tex.setSize(width, height)

        oldSize       = gl.glGetIntegerv(gl.GL_VIEWPORT)
        oldProjMat    = gl.glGetFloatv(  gl.GL_PROJECTION_MATRIX)
        oldMVMat      = gl.glGetFloatv(  gl.GL_MODELVIEW_MATRIX)

        tex.bindAsRenderTarget()
        glroutines.show2D(xax, yax, width, height, lo, hi)
        glroutines.clear((0, 0, 0, 0))

        with glroutines.disabled(gl.GL_BLEND):
            globj.preDraw()
            globj.draw2D(zpos, axes)
            globj.postDraw()

        tex.unbindAsRenderTarget()

        gl.glViewport(*oldSize)
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadMatrixf(oldProjMat)
        gl.glMatrixMode(gl.GL_MODELVIEW)
        gl.glLoadMatrixf(oldMVMat)

        self.__textureDirty[idx] = False
예제 #4
0
    def drawAll(self, axes, zposes, xforms):
        """Calls the version-dependent ``drawAll`` function, then applies
        the edge filter if necessary.
        """

        opts = self.opts
        rtex = self.renderTexture

        # Is taking max(z) hacky? It seems to work ok.
        zpos = max(zposes)
        owidth = opts.outlineWidth
        w, h = self.canvas.GetSize()
        lo, hi = self.canvas.getViewport()
        xax = axes[0]
        yax = axes[1]
        xmin, xmax = lo[xax], hi[xax]
        ymin, ymax = lo[yax], hi[yax]
        offsets = [owidth / w, owidth / h]

        # Draw all slices to the off-screen texture
        with glroutines.disabled(gl.GL_BLEND), rtex.bound(xax, yax, lo, hi):
            fslgl.glmask_funcs.drawAll(self, axes, zposes, xforms)

        # if no outline, draw the texture directly
        if not opts.outline:
            self.renderTexture.drawOnBounds(zpos,
                                            xmin,
                                            xmax,
                                            ymin,
                                            ymax,
                                            xax,
                                            yax,
                                            textureUnit=gl.GL_TEXTURE1)

        else:
            # Run the texture through an edge detection
            # filter, drawing the result to screen
            self.edgeFilter.set(offsets=offsets, outline=1)
            self.edgeFilter.apply(self.renderTexture,
                                  zpos,
                                  xmin,
                                  xmax,
                                  ymin,
                                  ymax,
                                  xax,
                                  yax,
                                  textureUnit=gl.GL_TEXTURE1)
예제 #5
0
def draw3D(self, xform=None, bbox=None):
    """Draws the image in 3D on the canvas.

    :arg self:    The :class:`.GLVolume` object which is managing the image
                  to be drawn.

    :arg xform:   A 4*4 transformation matrix to be applied to the vertex
                  data.

    :arg bbox:    An optional bounding box.
    """
    opts = self.opts
    canvas = self.canvas
    display = self.display
    shader = self.shader
    shape = self.image.shape
    proj = canvas.projectionMatrix
    src = self.renderTexture1
    dest = self.renderTexture2
    w, h = src.shape

    vertices, voxCoords, texCoords = self.generateVertices3D(bbox)
    rayStep, texform = opts.calculateRayCastSettings(xform, proj)

    rayStep = affine.transformNormal(rayStep,
                                     self.imageTexture.texCoordXform(shape))
    texform = affine.concat(texform, self.imageTexture.invTexCoordXform(shape))

    if xform is not None:
        vertices = affine.transform(vertices, xform)

    vertices = np.array(vertices, dtype=np.float32).ravel('C')

    outerLoop = opts.getNumOuterSteps()
    screenSize = [1.0 / w, 1.0 / h, 0, 0]
    rayStep = list(rayStep) + [0]
    texform = texform[2, :]
    settings = [(1 - opts.blendFactor)**2, 0, 0, display.alpha / 100.0]

    gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices)

    shader.setAtt('texCoord', texCoords)
    shader.setFragParam('rayStep', rayStep)
    shader.setFragParam('screenSize', screenSize)
    shader.setFragParam('tex2ScreenXform', texform)

    # Disable blending - we want each
    # loop to replace the contents of
    # the texture, not blend into it!
    with glroutines.enabled((gl.GL_VERTEX_ARRAY)), \
         glroutines.disabled((gl.GL_BLEND)):

        for i in range(outerLoop):

            settings = list(settings)
            dtex = src.depthTexture
            settings[1] = i * opts.numInnerSteps

            if i == outerLoop - 1: settings[2] = 1
            else: settings[2] = -1

            shader.setFragParam('settings', settings)

            dest.bindAsRenderTarget()
            src.bindTexture(gl.GL_TEXTURE5)
            dtex.bindTexture(gl.GL_TEXTURE6)

            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
            gl.glDrawArrays(gl.GL_TRIANGLES, 0, 36)

            src.unbindTexture()
            dtex.unbindTexture()
            dest.unbindAsRenderTarget()

            dest, src = src, dest

    shader.unloadAtts()
    shader.unload()

    self.renderTexture1 = src
    self.renderTexture2 = dest
예제 #6
0
    def drawCrossSection(self, zpos, axes, lo, hi, dest):
        """Renders a filled cross-section of the mesh to an off-screen
        :class:`.RenderTexture`. See:

        http://glbook.gamedev.net/GLBOOK/glbook.gamedev.net/moglgp/advclip.html

        :arg zpos: Position along the z axis
        :arg axes: Tuple containing ``(x, y, z)`` axis indices.
        :arg lo:   Tuple containing the low bounds on each axis.
        :arg hi:   Tuple containing the high bounds on each axis.
        :arg dest: The :class:`.RenderTexture` to render to.
        """

        opts = self.opts
        xax = axes[0]
        yax = axes[1]
        zax = axes[2]
        xmin = lo[xax]
        ymin = lo[yax]
        xmax = hi[xax]
        ymax = hi[yax]
        vertices = self.vertices.ravel('C')
        indices = self.indices

        dest.bindAsRenderTarget()
        dest.setRenderViewport(xax, yax, lo, hi)

        # Figure out the equation of a plane
        # perpendicular to the Z axis, and
        # located at the z position. This is
        # used as a clipping plane to draw
        # the mesh intersection.
        clipPlaneVerts = np.zeros((4, 3), dtype=np.float32)
        clipPlaneVerts[0, [xax, yax]] = [xmin, ymin]
        clipPlaneVerts[1, [xax, yax]] = [xmin, ymax]
        clipPlaneVerts[2, [xax, yax]] = [xmax, ymax]
        clipPlaneVerts[3, [xax, yax]] = [xmax, ymin]
        clipPlaneVerts[:, zax] = zpos

        planeEq = glroutines.planeEquation(clipPlaneVerts[0, :],
                                           clipPlaneVerts[1, :],
                                           clipPlaneVerts[2, :])

        gl.glClearColor(0, 0, 0, 0)

        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT
                   | gl.GL_STENCIL_BUFFER_BIT)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnable(gl.GL_CLIP_PLANE0)
        gl.glEnable(gl.GL_CULL_FACE)
        gl.glEnable(gl.GL_STENCIL_TEST)
        gl.glFrontFace(gl.GL_CCW)
        gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL)

        gl.glClipPlane(gl.GL_CLIP_PLANE0, planeEq)
        gl.glColorMask(gl.GL_FALSE, gl.GL_FALSE, gl.GL_FALSE, gl.GL_FALSE)

        # First and second passes - render front and
        # back faces separately. In the stencil buffer,
        # subtract the mask created by the second
        # render from the mask created by the first -
        # this gives us a mask which shows the
        # intersection of the mesh with the clipping
        # plane.
        gl.glStencilFunc(gl.GL_ALWAYS, 0, 0)
        direction = [gl.GL_INCR, gl.GL_DECR]

        # If the mesh coordinate transformation
        # has a negative determinant, it means
        # the back faces will be facing the camera,
        # so we need to render the back faces first.
        if npla.det(opts.getCoordSpaceTransform()) > 0:
            faceOrder = [gl.GL_FRONT, gl.GL_BACK]
        else:
            faceOrder = [gl.GL_BACK, gl.GL_FRONT]

        for face, direction in zip(faceOrder, direction):

            gl.glStencilOp(gl.GL_KEEP, gl.GL_KEEP, direction)
            gl.glCullFace(face)

            gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices)
            gl.glDrawElements(gl.GL_TRIANGLES, len(indices),
                              gl.GL_UNSIGNED_INT, indices)

        # Third pass - render the intersection
        # of the front and back faces from the
        # stencil buffer to the render texture.
        gl.glColorMask(gl.GL_TRUE, gl.GL_TRUE, gl.GL_TRUE, gl.GL_TRUE)

        gl.glDisable(gl.GL_CLIP_PLANE0)
        gl.glDisable(gl.GL_CULL_FACE)
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

        gl.glStencilFunc(gl.GL_NOTEQUAL, 0, 255)

        gl.glColor(*opts.getConstantColour())

        # Disable alpha blending - we
        # just want the colour copied
        # into the texture as-is.
        with glroutines.disabled(gl.GL_BLEND):
            gl.glBegin(gl.GL_QUADS)
            gl.glVertex3f(*clipPlaneVerts[0, :])
            gl.glVertex3f(*clipPlaneVerts[1, :])
            gl.glVertex3f(*clipPlaneVerts[2, :])
            gl.glVertex3f(*clipPlaneVerts[3, :])
            gl.glEnd()

        gl.glDisable(gl.GL_STENCIL_TEST)

        dest.unbindAsRenderTarget()
        dest.restoreViewport()