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