From 8e25797c824d5e1ebeb4ee5b9ad7b589ee4dfa7a Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Thu, 20 Aug 2015 16:21:30 +0100 Subject: [PATCH] Horrible hacks so that line vectors are correctly offset - I broke them with my changes to id/pixdim origin (voxel origin in id/pixdim display is corner, whereas it is centre in affine display). --- fsl/fsleyes/gl/gl14/gllinevector_funcs.py | 5 +++++ fsl/fsleyes/gl/gl14/gllinevector_vert.prog | 7 ++++++- fsl/fsleyes/gl/gl21/gllinevector_funcs.py | 21 ++++++++++++++++----- fsl/fsleyes/gl/gl21/gllinevector_vert.glsl | 4 +++- fsl/fsleyes/gl/gllinevector.py | 3 +++ fsl/fsleyes/gl/routines.py | 6 +++--- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/fsl/fsleyes/gl/gl14/gllinevector_funcs.py b/fsl/fsleyes/gl/gl14/gllinevector_funcs.py index d786be442..da3229af7 100644 --- a/fsl/fsleyes/gl/gl14/gllinevector_funcs.py +++ b/fsl/fsleyes/gl/gl14/gllinevector_funcs.py @@ -40,6 +40,7 @@ def init(self): def vertexUpdate(*a): updateVertices(self) + updateShaderState(self) self.onUpdate() name = '{}_vertices'.format(self.name) @@ -122,8 +123,12 @@ def updateShaderState(self): invShape = 1.0 / shape modThreshold = [opts.modThreshold / 100.0, 0.0, 0.0, 0.0] + if opts.transform in ('id', 'pixdim'): offset = [0.0, 0.0, 0.0, 0.0] + else: offset = [0.5, 0.5, 0.5, 0.0] + # Vertex program inputs shaders.setVertexProgramVector( 0, invShape) + shaders.setVertexProgramVector( 1, offset) # Fragment program inputs shaders.setFragmentProgramMatrix(0, voxValXform) diff --git a/fsl/fsleyes/gl/gl14/gllinevector_vert.prog b/fsl/fsleyes/gl/gl14/gllinevector_vert.prog index 88cf87556..bbcb7e5c1 100644 --- a/fsl/fsleyes/gl/gl14/gllinevector_vert.prog +++ b/fsl/fsleyes/gl/gl14/gllinevector_vert.prog @@ -7,6 +7,10 @@ # vertex.position - Vertex position in the voxel coordinate system. # # program.local[0] - (first three components) inverse of image shape +# program.local[1] - (first three components) Offset to apply to transformed +# voxel coordinates before flooring to integers (this +# should be 0 in id/pixdim display mode, and 0.5 in +# affine display mode). # # Outputs: # result.position - the vertex position @@ -17,6 +21,7 @@ TEMP texCoord; PARAM invImageShape = program.local[0]; +PARAM voxelOffsets = program.local[1]; # Transform the vertex position (which is in voxel # coordinates) into display coordinates. It is @@ -30,7 +35,7 @@ DP4 result.position.w, state.matrix.mvp.row[3], vertex.position; # Transform the vertex coordinates # into integer voxel coordinates MOV texCoord, vertex.position; -ADD texCoord, texCoord, { 0.5, 0.5, 0.5, 0.0 }; +ADD texCoord, texCoord, voxelOffsets; FLR texCoord, texCoord; MOV result.texcoord[1], texCoord; diff --git a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py index 14734bb8a..76094c499 100644 --- a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py +++ b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py @@ -114,7 +114,9 @@ def compileShaders(self): self.voxToDisplayMatPos = gl.glGetUniformLocation(self.shaders, 'voxToDisplayMat') self.displayToVoxMatPos = gl.glGetUniformLocation(self.shaders, - 'displayToVoxMat') + 'displayToVoxMat') + self.voxelOffsetPos = gl.glGetUniformLocation(self.shaders, + 'voxelOffset') self.cmapXformPos = gl.glGetUniformLocation(self.shaders, 'cmapXform') @@ -160,13 +162,18 @@ def updateShaderState(self): d2vMat = opts.getTransform('display', 'voxel') v2dMat = opts.getTransform('voxel', 'display') + if opts.transform in ('id', 'pixdim'): offset = [0, 0, 0] + else: offset = [0.5, 0.5, 0.5] + + offset = np.array(offset, dtype=np.float32) imageDims = np.array(imageDims, dtype=np.float32) d2vMat = np.array(d2vMat, dtype=np.float32).ravel('C') v2dMat = np.array(v2dMat, dtype=np.float32).ravel('C') - gl.glUniform1f( self.directedPos, directed) - gl.glUniform3fv(self.imageDimsPos, 1, imageDims) - + gl.glUniform1f( self.directedPos, directed) + gl.glUniform3fv(self.imageDimsPos, 1, imageDims) + gl.glUniform3fv(self.voxelOffsetPos, 1, offset) + gl.glUniformMatrix4fv(self.displayToVoxMatPos, 1, False, d2vMat) gl.glUniformMatrix4fv(self.voxToDisplayMatPos, 1, False, v2dMat) @@ -277,12 +284,16 @@ def hardwareDraw(self, zpos, xform=None): elif opts.transform == 'pixdim': resolution = map(lambda r, p: max(r, p), resolution, image.pixdim[:3]) + if opts.transform == 'affine': origin = 'centre' + else: origin = 'corner' + vertices = glroutines.calculateSamplePoints( image.shape, resolution, v2dMat, self.xax, - self.yax)[0] + self.yax, + origin)[0] vertices[:, self.zax] = zpos diff --git a/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl b/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl index ad5865da1..c3217b5e4 100644 --- a/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl +++ b/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl @@ -17,6 +17,8 @@ uniform sampler3D imageTexture; uniform mat4 displayToVoxMat; uniform mat4 voxToDisplayMat; +uniform vec3 voxelOffset; + /* * Transformation matrix which transforms the @@ -74,7 +76,7 @@ void main(void) { * There is no round function in GLSL 1.2, so we use * floor(x + 0.5). */ - voxCoord = floor(vertVoxCoord + 0.5); + voxCoord = floor(vertVoxCoord + voxelOffset); /* * Normalise the voxel coordinates to [0.0, 1.0], diff --git a/fsl/fsleyes/gl/gllinevector.py b/fsl/fsleyes/gl/gllinevector.py index 817b6add0..e9557197e 100644 --- a/fsl/fsleyes/gl/gllinevector.py +++ b/fsl/fsleyes/gl/gllinevector.py @@ -100,6 +100,9 @@ class GLLineVertices(object): texCoords = (texCoords + 0.5) / np.array(image.shape[:3], dtype=np.float32) + if opts.transform in ('id', 'pixdim'): + vertices += 0.5 + self.vertices = vertices self.texCoords = texCoords self.starts = starts diff --git a/fsl/fsleyes/gl/routines.py b/fsl/fsleyes/gl/routines.py index 6e70da4e6..a9430e02b 100644 --- a/fsl/fsleyes/gl/routines.py +++ b/fsl/fsleyes/gl/routines.py @@ -53,7 +53,7 @@ def show2D(xax, yax, width, height, lo, hi): gl.glRotatef(270, 1, 0, 0) -def calculateSamplePoints(shape, resolution, xform, xax, yax): +def calculateSamplePoints(shape, resolution, xform, xax, yax, origin='centre'): """Calculates a uniform grid of points, in the display coordinate system (as specified by the given :class:`.Display` object properties) along the x-y plane (as specified by the xax/yax indices), at which the given image @@ -93,8 +93,8 @@ def calculateSamplePoints(shape, resolution, xform, xax, yax): # values of a bounding box which # encapsulates the entire image, # in the display coordinate system - xmin, xmax = transform.axisBounds(shape, xform, xax) - ymin, ymax = transform.axisBounds(shape, xform, yax) + xmin, xmax = transform.axisBounds(shape, xform, xax, origin) + ymin, ymax = transform.axisBounds(shape, xform, yax, origin) # Number of samples along each display # axis, given the requested resolution -- GitLab