UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

803 lines (653 loc) 32.3 kB
import Constants from '../Core/ImageMapper/Constants.js'; import { setGet, obj, newInstance as newInstance$1, vtkErrorMacro as vtkErrorMacro$1 } from '../../macro.js'; import vtkDataArray from '../../Common/Core/DataArray.js'; import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js'; import vtkHelper from './Helper.js'; import { u as uninitializeBounds } from '../../Common/Core/Math/index.js'; import vtkOpenGLTexture from './Texture.js'; import vtkShaderProgram from './ShaderProgram.js'; import vtkViewNode from '../SceneGraph/ViewNode.js'; import { Representation } from '../Core/Property/Constants.js'; import { Filter, Wrap } from './Texture/Constants.js'; import { InterpolationType } from '../Core/ImageProperty/Constants.js'; import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js'; import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js'; import vtkReplacementShaderMapper from './ReplacementShaderMapper.js'; import { registerOverride } from './ViewNodeFactory.js'; import { i as identity, m as multiply } from '../../vendor/gl-matrix/esm/mat4.js'; var vtkErrorMacro = vtkErrorMacro$1; var SlicingMode = Constants.SlicingMode; // ---------------------------------------------------------------------------- // helper methods // ---------------------------------------------------------------------------- function computeFnToString(property, fn, numberOfComponents) { var pwfun = fn.apply(property); if (pwfun) { var iComps = property.getIndependentComponents(); return "".concat(property.getMTime(), "-").concat(iComps, "-").concat(numberOfComponents); } return '0'; } // ---------------------------------------------------------------------------- // vtkOpenGLImageMapper methods // ---------------------------------------------------------------------------- function vtkOpenGLImageMapper(publicAPI, model) { // Set our className model.classHierarchy.push('vtkOpenGLImageMapper'); publicAPI.buildPass = function (prepass) { if (prepass) { model.openGLImageSlice = publicAPI.getFirstAncestorOfType('vtkOpenGLImageSlice'); model.openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer'); model.openGLRenderWindow = model.openGLRenderer.getParent(); model.context = model.openGLRenderWindow.getContext(); model.tris.setOpenGLRenderWindow(model.openGLRenderWindow); model.openGLTexture.setOpenGLRenderWindow(model.openGLRenderWindow); model.colorTexture.setOpenGLRenderWindow(model.openGLRenderWindow); model.pwfTexture.setOpenGLRenderWindow(model.openGLRenderWindow); var ren = model.openGLRenderer.getRenderable(); model.openGLCamera = model.openGLRenderer.getViewNodeFor(ren.getActiveCamera()); // is slice set by the camera if (model.renderable.getSliceAtFocalPoint()) { model.renderable.setSliceFromCamera(ren.getActiveCamera()); } } }; publicAPI.translucentPass = function (prepass) { if (prepass) { publicAPI.render(); } }; publicAPI.opaqueZBufferPass = function (prepass) { if (prepass) { model.haveSeenDepthRequest = true; model.renderDepth = true; publicAPI.render(); model.renderDepth = false; } }; publicAPI.opaquePass = function (prepass) { if (prepass) { publicAPI.render(); } }; publicAPI.getCoincidentParameters = function (ren, actor) { if (model.renderable.getResolveCoincidentTopology()) { return model.renderable.getCoincidentTopologyPolygonOffsetParameters(); } return null; }; // Renders myself publicAPI.render = function () { var actor = model.openGLImageSlice.getRenderable(); var ren = model.openGLRenderer.getRenderable(); publicAPI.renderPiece(ren, actor); }; publicAPI.buildShaders = function (shaders, ren, actor) { publicAPI.getShaderTemplate(shaders, ren, actor); publicAPI.replaceShaderValues(shaders, ren, actor); }; publicAPI.getShaderTemplate = function (shaders, ren, actor) { shaders.Vertex = vtkPolyDataVS; shaders.Fragment = vtkPolyDataFS; shaders.Geometry = ''; }; publicAPI.replaceShaderValues = function (shaders, ren, actor) { var VSSource = shaders.Vertex; var FSSource = shaders.Fragment; VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Camera::Dec', ['uniform mat4 MCPCMatrix;']).result; VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Impl', [' gl_Position = MCPCMatrix * vertexMC;']).result; VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Impl', 'tcoordVCVSOutput = tcoordMC;').result; VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', 'attribute vec2 tcoordMC; varying vec2 tcoordVCVSOutput;').result; var tNumComp = model.openGLTexture.getComponents(); var iComps = actor.getProperty().getIndependentComponents(); var tcoordDec = ['varying vec2 tcoordVCVSOutput;', // color shift and scale 'uniform float cshift0;', 'uniform float cscale0;', // pwf shift and scale 'uniform float pwfshift0;', 'uniform float pwfscale0;', 'uniform sampler2D texture1;', 'uniform sampler2D colorTexture1;', 'uniform sampler2D pwfTexture1;', 'uniform float opacity;']; if (iComps) { for (var comp = 1; comp < tNumComp; comp++) { tcoordDec = tcoordDec.concat([// color shift and scale "uniform float cshift".concat(comp, ";"), "uniform float cscale".concat(comp, ";"), // weighting shift and scale "uniform float pwfshift".concat(comp, ";"), "uniform float pwfscale".concat(comp, ";")]); } // the heights defined below are the locations // for the up to four components of the tfuns // the tfuns have a height of 2XnumComps pixels so the // values are computed to hit the middle of the two rows // for that component switch (tNumComp) { case 1: tcoordDec = tcoordDec.concat(['uniform float mix0;', '#define height0 0.5']); break; case 2: tcoordDec = tcoordDec.concat(['uniform float mix0;', 'uniform float mix1;', '#define height0 0.25', '#define height1 0.75']); break; case 3: tcoordDec = tcoordDec.concat(['uniform float mix0;', 'uniform float mix1;', 'uniform float mix2;', '#define height0 0.17', '#define height1 0.5', '#define height2 0.83']); break; case 4: tcoordDec = tcoordDec.concat(['uniform float mix0;', 'uniform float mix1;', 'uniform float mix2;', 'uniform float mix3;', '#define height0 0.125', '#define height1 0.375', '#define height2 0.625', '#define height3 0.875']); break; default: vtkErrorMacro('Unsupported number of independent coordinates.'); } } FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', tcoordDec).result; if (iComps) { var rgba = ['r', 'g', 'b', 'a']; var tcoordImpl = ['vec4 tvalue = texture2D(texture1, tcoordVCVSOutput);']; for (var _comp = 0; _comp < tNumComp; _comp++) { tcoordImpl = tcoordImpl.concat(["vec3 tcolor".concat(_comp, " = mix").concat(_comp, " * texture2D(colorTexture1, vec2(tvalue.").concat(rgba[_comp], " * cscale").concat(_comp, " + cshift").concat(_comp, ", height").concat(_comp, ")).rgb;"), "float compWeight".concat(_comp, " = mix").concat(_comp, " * texture2D(pwfTexture1, vec2(tvalue.").concat(rgba[_comp], " * pwfscale").concat(_comp, " + pwfshift").concat(_comp, ", height").concat(_comp, ")).r;")]); } switch (tNumComp) { case 1: tcoordImpl = tcoordImpl.concat(['gl_FragData[0] = vec4(tcolor0.rgb, opacity);']); break; case 2: tcoordImpl = tcoordImpl.concat(['float weightSum = compWeight0 + compWeight1;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum))), opacity);']); break; case 3: tcoordImpl = tcoordImpl.concat(['float weightSum = compWeight0 + compWeight1 + compWeight2;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum)) + (tcolor2.rgb * (compWeight2 / weightSum))), opacity);']); break; case 4: tcoordImpl = tcoordImpl.concat(['float weightSum = compWeight0 + compWeight1 + compWeight2 + compWeight3;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum)) + (tcolor2.rgb * (compWeight2 / weightSum)) + (tcolor3.rgb * (compWeight3 / weightSum))), opacity);']); break; default: vtkErrorMacro('Unsupported number of independent coordinates.'); } FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', tcoordImpl).result; } else { // dependent components switch (tNumComp) { case 1: FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['float intensity = texture2D(texture1, tcoordVCVSOutput).r;', 'vec3 tcolor = texture2D(colorTexture1, vec2(intensity * cscale0 + cshift0, 0.5)).rgb;', 'float scalarOpacity = texture2D(pwfTexture1, vec2(intensity * pwfscale0 + pwfshift0, 0.5)).r;', 'gl_FragData[0] = vec4(tcolor, scalarOpacity * opacity);']).result; break; case 2: FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = texture2D(texture1, tcoordVCVSOutput);', 'float intensity = tcolor.r*cscale0 + cshift0;', 'gl_FragData[0] = vec4(texture2D(colorTexture1, vec2(intensity, 0.5)).rgb, pwfscale0*tcolor.g + pwfshift0);']).result; break; default: FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = cscale0*texture2D(texture1, tcoordVCVSOutput.st) + cshift0;', 'gl_FragData[0] = vec4(texture2D(colorTexture1, vec2(tcolor.r,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.g,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.b,0.5)).r, tcolor.a);']).result; } } if (model.haveSeenDepthRequest) { FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Dec', 'uniform int depthRequest;').result; FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['if (depthRequest == 1) {', 'float iz = floor(gl_FragCoord.z*65535.0 + 0.1);', 'float rf = floor(iz/256.0)/255.0;', 'float gf = mod(iz,256.0)/255.0;', 'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0); }']).result; } shaders.Vertex = VSSource; shaders.Fragment = FSSource; publicAPI.replaceShaderCoincidentOffset(shaders, ren, actor); }; publicAPI.getNeedToRebuildShaders = function (cellBO, ren, actor) { // has something changed that would require us to recreate the shader? // candidates are // property modified (representation interpolation and lighting) // input modified // light complexity changed var tNumComp = model.openGLTexture.getComponents(); var iComp = actor.getProperty().getIndependentComponents(); if (model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) { model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest; model.lastTextureComponents = tNumComp; model.lastIndependentComponents = iComp; return true; } return false; }; publicAPI.updateShaders = function (cellBO, ren, actor) { model.lastBoundBO = cellBO; // has something changed that would require us to recreate the shader? if (publicAPI.getNeedToRebuildShaders(cellBO, ren, actor)) { var shaders = { Vertex: null, Fragment: null, Geometry: null }; publicAPI.buildShaders(shaders, ren, actor); // compile and bind the program if needed var newShader = model.openGLRenderWindow.getShaderCache().readyShaderProgramArray(shaders.Vertex, shaders.Fragment, shaders.Geometry); // if the shader changed reinitialize the VAO if (newShader !== cellBO.getProgram()) { cellBO.setProgram(newShader); // reset the VAO as the shader has changed cellBO.getVAO().releaseGraphicsResources(); } cellBO.getShaderSourceTime().modified(); } else { model.openGLRenderWindow.getShaderCache().readyShaderProgram(cellBO.getProgram()); } cellBO.getVAO().bind(); publicAPI.setMapperShaderParameters(cellBO, ren, actor); publicAPI.setCameraShaderParameters(cellBO, ren, actor); publicAPI.setPropertyShaderParameters(cellBO, ren, actor); }; publicAPI.setMapperShaderParameters = function (cellBO, ren, actor) { // Now to update the VAO too, if necessary. if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) { if (cellBO.getProgram().isAttributeUsed('vertexMC')) { if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'vertexMC', cellBO.getCABO().getVertexOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, 3, model.context.FALSE)) { vtkErrorMacro('Error setting vertexMC in shader VAO.'); } } if (cellBO.getProgram().isAttributeUsed('tcoordMC') && cellBO.getCABO().getTCoordOffset()) { if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'tcoordMC', cellBO.getCABO().getTCoordOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, cellBO.getCABO().getTCoordComponents(), model.context.FALSE)) { vtkErrorMacro('Error setting tcoordMC in shader VAO.'); } } cellBO.getAttributeUpdateTime().modified(); } var texUnit = model.openGLTexture.getTextureUnit(); cellBO.getProgram().setUniformi('texture1', texUnit); var numComp = model.openGLTexture.getComponents(); var iComps = actor.getProperty().getIndependentComponents(); if (iComps) { for (var i = 0; i < numComp; i++) { cellBO.getProgram().setUniformf("mix".concat(i), actor.getProperty().getComponentWeight(i)); } } var oglShiftScale = model.openGLTexture.getShiftAndScale(); // three levels of shift scale combined into one // for performance in the fragment shader for (var _i = 0; _i < numComp; _i++) { var cw = actor.getProperty().getColorWindow(); var cl = actor.getProperty().getColorLevel(); var target = iComps ? _i : 0; var cfun = actor.getProperty().getRGBTransferFunction(target); if (cfun) { var cRange = cfun.getRange(); cw = cRange[1] - cRange[0]; cl = 0.5 * (cRange[1] + cRange[0]); } var scale = oglShiftScale.scale / cw; var shift = (oglShiftScale.shift - cl) / cw + 0.5; cellBO.getProgram().setUniformf("cshift".concat(_i), shift); cellBO.getProgram().setUniformf("cscale".concat(_i), scale); } // pwf shift/scale for (var _i2 = 0; _i2 < numComp; _i2++) { var pwfScale = 1.0; var pwfShift = 0.0; var _target = iComps ? _i2 : 0; var pwfun = actor.getProperty().getPiecewiseFunction(_target); if (pwfun) { var pwfRange = pwfun.getRange(); var length = pwfRange[1] - pwfRange[0]; var mid = 0.5 * (pwfRange[0] + pwfRange[1]); pwfScale = oglShiftScale.scale / length; pwfShift = (oglShiftScale.shift - mid) / length + 0.5; } cellBO.getProgram().setUniformf("pwfshift".concat(_i2), pwfShift); cellBO.getProgram().setUniformf("pwfscale".concat(_i2), pwfScale); } if (model.haveSeenDepthRequest) { cellBO.getProgram().setUniformi('depthRequest', model.renderDepth ? 1 : 0); } // handle coincident if (cellBO.getProgram().isUniformUsed('coffset')) { var cp = publicAPI.getCoincidentParameters(ren, actor); cellBO.getProgram().setUniformf('coffset', cp.offset); // cfactor isn't always used when coffset is. if (cellBO.getProgram().isUniformUsed('cfactor')) { cellBO.getProgram().setUniformf('cfactor', cp.factor); } } var texColorUnit = model.colorTexture.getTextureUnit(); cellBO.getProgram().setUniformi('colorTexture1', texColorUnit); var texOpacityUnit = model.pwfTexture.getTextureUnit(); cellBO.getProgram().setUniformi('pwfTexture1', texOpacityUnit); }; publicAPI.setCameraShaderParameters = function (cellBO, ren, actor) { var program = cellBO.getProgram(); var actMats = model.openGLImageSlice.getKeyMatrices(); var image = model.currentInput; var i2wmat4 = image.getIndexToWorld(); multiply(model.imagemat, actMats.mcwc, i2wmat4); var keyMats = model.openGLCamera.getKeyMatrices(ren); multiply(model.imagemat, keyMats.wcpc, model.imagemat); if (cellBO.getCABO().getCoordShiftAndScaleEnabled()) { var inverseShiftScaleMat = cellBO.getCABO().getInverseShiftAndScaleMatrix(); multiply(model.imagemat, model.imagemat, inverseShiftScaleMat); } program.setUniformMatrix('MCPCMatrix', model.imagemat); }; publicAPI.setPropertyShaderParameters = function (cellBO, ren, actor) { var program = cellBO.getProgram(); var ppty = actor.getProperty(); var opacity = ppty.getOpacity(); program.setUniformf('opacity', opacity); }; publicAPI.renderPieceStart = function (ren, actor) { // make sure the BOs are up to date publicAPI.updateBufferObjects(ren, actor); // Bind the OpenGL, this is shared between the different primitive/cell types. model.lastBoundBO = null; }; publicAPI.renderPieceDraw = function (ren, actor) { var gl = model.context; // activate the texture model.openGLTexture.activate(); model.colorTexture.activate(); model.pwfTexture.activate(); // draw polygons if (model.tris.getCABO().getElementCount()) { // First we do the triangles, update the shader, set uniforms, etc. publicAPI.updateShaders(model.tris, ren, actor); gl.drawArrays(gl.TRIANGLES, 0, model.tris.getCABO().getElementCount()); model.tris.getVAO().release(); } model.openGLTexture.deactivate(); model.colorTexture.deactivate(); model.pwfTexture.deactivate(); }; publicAPI.renderPieceFinish = function (ren, actor) {}; publicAPI.renderPiece = function (ren, actor) { // Make sure that we have been properly initialized. // if (ren.getRenderWindow().checkAbortStatus()) { // return; // } publicAPI.invokeEvent({ type: 'StartEvent' }); model.renderable.update(); model.currentInput = model.renderable.getInputData(); publicAPI.invokeEvent({ type: 'EndEvent' }); if (!model.currentInput) { vtkErrorMacro('No input!'); return; } publicAPI.renderPieceStart(ren, actor); publicAPI.renderPieceDraw(ren, actor); publicAPI.renderPieceFinish(ren, actor); }; publicAPI.computeBounds = function (ren, actor) { if (!publicAPI.getInput()) { uninitializeBounds(model.bounds); return; } model.bounds = publicAPI.getInput().getBounds(); }; publicAPI.updateBufferObjects = function (ren, actor) { // Rebuild buffers if needed if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) { publicAPI.buildBufferObjects(ren, actor); } }; publicAPI.getNeedToRebuildBufferObjects = function (ren, actor) { // first do a coarse check if (model.VBOBuildTime.getMTime() < publicAPI.getMTime() || model.VBOBuildTime.getMTime() < actor.getMTime() || model.VBOBuildTime.getMTime() < model.renderable.getMTime() || model.VBOBuildTime.getMTime() < actor.getProperty().getMTime() || model.VBOBuildTime.getMTime() < model.currentInput.getMTime()) { return true; } return false; }; publicAPI.buildBufferObjects = function (ren, actor) { var image = model.currentInput; if (!image) { return; } var imgScalars = image.getPointData() && image.getPointData().getScalars(); if (!imgScalars) { return; } var actorProperty = actor.getProperty(); // set interpolation on the texture based on property setting var iType = actorProperty.getInterpolationType(); if (iType === InterpolationType.NEAREST) { model.colorTexture.setMinificationFilter(Filter.NEAREST); model.colorTexture.setMagnificationFilter(Filter.NEAREST); model.pwfTexture.setMinificationFilter(Filter.NEAREST); model.pwfTexture.setMagnificationFilter(Filter.NEAREST); } else { model.colorTexture.setMinificationFilter(Filter.LINEAR); model.colorTexture.setMagnificationFilter(Filter.LINEAR); model.pwfTexture.setMinificationFilter(Filter.LINEAR); model.pwfTexture.setMagnificationFilter(Filter.LINEAR); } var numComp = imgScalars.getNumberOfComponents(); var iComps = actorProperty.getIndependentComponents(); var numIComps = iComps ? numComp : 1; var textureHeight = iComps ? 2 * numIComps : 1; var cfunToString = computeFnToString(actorProperty, actorProperty.getRGBTransferFunction, numIComps); if (model.colorTextureString !== cfunToString) { var cWidth = 1024; var cSize = cWidth * textureHeight * 3; var cTable = new Uint8Array(cSize); var cfun = actorProperty.getRGBTransferFunction(); if (cfun) { var tmpTable = new Float32Array(cWidth * 3); for (var c = 0; c < numIComps; c++) { cfun = actorProperty.getRGBTransferFunction(c); var cRange = cfun.getRange(); cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1); if (iComps) { for (var i = 0; i < cWidth * 3; i++) { cTable[c * cWidth * 6 + i] = 255.0 * tmpTable[i]; cTable[c * cWidth * 6 + i + cWidth * 3] = 255.0 * tmpTable[i]; } } else { for (var _i3 = 0; _i3 < cWidth * 3; _i3++) { cTable[c * cWidth * 6 + _i3] = 255.0 * tmpTable[_i3]; } } } model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable); } else { for (var _i4 = 0; _i4 < cWidth * 3; ++_i4) { cTable[_i4] = 255.0 * _i4 / ((cWidth - 1) * 3); cTable[_i4 + 1] = 255.0 * _i4 / ((cWidth - 1) * 3); cTable[_i4 + 2] = 255.0 * _i4 / ((cWidth - 1) * 3); } model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable); } model.colorTextureString = cfunToString; } // Build piecewise function buffer. This buffer is used either // for component weighting or opacity, depending on whether we're // rendering components independently or not. var pwfunToString = computeFnToString(actorProperty, actorProperty.getPiecewiseFunction, numIComps); if (model.pwfTextureString !== pwfunToString) { var pwfWidth = 1024; var pwfSize = pwfWidth * textureHeight; var pwfTable = new Uint8Array(pwfSize); var pwfun = actorProperty.getPiecewiseFunction(); // support case where pwfun is added/removed model.pwfTexture.resetFormatAndType(); if (pwfun) { var pwfFloatTable = new Float32Array(pwfSize); var _tmpTable = new Float32Array(pwfWidth); for (var _c = 0; _c < numIComps; ++_c) { pwfun = actorProperty.getPiecewiseFunction(_c); if (pwfun === null) { // Piecewise constant max if no function supplied for this component pwfFloatTable.fill(1.0); } else { var pwfRange = pwfun.getRange(); pwfun.getTable(pwfRange[0], pwfRange[1], pwfWidth, _tmpTable, 1); // adjust for sample distance etc if (iComps) { for (var _i5 = 0; _i5 < pwfWidth; _i5++) { pwfFloatTable[_c * pwfWidth * 2 + _i5] = _tmpTable[_i5]; pwfFloatTable[_c * pwfWidth * 2 + _i5 + pwfWidth] = _tmpTable[_i5]; } } else { for (var _i6 = 0; _i6 < pwfWidth; _i6++) { pwfFloatTable[_c * pwfWidth * 2 + _i6] = _tmpTable[_i6]; } } } } model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable); } else { // default is opaque pwfTable.fill(255.0); model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable); } model.pwfTextureString = pwfunToString; } // Find what IJK axis and what direction to slice along var _model$renderable$get = model.renderable.getClosestIJKAxis(), ijkMode = _model$renderable$get.ijkMode; // Find the IJK slice var nSlice = model.renderable.getSlice(); if (ijkMode !== model.renderable.getSlicingMode()) { // If not IJK slicing, get the IJK slice from the XYZ position/slice nSlice = model.renderable.getSliceAtPosition(nSlice); } // Find sliceOffset var ext = image.getExtent(); var sliceOffset; if (ijkMode === SlicingMode.I) { sliceOffset = nSlice - ext[0]; } if (ijkMode === SlicingMode.J) { sliceOffset = nSlice - ext[2]; } if (ijkMode === SlicingMode.K || ijkMode === SlicingMode.NONE) { sliceOffset = nSlice - ext[4]; } // rebuild the VBO if the data has changed var toString = "".concat(nSlice, "A").concat(image.getMTime(), "A").concat(imgScalars.getMTime(), "B").concat(publicAPI.getMTime(), "C").concat(model.renderable.getSlicingMode(), "D").concat(actor.getProperty().getMTime()); if (model.VBOBuildString !== toString) { // Build the VBOs var dims = image.getDimensions(); if (iType === InterpolationType.NEAREST) { if (numComp === 4) { model.openGLTexture.setGenerateMipmap(true); model.openGLTexture.setMinificationFilter(Filter.NEAREST); } else { model.openGLTexture.setMinificationFilter(Filter.NEAREST); } model.openGLTexture.setMagnificationFilter(Filter.NEAREST); } else { if (numComp === 4) { model.openGLTexture.setGenerateMipmap(true); model.openGLTexture.setMinificationFilter(Filter.LINEAR_MIPMAP_LINEAR); } else { model.openGLTexture.setMinificationFilter(Filter.LINEAR); } model.openGLTexture.setMagnificationFilter(Filter.LINEAR); } model.openGLTexture.setWrapS(Wrap.CLAMP_TO_EDGE); model.openGLTexture.setWrapT(Wrap.CLAMP_TO_EDGE); var sliceSize = dims[0] * dims[1] * numComp; var ptsArray = new Float32Array(12); var tcoordArray = new Float32Array(8); for (var _i7 = 0; _i7 < 4; _i7++) { tcoordArray[_i7 * 2] = _i7 % 2 ? 1.0 : 0.0; tcoordArray[_i7 * 2 + 1] = _i7 > 1 ? 1.0 : 0.0; } var basicScalars = imgScalars.getData(); var scalars = null; // Get right scalars according to slicing mode if (ijkMode === SlicingMode.I) { scalars = new basicScalars.constructor(dims[2] * dims[1] * numComp); var id = 0; for (var k = 0; k < dims[2]; k++) { for (var j = 0; j < dims[1]; j++) { var bsIdx = (sliceOffset + j * dims[0] + k * dims[0] * dims[1]) * numComp; id = (k * dims[1] + j) * numComp; scalars.set(basicScalars.subarray(bsIdx, bsIdx + numComp), id); } } dims[0] = dims[1]; dims[1] = dims[2]; ptsArray[0] = nSlice; ptsArray[1] = ext[2]; ptsArray[2] = ext[4]; ptsArray[3] = nSlice; ptsArray[4] = ext[3]; ptsArray[5] = ext[4]; ptsArray[6] = nSlice; ptsArray[7] = ext[2]; ptsArray[8] = ext[5]; ptsArray[9] = nSlice; ptsArray[10] = ext[3]; ptsArray[11] = ext[5]; } else if (ijkMode === SlicingMode.J) { scalars = new basicScalars.constructor(dims[2] * dims[0] * numComp); var _id = 0; for (var _k = 0; _k < dims[2]; _k++) { for (var _i8 = 0; _i8 < dims[0]; _i8++) { var _bsIdx = (_i8 + sliceOffset * dims[0] + _k * dims[0] * dims[1]) * numComp; _id = (_k * dims[0] + _i8) * numComp; scalars.set(basicScalars.subarray(_bsIdx, _bsIdx + numComp), _id); } } dims[1] = dims[2]; ptsArray[0] = ext[0]; ptsArray[1] = nSlice; ptsArray[2] = ext[4]; ptsArray[3] = ext[1]; ptsArray[4] = nSlice; ptsArray[5] = ext[4]; ptsArray[6] = ext[0]; ptsArray[7] = nSlice; ptsArray[8] = ext[5]; ptsArray[9] = ext[1]; ptsArray[10] = nSlice; ptsArray[11] = ext[5]; } else if (ijkMode === SlicingMode.K || ijkMode === SlicingMode.NONE) { scalars = basicScalars.subarray(sliceOffset * sliceSize, (sliceOffset + 1) * sliceSize); ptsArray[0] = ext[0]; ptsArray[1] = ext[2]; ptsArray[2] = nSlice; ptsArray[3] = ext[1]; ptsArray[4] = ext[2]; ptsArray[5] = nSlice; ptsArray[6] = ext[0]; ptsArray[7] = ext[3]; ptsArray[8] = nSlice; ptsArray[9] = ext[1]; ptsArray[10] = ext[3]; ptsArray[11] = nSlice; } else { vtkErrorMacro('Reformat slicing not yet supported.'); } model.openGLTexture.create2DFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars); model.openGLTexture.activate(); model.openGLTexture.sendParameters(); model.openGLTexture.deactivate(); var points = vtkDataArray.newInstance({ numberOfComponents: 3, values: ptsArray }); points.setName('points'); var tcoords = vtkDataArray.newInstance({ numberOfComponents: 2, values: tcoordArray }); tcoords.setName('tcoords'); var cellArray = new Uint16Array(8); cellArray[0] = 3; cellArray[1] = 0; cellArray[2] = 1; cellArray[3] = 3; cellArray[4] = 3; cellArray[5] = 0; cellArray[6] = 3; cellArray[7] = 2; var cells = vtkDataArray.newInstance({ numberOfComponents: 1, values: cellArray }); model.tris.getCABO().createVBO(cells, 'polys', Representation.SURFACE, { points: points, tcoords: tcoords, cellOffset: 0 }); model.VBOBuildTime.modified(); model.VBOBuildString = toString; } }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { VBOBuildTime: 0, VBOBuildString: null, openGLTexture: null, tris: null, imagemat: null, colorTexture: null, pwfTexture: null, lastHaveSeenDepthRequest: false, haveSeenDepthRequest: false, lastTextureComponents: 0 }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance vtkViewNode.extend(publicAPI, model, initialValues); vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues); model.tris = vtkHelper.newInstance(); model.openGLTexture = vtkOpenGLTexture.newInstance(); model.colorTexture = vtkOpenGLTexture.newInstance(); model.pwfTexture = vtkOpenGLTexture.newInstance(); model.imagemat = identity(new Float64Array(16)); // Build VTK API setGet(publicAPI, model, []); model.VBOBuildTime = {}; obj(model.VBOBuildTime); // Object methods vtkOpenGLImageMapper(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = newInstance$1(extend, 'vtkOpenGLImageMapper'); // ---------------------------------------------------------------------------- var vtkImageMapper = { newInstance: newInstance, extend: extend }; // Register ourself to OpenGL backend if imported registerOverride('vtkImageMapper', newInstance); export default vtkImageMapper; export { extend, newInstance };