@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
803 lines (653 loc) • 32.3 kB
JavaScript
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 };