diff --git a/fsl/fsleyes/gl/gl14/gllinevector_funcs.py b/fsl/fsleyes/gl/gl14/gllinevector_funcs.py index d786be442e8c82fa95e2f0f142a320b59ff54e9e..da3229af77d836f97098abf3dc36fc50b01012db 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 88cf875568b08046ba203c74695a3b73f63ea86d..bbcb7e5c1c73b654f095048929b8dc456b5c4582 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 14734bb8a7918410580597aec392ab3ed057aa61..76094c499a907e12d83b639e52c59cae217d581c 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 ad5865da1719f205352cf6d884c35cf530550543..c3217b5e44aa21751b3a026759f6dcfd23d0e89e 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 817b6add0eb255b6c3ff64a09185db45cb06e6f8..e9557197e9573b25512714785f96c247b3e69148 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 6e70da4e63cd03a50f4cb7b1ae3a786b4f6f066b..a9430e02b887d2b830ce89f26e76a1470146af9e 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