From e74185056d0aced67405bb2444c6473ea56b7101 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Wed, 16 Dec 2015 17:51:44 +0000
Subject: [PATCH] GL21 LineVector  working, but all the other things still
 broken.

---
 fsl/fsleyes/displaycontext/tensoropts.py   |   8 +-
 fsl/fsleyes/gl/gl21/gllinevector_funcs.py  | 112 +++++++++------------
 fsl/fsleyes/gl/gl21/gllinevector_vert.glsl |  11 +-
 fsl/fsleyes/gl/gl21/gltensor_funcs.py      |  21 ++--
 fsl/fsleyes/gl/shaders.py                  |  24 ++++-
 5 files changed, 92 insertions(+), 84 deletions(-)

diff --git a/fsl/fsleyes/displaycontext/tensoropts.py b/fsl/fsleyes/displaycontext/tensoropts.py
index ef7ed0894..c3b15b34a 100644
--- a/fsl/fsleyes/displaycontext/tensoropts.py
+++ b/fsl/fsleyes/displaycontext/tensoropts.py
@@ -19,18 +19,22 @@ class TensorOpts(vectoropts.VectorOpts):
     """
 
 
-    # Enable/disable lighting effects
     lighting = props.Boolean(default=True)
     """Enables a basic lighting model on the tensor ellipsoids. """
 
 
-    # Tensor ellipsoid resolution
     tensorResolution = props.Int(minval=4, maxval=20, default=10)
     """Tensor ellipsoid resolution - this value controls the number of vertices
     used to represent each tensor. It is ultimately passed to the
     :func:`.routines.unitSphere` function.
     """
 
+    tensorScale = props.Real(minval=0.0, maxval=5.0, default=1.0)
+    """Scaling factor - by default, the tensor ellipsoids are scaled such that
+    the biggest tensor (as defined by the first principal eigenvalue) fits
+    inside a voxel. This parameter can be used to adjust this scale.
+    """
+
     
     def __init__(self, *args, **kwargs):
         """Create a ``TensorOpts`` instance. All arguments are passed through
diff --git a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py
index c82a87d15..436c75e92 100644
--- a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py
+++ b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py
@@ -94,42 +94,21 @@ def compileShaders(self):
     
     self.shaders = shaders.compileShaders(vertShaderSrc, fragShaderSrc)
 
-    self.vertexPos          = gl.glGetAttribLocation( self.shaders,
-                                                      'vertex')
-    self.vertexIDPos        = gl.glGetAttribLocation( self.shaders,
-                                                      'vertexID')
-    self.texCoordPos        = gl.glGetAttribLocation( self.shaders,
-                                                      'texCoord') 
-    self.imageShapePos      = gl.glGetUniformLocation(self.shaders,
-                                                      'imageShape')
-    self.imageDimsPos       = gl.glGetUniformLocation(self.shaders,
-                                                      'imageDims') 
-    self.directedPos        = gl.glGetUniformLocation(self.shaders,
-                                                      'directed')
-    self.imageTexturePos    = gl.glGetUniformLocation(self.shaders,
-                                                      'imageTexture')
-    self.modTexturePos      = gl.glGetUniformLocation(self.shaders,
-                                                      'modTexture')
-    self.xColourTexturePos  = gl.glGetUniformLocation(self.shaders,
-                                                      'xColourTexture')
-    self.yColourTexturePos  = gl.glGetUniformLocation(self.shaders,
-                                                      'yColourTexture') 
-    self.zColourTexturePos  = gl.glGetUniformLocation(self.shaders,
-                                                      'zColourTexture')
-    self.modThresholdPos    = gl.glGetUniformLocation(self.shaders,
-                                                      'modThreshold') 
-    self.useSplinePos       = gl.glGetUniformLocation(self.shaders,
-                                                      'useSpline')
-    self.voxValXformPos     = gl.glGetUniformLocation(self.shaders,
-                                                      'voxValXform')
-    self.voxToDisplayMatPos = gl.glGetUniformLocation(self.shaders,
-                                                      'voxToDisplayMat') 
-    self.displayToVoxMatPos = gl.glGetUniformLocation(self.shaders,
-                                                      'displayToVoxMat')
-    self.voxelOffsetPos     = gl.glGetUniformLocation(self.shaders,
-                                                      'voxelOffset') 
-    self.cmapXformPos       = gl.glGetUniformLocation(self.shaders,
-                                                      'cmapXform')
+    vertAtts     = ['vertex', 'vertexID']
+
+    vertUniforms = ['imageTexture', 'displayToVoxMat', 'voxToDisplayMat',
+                    'voxelOffset',  'voxValXform',     'imageShape',
+                    'directed',     'imageDims']
+
+    fragUniforms = ['imageTexture',   'modulateTexture', 'clipTexture',
+                    'clipThreshold',  'xColourTexture',  'yColourTexture',
+                    'zColourTexture', 'voxValXform',     'cmapXform',
+                    'imageShape',     'useSpline']
+
+    self.shaderVars = shaders.getShaderVars(self.shaders,
+                                            vertAtts,
+                                            vertUniforms,
+                                            fragUniforms)
 
     
 def updateShaderState(self):
