Skip to content
Snippets Groups Projects
Commit 41f60956 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Discovered that my GLObject destroy methods were never being

called. Fixed. GL21/glvolume no longer using PyOpenGL.vbo module, as it
is rubbish.
parent afbb6181
No related branches found
No related tags found
No related merge requests found
...@@ -30,9 +30,9 @@ This PDF is quite useful: ...@@ -30,9 +30,9 @@ This PDF is quite useful:
""" """
import logging import logging
log = logging.getLogger(__name__)
import OpenGL.GL as gl import OpenGL.GL as gl
import OpenGL.raw.GL._types as gltypes
import OpenGL.GL.ARB.fragment_program as arbfp import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp import OpenGL.GL.ARB.vertex_program as arbvp
...@@ -40,6 +40,9 @@ import fsl.utils.transform as transform ...@@ -40,6 +40,9 @@ import fsl.utils.transform as transform
import fsl.fslview.gl.shaders as shaders import fsl.fslview.gl.shaders as shaders
log = logging.getLogger(__name__)
def init(glvol, xax, yax): def init(glvol, xax, yax):
"""Compiles the vertex and fragment programs used for rendering.""" """Compiles the vertex and fragment programs used for rendering."""
...@@ -55,8 +58,9 @@ def init(glvol, xax, yax): ...@@ -55,8 +58,9 @@ def init(glvol, xax, yax):
def destroy(glvol): def destroy(glvol):
"""Deletes handles to the vertex/fragment programs.""" """Deletes handles to the vertex/fragment programs."""
arbvp.glDeleteProgramsARB(glvol.vertexProgram)
arbfp.glDeleteProgramsARB(glvol.fragmentProgram) arbvp.glDeleteProgramsARB(1, gltypes.GLuint(glvol.vertexProgram))
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(glvol.fragmentProgram))
def genVertexData(glvol): def genVertexData(glvol):
...@@ -213,10 +217,12 @@ def postDraw(glvol): ...@@ -213,10 +217,12 @@ def postDraw(glvol):
gl.glMatrixMode(gl.GL_TEXTURE) gl.glMatrixMode(gl.GL_TEXTURE)
gl.glActiveTexture(gl.GL_TEXTURE0) gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glBindTexture(gl.GL_TEXTURE_3D, 0)
gl.glPopMatrix() gl.glPopMatrix()
gl.glMatrixMode(gl.GL_TEXTURE) gl.glMatrixMode(gl.GL_TEXTURE)
gl.glActiveTexture(gl.GL_TEXTURE1) gl.glActiveTexture(gl.GL_TEXTURE1)
gl.glBindTexture(gl.GL_TEXTURE_1D, 0)
gl.glPopMatrix() gl.glPopMatrix()
gl.glDisable(gl.GL_TEXTURE_1D) gl.glDisable(gl.GL_TEXTURE_1D)
......
...@@ -26,9 +26,9 @@ This module provides the following functions: ...@@ -26,9 +26,9 @@ This module provides the following functions:
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
import numpy as np import numpy as np
import OpenGL.GL as gl import OpenGL.GL as gl
import OpenGL.arrays.vbo as vbo import OpenGL.raw.GL._types as gltypes
import fsl.fslview.gl.shaders as shaders import fsl.fslview.gl.shaders as shaders
import fsl.utils.transform as transform import fsl.utils.transform as transform
...@@ -66,10 +66,10 @@ def _compileShaders(glvol): ...@@ -66,10 +66,10 @@ def _compileShaders(glvol):
'colourTexture') 'colourTexture')
glvol.useSplinePos = gl.glGetUniformLocation(glvol.shaders, glvol.useSplinePos = gl.glGetUniformLocation(glvol.shaders,
'useSpline') 'useSpline')
glvol.displayToVoxMatPos = gl.glGetUniformLocation(glvol.shaders, glvol.displayToVoxMatPos = gl.glGetUniformLocation(glvol.shaders,
'displayToVoxMat') 'displayToVoxMat')
glvol.voxValXformPos = gl.glGetUniformLocation(glvol.shaders, glvol.voxValXformPos = gl.glGetUniformLocation(glvol.shaders,
'voxValXform') 'voxValXform')
def init(glvol, xax, yax): def init(glvol, xax, yax):
...@@ -77,11 +77,16 @@ def init(glvol, xax, yax): ...@@ -77,11 +77,16 @@ def init(glvol, xax, yax):
""" """
_compileShaders(glvol) _compileShaders(glvol)
glvol.worldCoordBuffer = gl.glGenBuffers(1)
glvol.indexBuffer = gl.glGenBuffers(1)
def destroy(glvol): def destroy(glvol):
"""Cleans up VBO handles.""" """Cleans up VBO handles."""
glvol.worldCoords.delete()
glvol.indices .delete() gl.glDeleteBuffers(1, gltypes.GLuint(glvol.worldCoordBuffer))
gl.glDeleteBuffers(1, gltypes.GLuint(glvol.indexBuffer))
gl.glDeleteProgram(glvol.shaders)
def genVertexData(glvol): def genVertexData(glvol):
...@@ -92,13 +97,26 @@ def genVertexData(glvol): ...@@ -92,13 +97,26 @@ def genVertexData(glvol):
xax = glvol.xax xax = glvol.xax
yax = glvol.yax yax = glvol.yax
worldCoordBuffer = glvol.worldCoordBuffer
indexBuffer = glvol.indexBuffer
worldCoords, indices = glvol.genVertexData() worldCoords, indices = glvol.genVertexData()
worldCoords = worldCoords[:, [xax, yax]] worldCoords = worldCoords[:, [xax, yax]]
worldCoordBuffer = vbo.VBO(worldCoords.ravel('C'), gl.GL_STATIC_DRAW) worldCoords = worldCoords.ravel('C')
indexBuffer = vbo.VBO(indices .ravel('C'), gl.GL_STATIC_DRAW, indices = indices .ravel('C')
gl.GL_ELEMENT_ARRAY_BUFFER)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, worldCoordBuffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER,
worldCoords.nbytes,
worldCoords,
gl.GL_STATIC_DRAW)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
indices.nbytes,
indices,
gl.GL_STATIC_DRAW)
return worldCoordBuffer, indexBuffer, len(indices) return worldCoordBuffer, indexBuffer, len(indices)
...@@ -155,7 +173,7 @@ def preDraw(glvol): ...@@ -155,7 +173,7 @@ def preDraw(glvol):
gl.glUniform1i(glvol.imageTexturePos, 1) gl.glUniform1i(glvol.imageTexturePos, 1)
# Bind the world x/y coordinate buffer # Bind the world x/y coordinate buffer
glvol.worldCoords.bind() gl.glBindBuffer(gl.GL_ARRAY_BUFFER, glvol.worldCoords)
gl.glVertexAttribPointer( gl.glVertexAttribPointer(
glvol.worldCoordPos, glvol.worldCoordPos,
2, 2,
...@@ -166,7 +184,7 @@ def preDraw(glvol): ...@@ -166,7 +184,7 @@ def preDraw(glvol):
gl.glEnableVertexAttribArray(glvol.worldCoordPos) gl.glEnableVertexAttribArray(glvol.worldCoordPos)
# Bind the vertex index buffer # Bind the vertex index buffer
glvol.indices.bind() gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, glvol.indices)
def draw(glvol, zpos, xform=None): def draw(glvol, zpos, xform=None):
...@@ -214,7 +232,7 @@ def postDraw(glvol): ...@@ -214,7 +232,7 @@ def postDraw(glvol):
gl.glDisable(gl.GL_TEXTURE_1D) gl.glDisable(gl.GL_TEXTURE_1D)
gl.glDisable(gl.GL_TEXTURE_3D) gl.glDisable(gl.GL_TEXTURE_3D)
glvol.indices .unbind() gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
glvol.worldCoords.unbind() gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0)
gl.glUseProgram(0) gl.glUseProgram(0)
...@@ -51,6 +51,7 @@ import numpy as np ...@@ -51,6 +51,7 @@ import numpy as np
import fsl.fslview.gl as fslgl import fsl.fslview.gl as fslgl
import fsl.fslview.gl.globject as globject import fsl.fslview.gl.globject as globject
import fsl.utils.transform as transform
class GLVolume(globject.GLObject): class GLVolume(globject.GLObject):
...@@ -85,13 +86,13 @@ class GLVolume(globject.GLObject): ...@@ -85,13 +86,13 @@ class GLVolume(globject.GLObject):
# Only one 'GLVolumeDirty' listener, for all GLVolume # Only one 'GLVolumeDirty' listener, for all GLVolume
# instances, is registered on ecah image/display, # instances, is registered on ecah image/display,
# so the GLVolumeDirty attribute is only set once. # so the GLVolumeDirty attribute is only set once.
try: display.addListener('interpolation', name, markImage) try: display.addListener('interpolation', name, markImage)
except: pass except: pass
try: display.addListener('volume', name, markImage) try: display.addListener('volume', name, markImage)
except: pass except: pass
try: display.addListener('resolution', name, markImage) try: display.addListener('resolution', name, markImage)
except: pass except: pass
try: image .addListener('data', name, markImage) try: image .addListener('data', name, markImage)
except: pass except: pass
...@@ -183,7 +184,7 @@ class GLVolume(globject.GLObject): ...@@ -183,7 +184,7 @@ class GLVolume(globject.GLObject):
deleting texture handles). deleting texture handles).
""" """
log.debug('Deleting GL texture: {}'.format(self.colourTexture)) log.debug('Deleting GL texture: {}'.format(self.colourTexture))
gl.glDeleteTextures(1, self.colourTexture) gl.glDeleteTextures(self.colourTexture)
# Another GLVolume object may have # Another GLVolume object may have
# already deleted the image texture # already deleted the image texture
...@@ -191,13 +192,12 @@ class GLVolume(globject.GLObject): ...@@ -191,13 +192,12 @@ class GLVolume(globject.GLObject):
imageTexture = self.image.delAttribute( imageTexture = self.image.delAttribute(
'{}Texture'.format(type(self).__name__)) '{}Texture'.format(type(self).__name__))
log.debug('Deleting GL texture: {}'.format(imageTexture)) log.debug('Deleting GL texture: {}'.format(imageTexture))
gl.glDeleteTextures(1, imageTexture) gl.glDeleteTextures(imageTexture)
except KeyError: except KeyError:
pass pass
self.removeDisplayListeners() self.removeDisplayListeners()
fslgl.glvolume_funcs.destroy(self) fslgl.glvolume_funcs.destroy(self)
...@@ -303,9 +303,7 @@ class GLVolume(globject.GLObject): ...@@ -303,9 +303,7 @@ class GLVolume(globject.GLObject):
elif dtype == np.int16: scale = 65535 elif dtype == np.int16: scale = 65535
else: scale = dmax - dmin else: scale = dmax - dmin
voxValXform = np.eye(4, dtype=np.float32) voxValXform = transform.scaleOffsetXform(scale, offset)
voxValXform[0, 0] = scale
voxValXform[3, 0] = offset
return data, texIntFmt, texExtFmt, voxValXform return data, texIntFmt, texExtFmt, voxValXform
......
...@@ -24,9 +24,7 @@ import logging ...@@ -24,9 +24,7 @@ import logging
import os.path as op import os.path as op
import fsl.fslview.gl as fslgl import fsl.fslview.gl as fslgl
import fsl.fslview.gl.glvolume as glvolume
import fsl.fslview.gl.gltensor as gltensor
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -173,6 +171,9 @@ def _getFileName(globj, shaderType): ...@@ -173,6 +171,9 @@ def _getFileName(globj, shaderType):
# callers can request a specific # callers can request a specific
# shader by passing the name, rather # shader by passing the name, rather
# than passing a GLObject instance # than passing a GLObject instance
import fsl.fslview.gl.glvolume as glvolume
import fsl.fslview.gl.gltensor as gltensor
if isinstance(globj, str): prefix = globj if isinstance(globj, str): prefix = globj
elif isinstance(globj, glvolume.GLVolume): prefix = 'glvolume' elif isinstance(globj, glvolume.GLVolume): prefix = 'glvolume'
elif isinstance(globj, gltensor.GLTensor): prefix = 'gltensor' elif isinstance(globj, gltensor.GLTensor): prefix = 'gltensor'
......
...@@ -384,6 +384,19 @@ class SliceCanvas(props.HasProperties): ...@@ -384,6 +384,19 @@ class SliceCanvas(props.HasProperties):
valid=None, valid=None,
name=None, name=None,
disp=display): disp=display):
log.debug('GLObject representation for {} '
'changed to {}'.format(display.name,
display.imageType))
# Tell the previous GLObject (if
# any) to clean up after itself
try:
globj = image.getAttribute(self.name)
globj.destroy()
except KeyError:
pass
globj = globject.createGLObject(image, disp) globj = globject.createGLObject(image, disp)
opts = display.getDisplayOpts() opts = display.getDisplayOpts()
......
...@@ -23,6 +23,33 @@ def concat(x1, x2): ...@@ -23,6 +23,33 @@ def concat(x1, x2):
return np.dot(x1, x2) return np.dot(x1, x2)
def scaleOffsetXform(scales, offsets):
"""Creates and returns an affine transformation matrix which encodes
the specified scale(s) and offset(s).
"""
if not isinstance(scales, collections.Sequence): scales = [scales]
if not isinstance(offsets, collections.Sequence): offsets = [offsets]
lens = len(scales)
leno = len(offsets)
if lens < 3: scales = scales + [1] * (3 - lens)
if leno < 3: offsets = offsets + [0] * (3 - leno)
xform = np.eye(4, dtype=np.float32)
xform[0, 0] = scales[0]
xform[1, 1] = scales[1]
xform[2, 2] = scales[2]
xform[3, 0] = offsets[0]
xform[3, 1] = offsets[0]
xform[3, 2] = offsets[0]
return xform
def axisBounds(shape, xform, axes=None): def axisBounds(shape, xform, axes=None):
"""Returns the (lo, hi) bounds of the specified axis/axes.""" """Returns the (lo, hi) bounds of the specified axis/axes."""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment