def updateShaderState(self): """Sets all variables required by the vertex and fragment programs. """ if not self.ready(): return opts = self.opts shader = self.shader # enable the vertex and fragment programs shader.load() # The voxValXform transformation turns # an image texture value into a raw # voxel value. The colourMapXform # transformation turns a raw voxel value # into a value between 0 and 1, suitable # for looking up an appropriate colour # in the 1D colour map texture. voxValXform = transform.concat(self.colourTexture.getCoordinateTransform(), self.imageTexture.voxValXform) voxValXform = [voxValXform[0, 0], voxValXform[0, 3], 0, 0] # And the clipping range, normalised # to the image texture value range invClip = 1 if opts.invertClipping else -1 useNegCmap = 1 if opts.useNegativeCmap else 0 imageIsClip = 1 if opts.clipImage is None else -1 imgXform = self.imageTexture.invVoxValXform if opts.clipImage is None: clipXform = imgXform else: clipXform = self.clipTexture.invVoxValXform clipLo = opts.clippingRange[0] * clipXform[0, 0] + clipXform[0, 3] clipHi = opts.clippingRange[1] * clipXform[0, 0] + clipXform[0, 3] texZero = 0.0 * imgXform[ 0, 0] + imgXform[ 0, 3] clipping = [clipLo, clipHi, invClip, imageIsClip] negCmap = [useNegCmap, texZero, 0, 0] changed = False changed |= shader.setFragParam('voxValXform', voxValXform) changed |= shader.setFragParam('clipping', clipping) changed |= shader.setFragParam('negCmap', negCmap) if self.threedee: clipPlanes = np.zeros((5, 4), dtype=np.float32) d2tmat = opts.getTransform('display', 'texture') for i in range(opts.numClipPlanes): origin, normal = self.get3DClipPlane(i) origin = transform.transform(origin, d2tmat) normal = transform.transformNormal(normal, d2tmat) clipPlanes[i, :] = glroutines.planeEquation2(origin, normal) changed |= shader.setFragParam('clipPlanes', clipPlanes) self.shader.unload() return changed
def get3DClipPlane(self, planeIdx): """A convenience method which calculates a point-vector description of the specified clipping plane. ``planeIdx`` is an index into the :attr:`clipPosition`, :attr:`clipAzimuth`, and :attr:`clipInclination`, properties. Returns the clip plane at the given ``planeIdx`` as an origin and normal vector, in the display coordinate system.. """ pos = self.clipPosition[planeIdx] azimuth = self.clipAzimuth[planeIdx] incline = self.clipInclination[planeIdx] b = self.bounds pos = pos / 100.0 azimuth = azimuth * np.pi / 180.0 incline = incline * np.pi / 180.0 xmid = b.xlo + 0.5 * b.xlen ymid = b.ylo + 0.5 * b.ylen zmid = b.zlo + 0.5 * b.zlen centre = [xmid, ymid, zmid] normal = [0, 0, -1] rot1 = transform.axisAnglesToRotMat(incline, 0, 0) rot2 = transform.axisAnglesToRotMat(0, 0, azimuth) rotation = transform.concat(rot2, rot1) normal = transform.transformNormal(normal, rotation) normal = transform.normalise(normal) offset = (pos - 0.5) * max((b.xlen, b.ylen, b.zlen)) origin = centre + normal * offset return origin, normal
def updateShaderState(self): """Updates the parameters used by the shader programs, reflecting the current display properties. """ if not self.ready(): return opts = self.opts display = self.display shader = self.shader # The clipping range options are in the voxel value # range, but the shader needs them to be in image # texture value range (0.0 - 1.0). So let's scale # them. imageIsClip = opts.clipImage is None imgXform = self.imageTexture.invVoxValXform if imageIsClip: clipXform = imgXform else: clipXform = self.clipTexture.invVoxValXform clipLow = opts.clippingRange[0] * clipXform[0, 0] + clipXform[0, 3] clipHigh = opts.clippingRange[1] * clipXform[0, 0] + clipXform[0, 3] texZero = 0.0 * imgXform[0, 0] + imgXform[0, 3] imageShape = self.image.shape[:3] if imageIsClip: clipImageShape = imageShape else: clipImageShape = opts.clipImage.shape[:3] # Create a single transformation matrix # which transforms from image texture values # to voxel values, and scales said voxel # values to colour map texture coordinates. img2CmapXform = transform.concat( self.colourTexture.getCoordinateTransform(), self.imageTexture.voxValXform) shader.load() changed = False changed |= shader.set('useSpline', opts.interpolation == 'spline') changed |= shader.set('imageShape', imageShape) changed |= shader.set('clipLow', clipLow) changed |= shader.set('clipHigh', clipHigh) changed |= shader.set('texZero', texZero) changed |= shader.set('invertClip', opts.invertClipping) changed |= shader.set('useNegCmap', opts.useNegativeCmap) changed |= shader.set('imageIsClip', imageIsClip) changed |= shader.set('img2CmapXform', img2CmapXform) changed |= shader.set('clipImageShape', clipImageShape) changed |= shader.set('imageTexture', 0) changed |= shader.set('colourTexture', 1) changed |= shader.set('negColourTexture', 2) changed |= shader.set('clipTexture', 3) if self.threedee: blendFactor = (1 - opts.blendFactor)**2 clipPlanes = np.zeros((opts.numClipPlanes, 4), dtype=np.float32) d2tmat = opts.getTransform('display', 'texture') if opts.clipMode == 'intersection': clipMode = 1 elif opts.clipMode == 'union': clipMode = 2 elif opts.clipMode == 'complement': clipMode = 3 else: clipMode = 0 for i in range(opts.numClipPlanes): origin, normal = self.get3DClipPlane(i) origin = transform.transform(origin, d2tmat) normal = transform.transformNormal(normal, d2tmat) clipPlanes[i, :] = glroutines.planeEquation2(origin, normal) changed |= shader.set('numClipPlanes', opts.numClipPlanes) changed |= shader.set('clipMode', clipMode) changed |= shader.set('clipPlanes', clipPlanes, opts.numClipPlanes) changed |= shader.set('blendFactor', blendFactor) changed |= shader.set('stepLength', 1.0 / opts.getNumSteps()) changed |= shader.set('alpha', display.alpha / 100.0) shader.unload() return changed