@@ -137,33 +116,40 @@ def updateShaderState(self):
 
     image = self.vectorImage
     opts  = self.displayOpts
+    svars = self.shaderVars
 
     # The coordinate transformation matrices for 
     # each of the three colour textures are identical,
     # so we'll just use the xColourTexture matrix
-    cmapXform   = self.xColourTexture.getCoordinateTransform()
-    voxValXform = self.imageTexture.voxValXform
-    useSpline   = False
-    imageShape  = np.array(image.shape[:3], dtype=np.float32)
+    cmapXform     = self.xColourTexture.getCoordinateTransform()
+    voxValXform   = self.imageTexture.voxValXform
+    useSpline     = False
+    imageShape    = np.array(image.shape[:3], dtype=np.float32)
+    clipThreshold = opts.clipThreshold
 
     voxValXform = np.array(voxValXform, dtype=np.float32).ravel('C')
     cmapXform   = np.array(cmapXform,   dtype=np.float32).ravel('C')
 
+    invClipValXform = self.clipTexture .invVoxValXform
+    clipThreshold   = clipThreshold * invClipValXform[0, 0] + \
+                                      invClipValXform[3, 0] 
+
     gl.glUseProgram(self.shaders)
 
-    gl.glUniform1f( self.useSplinePos,     useSpline)
-    gl.glUniform3fv(self.imageShapePos, 1, imageShape)
+    gl.glUniform1f( svars['useSpline'],     useSpline)
+    gl.glUniform3fv(svars['imageShape'], 1, imageShape)
     
-    gl.glUniformMatrix4fv(self.voxValXformPos, 1, False, voxValXform)
-    gl.glUniformMatrix4fv(self.cmapXformPos,   1, False, cmapXform)
+    gl.glUniformMatrix4fv(svars['voxValXform'], 1, False, voxValXform)
+    gl.glUniformMatrix4fv(svars['cmapXform'],   1, False, cmapXform)
 
-    gl.glUniform1f(self.modThresholdPos, opts.modThreshold / 100.0)
+    gl.glUniform1f(svars['clipThreshold'], clipThreshold)
 
-    gl.glUniform1i(self.imageTexturePos,   0)
-    gl.glUniform1i(self.modTexturePos,     1)
-    gl.glUniform1i(self.xColourTexturePos, 2)
-    gl.glUniform1i(self.yColourTexturePos, 3)
-    gl.glUniform1i(self.zColourTexturePos, 4)
+    gl.glUniform1i(svars['imageTexture'],    0)
+    gl.glUniform1i(svars['modulateTexture'], 1)
+    gl.glUniform1i(svars['clipTexture'],     2)
+    gl.glUniform1i(svars['xColourTexture'],  3)
+    gl.glUniform1i(svars['yColourTexture'],  4)
+    gl.glUniform1i(svars['zColourTexture'],  5)
 
     directed  = opts.directed
     imageDims = image.pixdim[:3]
