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