@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
298 lines (243 loc) • 15 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import { ObjectType } from './BufferObject/Constants.js';
import { newInstance as newInstance$1, vtkErrorMacro as vtkErrorMacro$1 } from '../../macro.js';
import vtkBufferObject from './BufferObject.js';
import { v as vtkStickMapperVS } from './glsl/vtkStickMapperVS.glsl.js';
import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
import vtkShaderProgram from './ShaderProgram.js';
import vtkOpenGLPolyDataMapper from './PolyDataMapper.js';
import { registerOverride } from './ViewNodeFactory.js';
import { m as multiply } from '../../vendor/gl-matrix/esm/mat4.js';
import { m as multiply$1 } from '../../vendor/gl-matrix/esm/mat3.js';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var vtkErrorMacro = vtkErrorMacro$1; // ----------------------------------------------------------------------------
// vtkOpenGLStickMapper methods
// ----------------------------------------------------------------------------
function vtkOpenGLStickMapper(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkOpenGLStickMapper'); // Capture 'parentClass' api for internal use
var superClass = _objectSpread({}, publicAPI);
publicAPI.getShaderTemplate = function (shaders, ren, actor) {
shaders.Vertex = vtkStickMapperVS;
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 VCPCMatrix;\n', 'uniform mat4 MCVCMatrix;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::PositionVC::Dec', 'varying vec4 vertexVCVSOutput;').result; // we create vertexVC below, so turn off the default
// implementation
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::PositionVC::Impl', ' vec4 vertexVC = vertexVCVSOutput;\n').result; // for lights kit and positional the VCPC matrix is already defined
// so don't redefine it
var replacement = ['uniform int cameraParallel;\n', 'varying float radiusVCVSOutput;\n', 'varying vec3 orientVCVSOutput;\n', 'varying float lengthVCVSOutput;\n', 'varying vec3 centerVCVSOutput;\n', 'uniform mat4 VCPCMatrix;\n'];
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Dec', replacement).result;
var fragString = '';
if (model.context.getExtension('EXT_frag_depth')) {
fragString = ' gl_FragDepthEXT = (pos.z / pos.w + 1.0) / 2.0;\n';
}
if (model.openGLRenderWindow.getWebgl2()) {
fragString = 'gl_FragDepth = (pos.z / pos.w + 1.0) / 2.0;\n';
} // see https://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Depth::Impl', [// compute the eye position and unit direction
' vec3 EyePos;\n', ' vec3 EyeDir;\n', ' if (cameraParallel != 0) {\n', ' EyePos = vec3(vertexVC.x, vertexVC.y, vertexVC.z + 3.0*radiusVCVSOutput);\n', ' EyeDir = vec3(0.0,0.0,-1.0); }\n', ' else {\n', ' EyeDir = vertexVC.xyz;\n', ' EyePos = vec3(0.0,0.0,0.0);\n', ' float lengthED = length(EyeDir);\n', ' EyeDir = normalize(EyeDir);\n', // we adjust the EyePos to be closer if it is too far away
// to prevent floating point precision noise
' if (lengthED > radiusVCVSOutput*3.0) {\n', ' EyePos = vertexVC.xyz - EyeDir*3.0*radiusVCVSOutput; }\n', ' }\n', // translate to Stick center
' EyePos = EyePos - centerVCVSOutput;\n', // rotate to new basis
// base1, base2, orientVC
' vec3 base1;\n', ' if (abs(orientVCVSOutput.z) < 0.99) {\n', ' base1 = normalize(cross(orientVCVSOutput,vec3(0.0,0.0,1.0))); }\n', ' else {\n', ' base1 = normalize(cross(orientVCVSOutput,vec3(0.0,1.0,0.0))); }\n', ' vec3 base2 = cross(orientVCVSOutput,base1);\n', ' EyePos = vec3(dot(EyePos,base1),dot(EyePos,base2),dot(EyePos,orientVCVSOutput));\n', ' EyeDir = vec3(dot(EyeDir,base1),dot(EyeDir,base2),dot(EyeDir,orientVCVSOutput));\n', // scale by radius
' EyePos = EyePos/radiusVCVSOutput;\n', // find the intersection
' float a = EyeDir.x*EyeDir.x + EyeDir.y*EyeDir.y;\n', ' float b = 2.0*(EyePos.x*EyeDir.x + EyePos.y*EyeDir.y);\n', ' float c = EyePos.x*EyePos.x + EyePos.y*EyePos.y - 1.0;\n', ' float d = b*b - 4.0*a*c;\n', ' vec3 normalVCVSOutput = vec3(0.0,0.0,1.0);\n', ' if (d < 0.0) { discard; }\n', ' else {\n', ' float t = (-b - sqrt(d))/(2.0*a);\n', ' float tz = EyePos.z + t*EyeDir.z;\n', ' vec3 iPoint = EyePos + t*EyeDir;\n', ' if (abs(iPoint.z)*radiusVCVSOutput > lengthVCVSOutput*0.5) {\n', // test for end cap
' float t2 = (-b + sqrt(d))/(2.0*a);\n', ' float tz2 = EyePos.z + t2*EyeDir.z;\n', ' if (tz2*radiusVCVSOutput > lengthVCVSOutput*0.5 || tz*radiusVCVSOutput < -0.5*lengthVCVSOutput) { discard; }\n', ' else {\n', ' normalVCVSOutput = orientVCVSOutput;\n', ' float t3 = (lengthVCVSOutput*0.5/radiusVCVSOutput - EyePos.z)/EyeDir.z;\n', ' iPoint = EyePos + t3*EyeDir;\n', ' vertexVC.xyz = radiusVCVSOutput*(iPoint.x*base1 + iPoint.y*base2 + iPoint.z*orientVCVSOutput) + centerVCVSOutput;\n', ' }\n', ' }\n', ' else {\n', // The normal is the iPoint.xy rotated back into VC
' normalVCVSOutput = iPoint.x*base1 + iPoint.y*base2;\n', // rescale rerotate and translate
' vertexVC.xyz = radiusVCVSOutput*(normalVCVSOutput + iPoint.z*orientVCVSOutput) + centerVCVSOutput;\n', ' }\n', ' }\n', // ' vec3 normalVC = vec3(0.0,0.0,1.0);\n'
// compute the pixel's depth
' vec4 pos = VCPCMatrix * vertexVC;\n', fragString]).result; // Strip out the normal line -- the normal is computed as part of the depth
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Impl', '').result;
if (model.haveSeenDepthRequest) {
// special depth impl
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['if (depthRequest == 1) {', 'float computedZ = (pos.z / pos.w + 1.0) / 2.0;', 'float iz = floor(computedZ * 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;
superClass.replaceShaderValues(shaders, ren, actor);
};
publicAPI.setMapperShaderParameters = function (cellBO, ren, actor) {
if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) {
if (cellBO.getProgram().isAttributeUsed('orientMC')) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'orientMC', 12, // after X Y Z
cellBO.getCABO().getStride(), model.context.FLOAT, 3, false)) {
vtkErrorMacro("Error setting 'orientMC' in shader VAO.");
}
}
if (cellBO.getProgram().isAttributeUsed('offsetMC')) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO().getColorBO(), 'offsetMC', 0, cellBO.getCABO().getColorBOStride(), model.context.UNSIGNED_BYTE, 3, true)) {
vtkErrorMacro("Error setting 'offsetMC' in shader VAO.");
}
}
if (cellBO.getProgram().isAttributeUsed('radiusMC')) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'radiusMC', 24, // X Y Z OX OY OZ
cellBO.getCABO().getStride(), model.context.FLOAT, 1, false)) {
vtkErrorMacro("Error setting 'radiusMC' in shader VAO.");
}
}
}
superClass.setMapperShaderParameters(cellBO, ren, actor);
};
publicAPI.setCameraShaderParameters = function (cellBO, ren, actor) {
var program = cellBO.getProgram();
var cam = ren.getActiveCamera();
var keyMats = model.openGLCamera.getKeyMatrices(ren);
if (program.isUniformUsed('VCPCMatrix')) {
program.setUniformMatrix('VCPCMatrix', keyMats.vcpc);
}
if (!actor.getIsIdentity()) {
var actMats = model.openGLActor.getKeyMatrices();
if (program.isUniformUsed('MCVCMatrix')) {
var tmp4 = new Float64Array(16);
multiply(tmp4, keyMats.wcvc, actMats.mcwc);
program.setUniformMatrix('MCVCMatrix', tmp4);
}
if (program.isUniformUsed('normalMatrix')) {
var anorms = new Float64Array(9);
multiply$1(anorms, keyMats.normalMatrix, actMats.normalMatrix);
program.setUniformMatrix3x3('normalMatrix', anorms);
}
} else {
if (program.isUniformUsed('MCVCMatrix')) {
program.setUniformMatrix('MCVCMatrix', keyMats.wcvc);
}
if (program.isUniformUsed('normalMatrix')) {
program.setUniformMatrix3x3('normalMatrix', keyMats.normalMatrix);
}
}
if (program.isUniformUsed('cameraParallel')) {
cellBO.getProgram().setUniformi('cameraParallel', cam.getParallelProjection());
}
};
publicAPI.getOpenGLMode = function (rep, type) {
return model.context.TRIANGLES;
};
publicAPI.buildBufferObjects = function (ren, actor) {
var poly = model.currentInput;
if (poly === null) {
return;
}
model.renderable.mapScalars(poly, 1.0);
var c = model.renderable.getColorMapColors();
var vbo = model.primitives[model.primTypes.Tris].getCABO();
var pointData = poly.getPointData();
var points = poly.getPoints();
var numPoints = points.getNumberOfPoints();
var pointArray = points.getData();
var pointSize = 3; // x,y,z
// three more floats for orientation + 1 for radius
pointSize += 4;
var colorData = null;
var colorComponents = 0;
vbo.setColorBOStride(4);
if (!vbo.getColorBO()) {
vbo.setColorBO(vtkBufferObject.newInstance());
}
vbo.getColorBO().setOpenGLRenderWindow(model.openGLRenderWindow);
if (c) {
colorComponents = c.getNumberOfComponents();
vbo.setColorOffset(4);
colorData = c.getData();
vbo.setColorBOStride(8);
}
vbo.setColorComponents(colorComponents);
vbo.setStride(pointSize * 4); // Create a buffer, and copy the data over.
var packedVBO = new Float32Array(pointSize * numPoints * 12);
var packedUCVBO = new Uint8Array(12 * numPoints * (colorData ? 8 : 4));
var scales = null;
var orientationArray = null; //
// Generate points and point data for sides
//
if (model.renderable.getScaleArray() != null && pointData.hasArray(model.renderable.getScaleArray())) {
scales = pointData.getArray(model.renderable.getScaleArray()).getData();
}
if (model.renderable.getOrientationArray() != null && pointData.hasArray(model.renderable.getOrientationArray())) {
orientationArray = pointData.getArray(model.renderable.getOrientationArray()).getData();
} else {
vtkErrorMacro(['Error setting orientationArray.\n', 'You have to specify the stick orientation']);
} // Vertices
// 013 - 032 - 324 - 453
//
// _.4---_.5
// .-* .-*
// 2-----3
// | /|
// | / |
// | / |
// | / |
// |/ |
// 0-----1
//
// coord for each points
// 0: 000
// 1: 100
// 2: 001
// 3: 101
// 4: 011
// 5: 111
// prettier-ignore
var verticesArray = [0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4];
var pointIdx = 0;
var colorIdx = 0;
var vboIdx = 0;
var ucIdx = 0;
for (var i = 0; i < numPoints; ++i) {
var length = model.renderable.getLength();
var radius = model.renderable.getRadius();
if (scales) {
length = scales[i * 2];
radius = scales[i * 2 + 1];
}
for (var j = 0; j < verticesArray.length; ++j) {
pointIdx = i * 3;
packedVBO[vboIdx++] = pointArray[pointIdx++];
packedVBO[vboIdx++] = pointArray[pointIdx++];
packedVBO[vboIdx++] = pointArray[pointIdx++];
pointIdx = i * 3;
packedVBO[vboIdx++] = orientationArray[pointIdx++] * length;
packedVBO[vboIdx++] = orientationArray[pointIdx++] * length;
packedVBO[vboIdx++] = orientationArray[pointIdx++] * length;
packedVBO[vboIdx++] = radius;
packedUCVBO[ucIdx++] = 255 * (verticesArray[j] % 2);
packedUCVBO[ucIdx++] = verticesArray[j] >= 4 ? 255 : 0;
packedUCVBO[ucIdx++] = verticesArray[j] >= 2 ? 255 : 0;
packedUCVBO[ucIdx++] = 255;
colorIdx = i * colorComponents;
if (colorData) {
packedUCVBO[ucIdx++] = colorData[colorIdx];
packedUCVBO[ucIdx++] = colorData[colorIdx + 1];
packedUCVBO[ucIdx++] = colorData[colorIdx + 2];
packedUCVBO[ucIdx++] = colorData[colorIdx + 3];
}
}
}
vbo.setElementCount(vboIdx / pointSize);
vbo.upload(packedVBO, ObjectType.ARRAY_BUFFER);
vbo.getColorBO().upload(packedUCVBO, ObjectType.ARRAY_BUFFER);
model.VBOBuildTime.modified();
};
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
vtkOpenGLPolyDataMapper.extend(publicAPI, model, initialValues); // Object methods
vtkOpenGLStickMapper(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = newInstance$1(extend, 'vtkOpenGLStickMapper'); // ----------------------------------------------------------------------------
var vtkStickMapper = {
newInstance: newInstance,
extend: extend
}; // Register ourself to OpenGL backend if imported
registerOverride('vtkStickMapper', newInstance);
export default vtkStickMapper;
export { extend, newInstance };