@@ -181,12 +167,12 @@ def updateShaderState(self):
     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.glUniform3fv(self.voxelOffsetPos, 1, offset)
+    gl.glUniform1f( svars['directed'],       directed)
+    gl.glUniform3fv(svars['imageDims'],   1, imageDims)
+    gl.glUniform3fv(svars['voxelOffset'], 1, offset)
 
-    gl.glUniformMatrix4fv(self.displayToVoxMatPos, 1, False, d2vMat)
-    gl.glUniformMatrix4fv(self.voxToDisplayMatPos, 1, False, v2dMat) 
+    gl.glUniformMatrix4fv(svars['displayToVoxMat'], 1, False, d2vMat)
+    gl.glUniformMatrix4fv(svars['voxToDisplayMat'], 1, False, v2dMat) 
 
     gl.glUseProgram(0) 
 
@@ -207,6 +193,7 @@ def draw(self, zpos, xform=None):
 
     image      = self.vectorImage
     opts       = self.displayOpts
+    svars      = self.shaderVars
     v2dMat     = opts.getTransform('voxel', 'display')
     resolution = np.array([opts.resolution] * 3)
 
@@ -232,32 +219,31 @@ def draw(self, zpos, xform=None):
     else:             xform = transform.concat(v2dMat, xform)
     
     xform = np.array(xform, dtype=np.float32).ravel('C') 
