UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

414 lines (349 loc) 14.2 kB
import macro from '../../macro.js'; import vtkBufferObject from './BufferObject.js'; import { ObjectType } from './BufferObject/Constants.js'; import { Representation } from '../Core/Property/Constants.js'; import { k as equals, m as inverse, g as exactEquals } from '../../vendor/gl-matrix/esm/vec3.js'; import { p as fromRotationTranslationScale } from '../../vendor/gl-matrix/esm/mat4.js'; import { c as create } from '../../vendor/gl-matrix/esm/quat.js'; var vtkErrorMacro = macro.vtkErrorMacro; // ---------------------------------------------------------------------------- // Static functions // ---------------------------------------------------------------------------- function computeInverseShiftAndScaleMatrix(coordShift, coordScale) { var inverseScale = new Float64Array(3); inverse(inverseScale, coordScale); var matrix = new Float64Array(16); fromRotationTranslationScale(matrix, create(), coordShift, inverseScale); return matrix; } function shouldApplyCoordShiftAndScale(coordShift, coordScale) { if (coordShift === null || coordScale === null) { return false; } return !(exactEquals(coordShift, [0, 0, 0]) && exactEquals(coordScale, [1, 1, 1])); } // ---------------------------------------------------------------------------- // vtkOpenGLCellArrayBufferObject methods // ---------------------------------------------------------------------------- function vtkOpenGLCellArrayBufferObject(publicAPI, model) { // Set our className model.classHierarchy.push('vtkOpenGLCellArrayBufferObject'); publicAPI.setType(ObjectType.ARRAY_BUFFER); publicAPI.createVBO = function (cellArray, inRep, outRep, options) { if (!cellArray.getData() || !cellArray.getData().length) { model.elementCount = 0; return 0; } // Figure out how big each block will be, currently 6 or 7 floats. model.blockSize = 3; model.vertexOffset = 0; model.normalOffset = 0; model.tCoordOffset = 0; model.tCoordComponents = 0; model.colorComponents = 0; model.colorOffset = 0; model.customData = []; var pointData = options.points.getData(); var normalData = null; var tcoordData = null; var colorData = null; var colorComponents = options.colors ? options.colors.getNumberOfComponents() : 0; var textureComponents = options.tcoords ? options.tcoords.getNumberOfComponents() : 0; // the values of 4 below are because floats are 4 bytes if (options.normals) { model.normalOffset = 4 * model.blockSize; model.blockSize += 3; normalData = options.normals.getData(); } if (options.customAttributes) { options.customAttributes.forEach(function (a) { if (a) { model.customData.push({ data: a.getData(), offset: 4 * model.blockSize, components: a.getNumberOfComponents(), name: a.getName() }); model.blockSize += a.getNumberOfComponents(); } }); } if (options.tcoords) { model.tCoordOffset = 4 * model.blockSize; model.tCoordComponents = textureComponents; model.blockSize += textureComponents; tcoordData = options.tcoords.getData(); } if (options.colors) { model.colorComponents = options.colors.getNumberOfComponents(); model.colorOffset = 0; colorData = options.colors.getData(); if (!model.colorBO) { model.colorBO = vtkBufferObject.newInstance(); } model.colorBO.setOpenGLRenderWindow(model.openGLRenderWindow); } else { model.colorBO = null; } model.stride = 4 * model.blockSize; var pointIdx = 0; var normalIdx = 0; var tcoordIdx = 0; var colorIdx = 0; var custIdx = 0; var cellCount = 0; var addAPoint; var cellBuilders = { // easy, every input point becomes an output point anythingToPoints: function anythingToPoints(numPoints, cellPts, offset) { for (var i = 0; i < numPoints; ++i) { addAPoint(cellPts[offset + i]); } }, linesToWireframe: function linesToWireframe(numPoints, cellPts, offset) { // for lines we add a bunch of segments for (var i = 0; i < numPoints - 1; ++i) { addAPoint(cellPts[offset + i]); addAPoint(cellPts[offset + i + 1]); } }, polysToWireframe: function polysToWireframe(numPoints, cellPts, offset) { // for polys we add a bunch of segments and close it if (numPoints > 2) { for (var i = 0; i < numPoints; ++i) { addAPoint(cellPts[offset + i]); addAPoint(cellPts[offset + (i + 1) % numPoints]); } } }, stripsToWireframe: function stripsToWireframe(numPoints, cellPts, offset) { if (numPoints > 2) { // for strips we add a bunch of segments and close it for (var i = 0; i < numPoints - 1; ++i) { addAPoint(cellPts[offset + i]); addAPoint(cellPts[offset + i + 1]); } for (var _i = 0; _i < numPoints - 2; _i++) { addAPoint(cellPts[offset + _i]); addAPoint(cellPts[offset + _i + 2]); } } }, polysToSurface: function polysToSurface(npts, cellPts, offset) { for (var i = 0; i < npts - 2; i++) { addAPoint(cellPts[offset + 0]); addAPoint(cellPts[offset + i + 1]); addAPoint(cellPts[offset + i + 2]); } }, stripsToSurface: function stripsToSurface(npts, cellPts, offset) { for (var i = 0; i < npts - 2; i++) { addAPoint(cellPts[offset + i]); addAPoint(cellPts[offset + i + 1 + i % 2]); addAPoint(cellPts[offset + i + 1 + (i + 1) % 2]); } } }; var cellCounters = { // easy, every input point becomes an output point anythingToPoints: function anythingToPoints(numPoints, cellPts) { return numPoints; }, linesToWireframe: function linesToWireframe(numPoints, cellPts) { if (numPoints > 1) { return (numPoints - 1) * 2; } return 0; }, polysToWireframe: function polysToWireframe(numPoints, cellPts) { if (numPoints > 2) { return numPoints * 2; } return 0; }, stripsToWireframe: function stripsToWireframe(numPoints, cellPts) { if (numPoints > 2) { return numPoints * 4 - 6; } return 0; }, polysToSurface: function polysToSurface(npts, cellPts) { if (npts > 2) { return (npts - 2) * 3; } return 0; }, stripsToSurface: function stripsToSurface(npts, cellPts, offset) { if (npts > 2) { return (npts - 2) * 3; } return 0; } }; var func = null; var countFunc = null; if (outRep === Representation.POINTS || inRep === 'verts') { func = cellBuilders.anythingToPoints; countFunc = cellCounters.anythingToPoints; } else if (outRep === Representation.WIREFRAME || inRep === 'lines') { func = cellBuilders["".concat(inRep, "ToWireframe")]; countFunc = cellCounters["".concat(inRep, "ToWireframe")]; } else { func = cellBuilders["".concat(inRep, "ToSurface")]; countFunc = cellCounters["".concat(inRep, "ToSurface")]; } var array = cellArray.getData(); var size = array.length; var caboCount = 0; for (var index = 0; index < size;) { caboCount += countFunc(array[index], array); index += array[index] + 1; } var packedUCVBO = null; var packedVBO = new Float32Array(caboCount * model.blockSize); if (colorData) { packedUCVBO = new Uint8Array(caboCount * 4); } var vboidx = 0; var ucidx = 0; // Find out if shift scale should be used // Compute squares of diagonal size and distance from the origin var diagSq = 0.0; var distSq = 0.0; for (var i = 0; i < 3; ++i) { var range = options.points.getRange(i); var delta = range[1] - range[0]; diagSq += delta * delta; var distShift = 0.5 * (range[1] + range[0]); distSq += distShift * distShift; } var useShiftAndScale = diagSq > 0 && (Math.abs(distSq) / diagSq > 1.0e6 || // If data is far from the origin relative to its size Math.abs(Math.log10(diagSq)) > 3.0 || // If the size is huge when not far from the origin diagSq === 0 && distSq > 1.0e6); // If data is a point, but far from the origin if (useShiftAndScale) { // Compute shift and scale vectors var coordShift = new Float64Array(3); var coordScale = new Float64Array(3); for (var _i2 = 0; _i2 < 3; ++_i2) { var _range = options.points.getRange(_i2); var _delta = _range[1] - _range[0]; coordShift[_i2] = 0.5 * (_range[1] + _range[0]); coordScale[_i2] = _delta > 0 ? 1.0 / _delta : 1.0; } publicAPI.setCoordShiftAndScale(coordShift, coordScale); } else if (model.coordShiftAndScaleEnabled === true) { // Make sure to reset publicAPI.setCoordShiftAndScale(null, null); } addAPoint = function addAPointFunc(i) { // Vertices pointIdx = i * 3; if (!model.coordShiftAndScaleEnabled) { packedVBO[vboidx++] = pointData[pointIdx++]; packedVBO[vboidx++] = pointData[pointIdx++]; packedVBO[vboidx++] = pointData[pointIdx++]; } else { // Apply shift and scale packedVBO[vboidx++] = (pointData[pointIdx++] - model.coordShift[0]) * model.coordScale[0]; packedVBO[vboidx++] = (pointData[pointIdx++] - model.coordShift[1]) * model.coordScale[1]; packedVBO[vboidx++] = (pointData[pointIdx++] - model.coordShift[2]) * model.coordScale[2]; } if (normalData !== null) { if (options.haveCellNormals) { normalIdx = (cellCount + options.cellOffset) * 3; } else { normalIdx = i * 3; } packedVBO[vboidx++] = normalData[normalIdx++]; packedVBO[vboidx++] = normalData[normalIdx++]; packedVBO[vboidx++] = normalData[normalIdx++]; } model.customData.forEach(function (attr) { custIdx = i * attr.components; for (var j = 0; j < attr.components; ++j) { packedVBO[vboidx++] = attr.data[custIdx++]; } }); if (tcoordData !== null) { tcoordIdx = i * textureComponents; for (var j = 0; j < textureComponents; ++j) { packedVBO[vboidx++] = tcoordData[tcoordIdx++]; } } if (colorData !== null) { if (options.haveCellScalars) { colorIdx = (cellCount + options.cellOffset) * colorComponents; } else { colorIdx = i * colorComponents; } packedUCVBO[ucidx++] = colorData[colorIdx++]; packedUCVBO[ucidx++] = colorData[colorIdx++]; packedUCVBO[ucidx++] = colorData[colorIdx++]; packedUCVBO[ucidx++] = colorComponents === 4 ? colorData[colorIdx++] : 255; } }; for (var _index = 0; _index < size;) { func(array[_index], array, _index + 1); _index += array[_index] + 1; cellCount++; } model.elementCount = caboCount; publicAPI.upload(packedVBO, ObjectType.ARRAY_BUFFER); if (model.colorBO) { model.colorBOStride = 4; model.colorBO.upload(packedUCVBO, ObjectType.ARRAY_BUFFER); } return cellCount; }; publicAPI.setCoordShiftAndScale = function (coordShift, coordScale) { if (coordShift !== null && (coordShift.constructor !== Float64Array || coordShift.length !== 3)) { vtkErrorMacro('Wrong type for coordShift, expected vec3 or null'); return; } if (coordScale !== null && (coordScale.constructor !== Float64Array || coordScale.length !== 3)) { vtkErrorMacro('Wrong type for coordScale, expected vec3 or null'); return; } if (model.coordShift === null || coordShift === null || !equals(coordShift, model.coordShift)) { model.coordShift = coordShift; } if (model.coordScale === null || coordScale === null || !equals(coordScale, model.coordScale)) { model.coordScale = coordScale; } model.coordShiftAndScaleEnabled = shouldApplyCoordShiftAndScale(model.coordShift, model.coordScale); if (model.coordShiftAndScaleEnabled) { model.inverseShiftAndScaleMatrix = computeInverseShiftAndScaleMatrix(model.coordShift, model.coordScale); } else { model.inverseShiftAndScaleMatrix = null; } }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { elementCount: 0, stride: 0, colorBOStride: 0, vertexOffset: 0, normalOffset: 0, tCoordOffset: 0, tCoordComponents: 0, colorOffset: 0, colorComponents: 0, tcoordBO: null, customData: [], coordShift: null, coordScale: null, coordShiftAndScaleEnabled: false, inverseShiftAndScaleMatrix: null }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance vtkBufferObject.extend(publicAPI, model, initialValues); macro.setGet(publicAPI, model, ['colorBO', 'elementCount', 'stride', 'colorBOStride', 'vertexOffset', 'normalOffset', 'tCoordOffset', 'tCoordComponents', 'colorOffset', 'colorComponents', 'customData']); macro.get(publicAPI, model, ['coordShift', 'coordScale', 'coordShiftAndScaleEnabled', 'inverseShiftAndScaleMatrix']); // Object specific methods vtkOpenGLCellArrayBufferObject(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend); // ---------------------------------------------------------------------------- var vtkCellArrayBufferObject = { newInstance: newInstance, extend: extend }; export default vtkCellArrayBufferObject; export { extend, newInstance };