-    gl.glUniformMatrix4fv(self.voxToDisplayMatPos, 1, False, xform)
+    gl.glUniformMatrix4fv(svars['voxToDisplayMat'], 1, False, xform)
 
     # bind the vertex ID buffer
     gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexIDBuffer)
     gl.glBufferData(
         gl.GL_ARRAY_BUFFER, indices.nbytes, indices, gl.GL_STATIC_DRAW)
     gl.glVertexAttribPointer(
-        self.vertexIDPos, 1, gl.GL_UNSIGNED_INT, gl.GL_FALSE, 0, None)
-    gl.glEnableVertexAttribArray(self.vertexIDPos)
+        svars['vertexID'], 1, gl.GL_UNSIGNED_INT, gl.GL_FALSE, 0, None)
 
     # and the vertex buffer
     gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexBuffer)
     gl.glBufferData(
         gl.GL_ARRAY_BUFFER, vertices.nbytes, vertices, gl.GL_STATIC_DRAW)    
     gl.glVertexAttribPointer(
-        self.vertexPos, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
+        svars['vertex'], 3, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
 
-    gl.glEnableVertexAttribArray(self.vertexPos) 
-    gl.glEnableVertexAttribArray(self.vertexIDPos) 
+    gl.glEnableVertexAttribArray(svars['vertex']) 
+    gl.glEnableVertexAttribArray(svars['vertexID'])
         
     gl.glLineWidth(opts.lineWidth)
     gl.glDrawArrays(gl.GL_LINES, 0, vertices.size / 3)
 
     gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
-    gl.glDisableVertexAttribArray(self.vertexPos)
-    gl.glDisableVertexAttribArray(self.vertexIDPos) 
+    gl.glEnableVertexAttribArray(svars['vertexID'])
+    gl.glEnableVertexAttribArray(svars['vertex'])
 
 
 def drawAll(self, zposes, xforms):
diff --git a/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl b/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl
index 861fb8970..cef9d9ee8 100644
--- a/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl
+++ b/fsl/fsleyes/gl/gl21/gllinevector_vert.glsl
@@ -19,7 +19,6 @@ uniform mat4 voxToDisplayMat;
 
 uniform vec3 voxelOffset;
 
-
 /*
  * Transformation matrix which transforms the
  * vector texture data to its original data range.
@@ -32,7 +31,11 @@ uniform mat4 voxValXform;
  */
 uniform vec3 imageShape;
 
-
+/*
+ * Line vectors are interpreted as directed - each
+ * line begins in the centre of its voxel, and extends
+ * outwards.
+ */
 uniform bool directed;
 
 /*
@@ -40,7 +43,9 @@ uniform bool directed;
  */
 uniform vec3 imageDims;
 
-
+/*
+ * The current vertex on the current line.
+ */
 attribute vec3 vertex;
 
 /*
diff --git a/fsl/fsleyes/gl/gl21/gltensor_funcs.py b/fsl/fsleyes/gl/gl21/gltensor_funcs.py
index 9d1506a31..b38fbee52 100644
--- a/fsl/fsleyes/gl/gl21/gltensor_funcs.py
+++ b/fsl/fsleyes/gl/gl21/gltensor_funcs.py
@@ -103,8 +103,8 @@ def compileShaders(self):
     
     self.shaders = shaders.compileShaders(vertShaderSrc, fragShaderSrc)
 
-    shaderVars = {}
-
+    vertAtts     = ['voxel', 'vertex']
+ 
     vertUniforms = ['v1Texture',       'v2Texture',  'v3Texture',
                     'l1Texture',       'l2Texture',  'l3Texture',
                     'v1ValXform',      'v2ValXform', 'v3ValXform',
@@ -113,25 +113,16 @@ def compileShaders(self):
                     'lighting',        'lightPos',   'normalMatrix',
                     'eigValNorm',      'zax']
 
-    vertAtts     = ['voxel', 'vertex']
-
     fragUniforms = ['imageTexture',   'modulateTexture', 'clipTexture',
                     'clipThreshold',  'xColourTexture',  'yColourTexture',
                     'zColourTexture', 'voxValXform',     'cmapXform',
                     'imageShape',     'useSpline']
 
-    for vu in vertUniforms:
-        shaderVars[vu] = gl.glGetUniformLocation(self.shaders, vu)
-        
-    for va in vertAtts:
-        shaderVars[va] = gl.glGetAttribLocation(self.shaders, va)
-
-    for fu in fragUniforms:
-        if fu in shaderVars:
-            continue
-        shaderVars[fu] = gl.glGetUniformLocation(self.shaders, fu)
 
-    self.shaderVars = shaderVars
+    self.shaderVars = shaders.getShaderVars(self.shaders,
+                                            vertAtts,
+                                            vertUniforms,
+                                            fragUniforms)
 
 
 def updateShaderState(self):
diff --git a/fsl/fsleyes/gl/shaders.py b/fsl/fsleyes/gl/shaders.py
index d0362eb9e..6f503e053 100644
--- a/fsl/fsleyes/gl/shaders.py
+++ b/fsl/fsleyes/gl/shaders.py
@@ -117,7 +117,29 @@ def setFragmentProgramMatrix(index, matrix):
     for i, row in enumerate(matrix):
         arbfp.glProgramLocalParameter4fARB(
             arbfp.GL_FRAGMENT_PROGRAM_ARB, i + index,
-            row[0], row[1], row[2], row[3]) 
+            row[0], row[1], row[2], row[3])
+
+
+def getShaderVars(shaders, vertAtts, vertUniforms, fragUniforms):
+    """
+    """
+
+    import OpenGL.GL as gl
+
+    shaderVars = {}
+
+    for vu in vertUniforms:
+        shaderVars[vu] = gl.glGetUniformLocation(shaders, vu)
+        
+    for va in vertAtts:
+        shaderVars[va] = gl.glGetAttribLocation(shaders, va)
+
+    for fu in fragUniforms:
+        if fu in shaderVars:
+            continue
+        shaderVars[fu] = gl.glGetUniformLocation(shaders, fu)
+
+    return shaderVars
 
 
 def compilePrograms(vertexProgramSrc, fragmentProgramSrc):
-- 
GitLab