@kitware/vtk.js 32.8.1 → 32.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ import { vtkAlgorithm, vtkObject } from './../../interfaces';
2
+
3
+ export interface ThresholdCriteria {
4
+ arrayName: string;
5
+ fieldAssociation: string;
6
+ operation: string;
7
+ value: number;
8
+ }
9
+
10
+ /**
11
+ *
12
+ */
13
+ export interface IThresholdPointsInitialValues {
14
+ criterias?: ThresholdCriteria[];
15
+ }
16
+
17
+ type vtkThresholdPointsBase = vtkObject & vtkAlgorithm;
18
+
19
+ export interface vtkThresholdPoints extends vtkThresholdPointsBase {
20
+ /**
21
+ * Get the desired precision for the output types.
22
+ */
23
+ getCriterias(): ThresholdCriteria[];
24
+
25
+ /**
26
+ * Set the desired precision for the output types.
27
+ * @param outputPointsPrecision
28
+ */
29
+ setCriterias(criterias: ThresholdCriteria[]): boolean;
30
+
31
+ /**
32
+ *
33
+ * @param inData
34
+ * @param outData
35
+ */
36
+ requestData(inData: any, outData: any): void;
37
+ }
38
+
39
+ /**
40
+ * Method used to decorate a given object (publicAPI+model) with vtkThresholdPoints characteristics.
41
+ *
42
+ * @param publicAPI object on which methods will be bounds (public)
43
+ * @param model object on which data structure will be bounds (protected)
44
+ * @param {IThresholdPointsInitialValues} [initialValues] (default: {})
45
+ */
46
+ export function extend(
47
+ publicAPI: object,
48
+ model: object,
49
+ initialValues?: IThresholdPointsInitialValues
50
+ ): void;
51
+
52
+ /**
53
+ * Method used to create a new instance of vtkThresholdPoints
54
+ * @param {IThresholdPointsInitialValues} [initialValues] for pre-setting some of its content
55
+ */
56
+ export function newInstance(
57
+ initialValues?: IThresholdPointsInitialValues
58
+ ): vtkThresholdPoints;
59
+
60
+ /**
61
+ * vtkThresholdPoints - extracts points whose scalar value satisfies threshold criterion
62
+ *
63
+ * vtkThresholdPoints is a filter that extracts points from a dataset that
64
+ * satisfy a threshold criterion. The criterion can take three forms:
65
+ * 1) greater than a particular value; 2) less than a particular value; or
66
+ * 3) between a particular value. The output of the filter is polygonal data.
67
+ */
68
+ export declare const vtkThresholdPoints: {
69
+ newInstance: typeof newInstance;
70
+ extend: typeof extend;
71
+ };
72
+ export default vtkThresholdPoints;
@@ -0,0 +1,219 @@
1
+ import { m as macro } from '../../macros2.js';
2
+ import vtkCellArray from '../../Common/Core/CellArray.js';
3
+ import vtkDataArray from '../../Common/Core/DataArray.js';
4
+ import vtkPoints from '../../Common/Core/Points.js';
5
+ import vtkPolyData from '../../Common/DataModel/PolyData.js';
6
+ import { POLYDATA_FIELDS } from '../../Common/DataModel/PolyData/Constants.js';
7
+
8
+ const {
9
+ vtkErrorMacro
10
+ } = macro;
11
+ const OperationType = {
12
+ Below: 'Below',
13
+ Above: 'Above'
14
+ };
15
+
16
+ // Function to perform binary search on a sorted array
17
+ function binarySearch(items, value) {
18
+ let firstIndex = 0;
19
+ let lastIndex = items.length - 1;
20
+ let middleIndex = Math.floor((lastIndex + firstIndex) / 2);
21
+ while (items[middleIndex] !== value && firstIndex < lastIndex) {
22
+ if (value < items[middleIndex]) {
23
+ lastIndex = middleIndex - 1;
24
+ } else if (value > items[middleIndex]) {
25
+ firstIndex = middleIndex + 1;
26
+ }
27
+ middleIndex = Math.floor((lastIndex + firstIndex) / 2);
28
+ }
29
+ return {
30
+ found: items[middleIndex] === value,
31
+ index: Math.max(items[middleIndex] < value ? middleIndex + 1 : middleIndex, 0)
32
+ };
33
+ }
34
+ function camelize(str) {
35
+ return str.replace(/(?:^\w|[A-Z]|\b\w)/g, letter => letter.toUpperCase()).replace(/\s+/g, '');
36
+ }
37
+ // ----------------------------------------------------------------------------
38
+ // vtkThresholdPoints methods
39
+ // ----------------------------------------------------------------------------
40
+
41
+ function vtkThresholdPoints(publicAPI, model) {
42
+ // Set our classname
43
+ model.classHierarchy.push('vtkThresholdPoints');
44
+ publicAPI.requestData = (inData, outData) => {
45
+ const input = inData[0];
46
+ const output = vtkPolyData.newInstance();
47
+ outData[0] = output;
48
+ if (model.criterias.length === 0) {
49
+ output.shallowCopy(input);
50
+ return;
51
+ }
52
+ const oldPoints = input.getPoints();
53
+ const oldPointCount = oldPoints.getNumberOfPoints();
54
+ const oldPointData = input.getPointData();
55
+ const oldPointsData = oldPoints.getData();
56
+ const newPointsData = macro.newTypedArray(input.getPoints().getDataType(), 3 * oldPointCount);
57
+ const oldArrays = [];
58
+ const newArraysData = [];
59
+ const numArrays = oldPointData.getNumberOfArrays();
60
+ for (let i = 0; i < numArrays; ++i) {
61
+ const oldArray = oldPointData.getArrayByIndex(i);
62
+ oldArrays.push(oldArray);
63
+ newArraysData.push(macro.newTypedArray(oldArray.getDataType(), oldPointCount * oldArray.getNumberOfComponents()));
64
+ }
65
+ const pointAcceptanceFunctions = model.criterias.map(criteria => {
66
+ let inputArray = null;
67
+ let component = 0;
68
+ let numberOfComponents = 1;
69
+ if (criteria.fieldAssociation === 'PointData') {
70
+ inputArray = oldArrays.find(oldArray => oldArray.getName() === criteria.arrayName);
71
+ numberOfComponents = inputArray.getNumberOfComponents();
72
+ } else if (criteria.fieldAssociation === 'Points') {
73
+ inputArray = oldPoints;
74
+ if (criteria.arrayName === 'z') {
75
+ component = 2;
76
+ } else {
77
+ component = criteria.arrayName === 'y' ? 1 : 0;
78
+ }
79
+ numberOfComponents = 3;
80
+ } else {
81
+ vtkErrorMacro('No field association');
82
+ }
83
+ const inputArrayData = inputArray.getData();
84
+ const operation = criteria.operation === OperationType.Below ? (a, b) => a < b : (a, b) => a > b;
85
+ const pointAcceptanceFunction = pointId => operation(inputArrayData[numberOfComponents * pointId + component], criteria.value);
86
+ return pointAcceptanceFunction;
87
+ });
88
+ const thresholdedPointIds = []; // sorted list
89
+ let newI = 0;
90
+ for (let i = 0; i < oldPointCount; ++i) {
91
+ const keepPoint = pointAcceptanceFunctions.reduce((keep, pointAcceptanceFunction) => keep && pointAcceptanceFunction(i), true);
92
+ if (keepPoint) {
93
+ let ii = 3 * i;
94
+ let newII = 3 * newI;
95
+ for (let c = 0; c < 3; ++c) {
96
+ newPointsData[newII++] = oldPointsData[ii++];
97
+ }
98
+ for (let j = 0; j < numArrays; ++j) {
99
+ const oldArrayData = oldArrays[j].getData();
100
+ const newArrayData = newArraysData[j];
101
+ const cc = oldArrays[j].getNumberOfComponents();
102
+ ii = cc * i;
103
+ newII = cc * newI;
104
+ for (let c = 0; c < cc; ++c) {
105
+ newArrayData[newII++] = oldArrayData[ii++];
106
+ }
107
+ }
108
+ ++newI;
109
+ } else {
110
+ thresholdedPointIds.push(i);
111
+ }
112
+ }
113
+ if (thresholdedPointIds.length === 0) {
114
+ output.shallowCopy(input);
115
+ return;
116
+ }
117
+ output.setPoints(vtkPoints.newInstance({
118
+ values: newPointsData,
119
+ size: 3 * newI
120
+ }));
121
+ for (let i = 0; i < numArrays; ++i) {
122
+ const oldArray = oldArrays[i];
123
+ const newArray = vtkDataArray.newInstance({
124
+ name: oldArray.getName(),
125
+ values: newArraysData[i],
126
+ dataType: oldArray.getDataType(),
127
+ numberOfComponents: oldArray.getNumberOfComponents(),
128
+ size: newI * oldArray.getNumberOfComponents()
129
+ });
130
+ output.getPointData().addArray(newArray);
131
+ oldPointData.getAttributes(oldArray).forEach(attrType => {
132
+ output.getPointData().setAttribute(newArray, attrType);
133
+ });
134
+ }
135
+ POLYDATA_FIELDS.forEach(cellType => {
136
+ const oldPolysData = input[`get${camelize(cellType)}`]().getData();
137
+ const newCellData = macro.newTypedArray(input.getPolys().getDataType(), oldPolysData.length);
138
+ const newPointIds = []; // first point starts at [1]
139
+ const firstPointIndex = cellType === 'verts' ? 0 : 1;
140
+ let numberOfPoints = 1;
141
+ let newP = 0;
142
+ for (let c = 0; c < oldPolysData.length; c += numberOfPoints + firstPointIndex) {
143
+ if (firstPointIndex === 1) {
144
+ // not for verts
145
+ numberOfPoints = oldPolysData[c];
146
+ }
147
+ let keepCell = true;
148
+ for (let p = firstPointIndex; p <= numberOfPoints; ++p) {
149
+ const {
150
+ found,
151
+ index
152
+ } = binarySearch(thresholdedPointIds, oldPolysData[c + p]);
153
+ if (found) {
154
+ keepCell = false;
155
+ break;
156
+ }
157
+ newPointIds[p] = oldPolysData[c + p] - index;
158
+ }
159
+ if (keepCell) {
160
+ newCellData[newP++] = numberOfPoints;
161
+ for (let p = firstPointIndex; p <= numberOfPoints;) {
162
+ newCellData[newP++] = newPointIds[p++];
163
+ }
164
+ }
165
+ }
166
+ output[`set${camelize(cellType)}`](vtkCellArray.newInstance({
167
+ values: newCellData,
168
+ size: newP,
169
+ // it may shorter than original array if cells are not kept
170
+ dataType: input.getPolys().getDataType()
171
+ }));
172
+ });
173
+ outData[0] = output;
174
+ };
175
+ }
176
+
177
+ // ----------------------------------------------------------------------------
178
+
179
+ function defaultValues(publicAPI, model) {
180
+ let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
181
+ return {
182
+ criterias: [],
183
+ // arrayName: string, fieldAssociation: string, operation: string, value: number
184
+ ...initialValues
185
+ };
186
+ }
187
+
188
+ // ----------------------------------------------------------------------------
189
+
190
+ function extend(publicAPI, model) {
191
+ let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
192
+ Object.assign(model, defaultValues(publicAPI, model, initialValues));
193
+
194
+ // Build VTK API
195
+ macro.setGet(publicAPI, model, []);
196
+ macro.get(publicAPI, model, []);
197
+ macro.setGetArray(publicAPI, model, ['criterias']);
198
+
199
+ // Make this a VTK object
200
+ macro.obj(publicAPI, model);
201
+ macro.algo(publicAPI, model, 1, 1);
202
+
203
+ // Object specific methods
204
+ vtkThresholdPoints(publicAPI, model);
205
+ }
206
+
207
+ // ----------------------------------------------------------------------------
208
+
209
+ const newInstance = macro.newInstance(extend, 'vtkThresholdPoints');
210
+
211
+ // ----------------------------------------------------------------------------
212
+
213
+ var index = {
214
+ newInstance,
215
+ extend,
216
+ OperationType
217
+ };
218
+
219
+ export { index as default, extend, newInstance };
@@ -1747,11 +1747,11 @@ function vtkCCSCutHoleyPolys(polys, points, polyGroups, polyEdges, normal) {
1747
1747
  // Do a quick search first, then do an exhaustive search.
1748
1748
  let madeCut = 0;
1749
1749
  let inner = 0;
1750
+ const cuts = [[0, 0], [0, 0]];
1750
1751
  for (let exhaustive = 0; exhaustive < 2 && !madeCut; exhaustive++) {
1751
1752
  for (let j = 1; j < polyGroup.length; j++) {
1752
1753
  inner = innerBySize[j][1];
1753
1754
  innerPolyId = polyGroup[inner];
1754
- const cuts = [];
1755
1755
  if (vtkCCSFindCuts(polys, polyGroup, outerPolyId, innerPolyId, points, normal, cuts, exhaustive)) {
1756
1756
  vtkCCSMakeCuts(polys, polyEdges, outerPolyId, innerPolyId, points, cuts);
1757
1757
  madeCut = 1;
@@ -118,15 +118,15 @@ export function newInstance(
118
118
  ): vtkDracoReader;
119
119
 
120
120
  /**
121
- *
121
+ * Get the draco decoder
122
122
  */
123
123
  export function getDracoDecoder(): any;
124
124
 
125
125
  /**
126
- *
127
- * @param createDracoModule
126
+ * Set the draco decoder
127
+ * @param dracoDecoder
128
128
  */
129
- export function setDracoDecoder(createDracoModule: any): void;
129
+ export function setDracoDecoder(dracoDecoder: any): Promise<any>;
130
130
 
131
131
  /**
132
132
  * Load the WASM decoder from url and set the decoderModule
@@ -1,8 +1,9 @@
1
- import DataAccessHelper from '../Core/DataAccessHelper.js';
2
1
  import { m as macro } from '../../macros2.js';
2
+ import DataAccessHelper from '../Core/DataAccessHelper.js';
3
3
  import vtkCellArray from '../../Common/Core/CellArray.js';
4
4
  import vtkDataArray from '../../Common/Core/DataArray.js';
5
5
  import vtkPolyData from '../../Common/DataModel/PolyData.js';
6
+ import vtkPolyDataNormals from '../../Filters/Core/PolyDataNormals.js';
6
7
  import '../Core/DataAccessHelper/LiteHttpDataAccessHelper.js';
7
8
 
8
9
  // import 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper'; // HTTP + zip
@@ -12,8 +13,7 @@ import '../Core/DataAccessHelper/LiteHttpDataAccessHelper.js';
12
13
  const {
13
14
  vtkErrorMacro
14
15
  } = macro;
15
- let decoderModule = {};
16
-
16
+ let decoderModule = null;
17
17
  // ----------------------------------------------------------------------------
18
18
  // static methods
19
19
  // ----------------------------------------------------------------------------
@@ -46,8 +46,13 @@ function setWasmBinary(url, binaryName) {
46
46
  xhr.send(null);
47
47
  });
48
48
  }
49
- function setDracoDecoder(createDracoModule) {
50
- decoderModule = createDracoModule({});
49
+
50
+ /**
51
+ * Set the Draco decoder module
52
+ * @param {*} dracoDecoder
53
+ */
54
+ async function setDracoDecoder(dracoDecoder) {
55
+ decoderModule = await dracoDecoder({});
51
56
  }
52
57
  function getDracoDecoder() {
53
58
  return decoderModule;
@@ -56,115 +61,141 @@ function getDracoDecoder() {
56
61
  // ----------------------------------------------------------------------------
57
62
  // vtkDracoReader methods
58
63
  // ----------------------------------------------------------------------------
59
-
60
- function decodeBuffer(buffer) {
61
- const byteArray = new Int8Array(buffer);
62
- const decoder = new decoderModule.Decoder();
63
- const decoderBuffer = new decoderModule.DecoderBuffer();
64
- decoderBuffer.Init(byteArray, byteArray.length);
65
- const geometryType = decoder.GetEncodedGeometryType(decoderBuffer);
66
- let dracoGeometry;
67
- if (geometryType === decoderModule.TRIANGULAR_MESH) {
68
- dracoGeometry = new decoderModule.Mesh();
69
- const status = decoder.DecodeBufferToMesh(decoderBuffer, dracoGeometry);
70
- if (!status.ok()) {
71
- vtkErrorMacro(`Could not decode Draco file: ${status.error_msg()}`);
72
- }
73
- } else {
74
- vtkErrorMacro('Wrong geometry type, expected mesh, got point cloud.');
64
+ function getDracoDataType(attributeType) {
65
+ switch (attributeType) {
66
+ case Float32Array:
67
+ return decoderModule.DT_FLOAT32;
68
+ case Int8Array:
69
+ return decoderModule.DT_INT8;
70
+ case Int16Array:
71
+ return decoderModule.DT_INT16;
72
+ case Int32Array:
73
+ return decoderModule.DT_INT32;
74
+ case Uint8Array:
75
+ return decoderModule.DT_UINT8;
76
+ case Uint16Array:
77
+ return decoderModule.DT_UINT16;
78
+ case Uint32Array:
79
+ return decoderModule.DT_UINT32;
80
+ default:
81
+ return decoderModule.DT_FLOAT32;
75
82
  }
76
- decoderModule.destroy(decoderBuffer);
77
- decoderModule.destroy(decoder);
78
- return dracoGeometry;
79
83
  }
80
- function getDracoAttributeAsFloat32Array(dracoGeometry, attributeId) {
81
- const decoder = new decoderModule.Decoder();
82
- const attribute = decoder.GetAttribute(dracoGeometry, attributeId);
83
- const numberOfComponents = attribute.num_components();
84
- const numberOfPoints = dracoGeometry.num_points();
85
- const attributeData = new decoderModule.DracoFloat32Array();
86
- decoder.GetAttributeFloatForAllPoints(dracoGeometry, attribute, attributeData);
87
- let i = numberOfPoints * numberOfComponents;
88
- const attributeArray = new Float32Array(i);
89
- while (i--) {
90
- attributeArray[i] = attributeData.GetValue(i);
91
- }
92
- return attributeArray;
84
+
85
+ /**
86
+ * Decode a single attribute
87
+ * @param {*} decoder The Draco decoder
88
+ * @param {*} dracoGeometry The geometry to decode
89
+ * @param {*} attributeName The name of the attribute
90
+ * @param {*} attributeType The type of the attribute
91
+ * @param {*} attribute The attribute to decode
92
+ * @returns object with name, array, itemSize
93
+ */
94
+ function decodeAttribute(decoder, dracoGeometry, attributeName, attributeType, attribute) {
95
+ const numComponents = attribute.num_components();
96
+ const numPoints = dracoGeometry.num_points();
97
+ const numValues = numPoints * numComponents;
98
+ const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
99
+ const dataType = getDracoDataType(attributeType);
100
+ const ptr = decoderModule._malloc(byteLength);
101
+ decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr);
102
+
103
+ // eslint-disable-next-line new-cap
104
+ const array = new attributeType(decoderModule.HEAPF32.buffer, ptr, numValues).slice();
105
+ decoderModule._free(ptr);
106
+ return {
107
+ name: attributeName,
108
+ array,
109
+ itemSize: numComponents
110
+ };
93
111
  }
94
- function getPolyDataFromDracoGeometry(dracoGeometry) {
95
- const decoder = new decoderModule.Decoder();
96
112
 
97
- // Get position attribute ID
98
- const positionAttributeId = decoder.GetAttributeId(dracoGeometry, decoderModule.POSITION);
99
- if (positionAttributeId === -1) {
100
- console.error('No position attribute found in the decoded model.');
101
- decoderModule.destroy(decoder);
102
- decoderModule.destroy(dracoGeometry);
103
- return null;
104
- }
105
- const positionArray = getDracoAttributeAsFloat32Array(dracoGeometry, positionAttributeId);
113
+ /**
114
+ * Decode the indices of the geometry
115
+ * @param {*} decoder The Draco decoder
116
+ * @param {*} dracoGeometry The geometry to decode
117
+ * @returns The indices array of the geometry
118
+ */
119
+ function decodeIndices(decoder, dracoGeometry) {
120
+ const numFaces = dracoGeometry.num_faces();
121
+ const numIndices = numFaces * 3;
122
+ const byteLength = numIndices * 4;
123
+ const ptr = decoderModule._malloc(byteLength);
124
+ decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
125
+ const indices = new Uint32Array(decoderModule.HEAPF32.buffer, ptr, numIndices).slice();
126
+ decoderModule._free(ptr);
127
+ return indices;
128
+ }
106
129
 
107
- // Read indices
108
- let i = dracoGeometry.num_faces();
109
- const indices = new Uint32Array(i * 4);
110
- const indicesArray = new decoderModule.DracoInt32Array();
111
- while (i--) {
112
- decoder.GetFaceFromMesh(dracoGeometry, i, indicesArray);
113
- const index = i * 4;
114
- indices[index] = 3;
115
- indices[index + 1] = indicesArray.GetValue(0);
116
- indices[index + 2] = indicesArray.GetValue(1);
117
- indices[index + 3] = indicesArray.GetValue(2);
130
+ /**
131
+ * Get the polyData from the Draco geometry
132
+ * @param {*} decoder The Draco decoder
133
+ * @param {*} dracoGeometry The geometry to decode
134
+ * @returns {vtkPolyData} The polyData of the geometry
135
+ */
136
+ function getPolyDataFromDracoGeometry(decoder, dracoGeometry) {
137
+ const indices = decodeIndices(decoder, dracoGeometry);
138
+ const nCells = indices.length - 2;
139
+ const cells = vtkCellArray.newInstance();
140
+ cells.resize(4 * indices.length / 3);
141
+ for (let cellId = 0; cellId < nCells; cellId += 3) {
142
+ const cell = indices.slice(cellId, cellId + 3);
143
+ cells.insertNextCell(cell);
118
144
  }
119
-
120
- // Create polyData and add positions and indinces
121
- const cellArray = vtkCellArray.newInstance({
122
- values: indices
123
- });
124
145
  const polyData = vtkPolyData.newInstance({
125
- polys: cellArray
146
+ polys: cells
126
147
  });
127
- polyData.getPoints().setData(positionArray);
128
-
129
- // Look for other attributes
130
- const pointData = polyData.getPointData();
131
148
 
132
- // Normals
133
- const normalAttributeId = decoder.GetAttributeId(dracoGeometry, decoderModule.NORMAL);
134
- if (normalAttributeId !== -1) {
135
- const normalArray = getDracoAttributeAsFloat32Array(dracoGeometry, decoderModule.NORMAL);
136
- const normals = vtkDataArray.newInstance({
137
- numberOfComponents: 3,
138
- values: normalArray,
139
- name: 'Normals'
140
- });
141
- pointData.setNormals(normals);
142
- }
143
-
144
- // Texture coordinates
145
- const texCoordAttributeId = decoder.GetAttributeId(dracoGeometry, decoderModule.TEX_COORD);
146
- if (texCoordAttributeId !== -1) {
147
- const texCoordArray = getDracoAttributeAsFloat32Array(dracoGeometry, texCoordAttributeId);
148
- const texCoords = vtkDataArray.newInstance({
149
- numberOfComponents: 2,
150
- values: texCoordArray,
151
- name: 'TCoords'
152
- });
153
- pointData.setTCoords(texCoords);
154
- }
149
+ // Look for attributes
150
+ const attributeIDs = {
151
+ points: 'POSITION',
152
+ normals: 'NORMAL',
153
+ scalars: 'COLOR',
154
+ tcoords: 'TEX_COORD'
155
+ };
156
+ Object.keys(attributeIDs).forEach(attributeName => {
157
+ const attributeType = Float32Array;
158
+ const attributeID = decoder.GetAttributeId(dracoGeometry, decoderModule[attributeIDs[attributeName]]);
159
+ if (attributeID === -1) return;
160
+ const attribute = decoder.GetAttribute(dracoGeometry, attributeID);
161
+ const attributeResult = decodeAttribute(decoder, dracoGeometry, attributeName, attributeType, attribute);
162
+ const pointData = polyData.getPointData();
163
+ switch (attributeName) {
164
+ case 'points':
165
+ polyData.getPoints().setData(attributeResult.array, attributeResult.itemSize);
166
+ break;
167
+ case 'normals':
168
+ pointData.setNormals(vtkDataArray.newInstance({
169
+ numberOfComponents: attributeResult.itemSize,
170
+ values: attributeResult.array,
171
+ name: 'Normals'
172
+ }));
173
+ break;
174
+ case 'scalars':
175
+ pointData.setScalars(vtkDataArray.newInstance({
176
+ numberOfComponents: attributeResult.itemSize,
177
+ values: attributeResult.array,
178
+ name: 'Scalars'
179
+ }));
180
+ break;
181
+ case 'tcoords':
182
+ pointData.setTCoords(vtkDataArray.newInstance({
183
+ numberOfComponents: attributeResult.itemSize,
184
+ values: attributeResult.array,
185
+ name: 'TCoords'
186
+ }));
187
+ break;
188
+ }
189
+ });
155
190
 
156
- // Scalars
157
- const colorAttributeId = decoder.GetAttributeId(dracoGeometry, decoderModule.COLOR);
158
- if (colorAttributeId !== -1) {
159
- const colorArray = getDracoAttributeAsFloat32Array(dracoGeometry, colorAttributeId);
160
- const scalars = vtkDataArray.newInstance({
161
- numberOfComponents: 3,
162
- values: colorArray,
163
- name: 'Scalars'
164
- });
165
- pointData.setScalars(scalars);
191
+ // we will generate normals if they're missing
192
+ const hasNormals = polyData.getPointData().getNormals();
193
+ if (!hasNormals) {
194
+ const pdn = vtkPolyDataNormals.newInstance();
195
+ pdn.setInputData(polyData);
196
+ pdn.setComputePointNormals(true);
197
+ return pdn.getOutputData();
166
198
  }
167
- decoderModule.destroy(decoder);
168
199
  return polyData;
169
200
  }
170
201
  function vtkDracoReader(publicAPI, model) {
@@ -235,9 +266,27 @@ function vtkDracoReader(publicAPI, model) {
235
266
  return;
236
267
  }
237
268
  model.parseData = content;
238
- const dracoGeometry = decodeBuffer(content);
239
- const polyData = getPolyDataFromDracoGeometry(dracoGeometry);
269
+ const byteArray = new Int8Array(content);
270
+ const decoder = new decoderModule.Decoder();
271
+ const buffer = new decoderModule.DecoderBuffer();
272
+ buffer.Init(byteArray, byteArray.length);
273
+ const geometryType = decoder.GetEncodedGeometryType(buffer);
274
+ let dracoGeometry;
275
+ if (geometryType === decoderModule.TRIANGULAR_MESH) {
276
+ dracoGeometry = new decoderModule.Mesh();
277
+ const status = decoder.DecodeBufferToMesh(buffer, dracoGeometry);
278
+ if (!status.ok()) {
279
+ vtkErrorMacro(`Could not decode Draco file: ${status.error_msg()}`);
280
+ return;
281
+ }
282
+ } else {
283
+ vtkErrorMacro('Wrong geometry type, expected mesh, got point cloud.');
284
+ return;
285
+ }
286
+ const polyData = getPolyDataFromDracoGeometry(decoder, dracoGeometry);
240
287
  decoderModule.destroy(dracoGeometry);
288
+ decoderModule.destroy(buffer);
289
+ decoderModule.destroy(decoder);
241
290
  model.output[0] = polyData;
242
291
  };
243
292
  publicAPI.requestData = () => {
@@ -91,7 +91,7 @@ function handleKHRLightsPunctual(extension, transformMatrix, model) {
91
91
  *
92
92
  * @param {object} extension - The KHR_draco_mesh_compression extension object.
93
93
  */
94
- async function handleKHRDracoMeshCompression(extension) {
94
+ function handleKHRDracoMeshCompression(extension) {
95
95
  const reader = vtkDracoReader.newInstance();
96
96
  reader.parse(extension.bufferView);
97
97
  return reader.getOutputData();
@@ -183,25 +183,25 @@ export interface vtkGLTFImporter extends vtkGLTFImporterBase {
183
183
 
184
184
  /**
185
185
  * Set the camera id.
186
- * @param cameraId
186
+ * @param cameraId The camera id.
187
187
  */
188
188
  setCamera(cameraId: string): void;
189
189
 
190
190
  /**
191
191
  * Set the Draco decoder.
192
- * @param mappings
192
+ * @param dracoDecoder
193
193
  */
194
- setDracoDecoder(decoder: any): void;
194
+ setDracoDecoder(dracoDecoder: any): void;
195
195
 
196
196
  /**
197
197
  * Set the vtk Renderer.
198
- * @param renderer
198
+ * @param renderer The vtk Renderer.
199
199
  */
200
200
  setRenderer(renderer: vtkRenderer): void;
201
201
 
202
202
  /**
203
203
  * Switch to a variant.
204
- * @param variantIndex
204
+ * @param variantIndex The index of the variant to switch to.
205
205
  */
206
206
  switchToVariant(variantIndex: number): void;
207
207
  }
@@ -133,8 +133,8 @@ function vtkGLTFImporter(publicAPI, model) {
133
133
  publicAPI.requestData = (inData, outData) => {
134
134
  publicAPI.parse(model.parseData);
135
135
  };
136
- publicAPI.setDracoDecoder = decoder => {
137
- vtkDracoReader.setDracoDecoder(decoder);
136
+ publicAPI.setDracoDecoder = async dracoDecoder => {
137
+ await vtkDracoReader.setDracoDecoder(dracoDecoder);
138
138
  };
139
139
  publicAPI.importActors = () => {
140
140
  // Add actors to renderer
@@ -8,6 +8,7 @@ import vtkPolyData from '../../Common/DataModel/PolyData.js';
8
8
  import vtkCellArray from '../../Common/Core/CellArray.js';
9
9
  import vtkAppendPolyData from '../../Filters/General/AppendPolyData.js';
10
10
  import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
11
+ import { mat3 } from 'gl-matrix';
11
12
 
12
13
  const {
13
14
  vtkErrorMacro
@@ -82,10 +83,12 @@ function vtkIFCImporter(publicAPI, model) {
82
83
  const colorArray = new Float32Array(vertices.length / 2);
83
84
  if (userMatrix) {
84
85
  const transformMatrix = vtkMatrixBuilder.buildFromRadian().setMatrix(userMatrix);
86
+ const normalMatrix = vtkMatrixBuilder.buildFromRadian().multiply3x3(mat3.fromMat4(mat3.create(), userMatrix));
85
87
  for (let i = 0; i < vertices.length; i += 6) {
86
88
  const point = [vertices[i], vertices[i + 1], vertices[i + 2]];
87
89
  const normal = [vertices[i + 3], vertices[i + 4], vertices[i + 5]];
88
- transformMatrix.apply(point).apply(normal);
90
+ transformMatrix.apply(point);
91
+ normalMatrix.apply(normal);
89
92
  pointValues[i / 2] = point[0];
90
93
  pointValues[i / 2 + 1] = point[1];
91
94
  pointValues[i / 2 + 2] = point[2];
@@ -199,26 +202,26 @@ function vtkIFCImporter(publicAPI, model) {
199
202
  publicAPI.importActors = renderer => {
200
203
  if (model.mergeGeometries) {
201
204
  const opaqueMeshes = meshes.filter(mesh => mesh.color.w === 1);
202
- let apd = vtkAppendPolyData.newInstance();
205
+ const oapd = vtkAppendPolyData.newInstance();
203
206
  opaqueMeshes.forEach(mesh => {
204
207
  const pd = createColoredPolyDataFromIFCMesh(mesh);
205
- apd.addInputData(pd);
208
+ oapd.addInputData(pd);
206
209
  });
207
210
  let mapper = vtkMapper.newInstance();
208
211
  mapper.setColorModeToDirectScalars();
209
- mapper.setInputConnection(apd.getOutputPort());
212
+ mapper.setInputConnection(oapd.getOutputPort());
210
213
  let actor = vtkActor.newInstance();
211
214
  actor.setMapper(mapper);
212
215
  renderer.addActor(actor);
213
216
  const transparentMeshes = meshes.filter(mesh => mesh.color.w < 1);
214
- apd = vtkAppendPolyData.newInstance();
217
+ const tapd = vtkAppendPolyData.newInstance();
215
218
  transparentMeshes.forEach(mesh => {
216
219
  const pd = createColoredPolyDataFromIFCMesh(mesh);
217
- apd.addInputData(pd);
220
+ tapd.addInputData(pd);
218
221
  });
219
222
  mapper = vtkMapper.newInstance();
220
223
  mapper.setColorModeToDirectScalars();
221
- mapper.setInputConnection(apd.getOutputPort());
224
+ mapper.setInputConnection(tapd.getOutputPort());
222
225
  actor = vtkActor.newInstance();
223
226
  actor.setMapper(mapper);
224
227
  actor.getProperty().setOpacity(0.5);
@@ -134,8 +134,10 @@ function extend(publicAPI, model) {
134
134
  Object.assign(model, DEFAULT_VALUES, initialValues);
135
135
 
136
136
  // Create internal instances
137
- model.canvas = document.createElement('canvas');
138
- model.canvas.style.width = '100%';
137
+ if (!model.canvas) {
138
+ model.canvas = document.createElement('canvas');
139
+ model.canvas.style.width = '100%';
140
+ }
139
141
 
140
142
  // Create internal bgImage
141
143
  model.bgImage = new Image();
@@ -13,21 +13,27 @@ interface IRemoteViewInitialValues {
13
13
  rpcGestureEvent?: any;
14
14
  rpcWheelEvent?: any;
15
15
  viewStream?: vtkViewStream;
16
+ canvasElement?: HTMLCanvasElement;
16
17
  }
17
18
 
18
19
  export interface vtkRemoteView extends vtkObject {
19
20
  /**
20
- * Get container element
21
+ * Get container HTML element
21
22
  */
22
23
  getContainer(): HTMLElement;
23
24
 
24
25
  /**
25
- *
26
+ * Get vtkViewStream object
26
27
  */
27
28
  getViewStream(): vtkViewStream;
28
29
 
29
30
  /**
30
- *
31
+ * Get the canvas HTML element
32
+ */
33
+ getCanvasElement(): HTMLCanvasElement;
34
+
35
+ /**
36
+ * Get the vtkCanvasView object
31
37
  */
32
38
  getCanvasView(): vtkCanvasView;
33
39
 
@@ -17,7 +17,9 @@ function vtkRemoteView(publicAPI, model) {
17
17
  model.classHierarchy.push('vtkRemoteView');
18
18
 
19
19
  // Constructor
20
- model.canvasView = vtkCanvasView.newInstance();
20
+ model.canvasView = vtkCanvasView.newInstance({
21
+ canvas: model.canvasElement
22
+ });
21
23
  model.interactorStyle = vtkInteractorStyleRemoteMouse.newInstance();
22
24
  model.interactor = vtkRenderWindowInteractor.newInstance();
23
25
  model.interactor.setView(model.canvasView);
@@ -60,6 +62,7 @@ function vtkRemoteView(publicAPI, model) {
60
62
  model.viewStream.delete();
61
63
  }
62
64
  }, publicAPI.delete);
65
+ publicAPI.getCanvasElement = () => model.canvasView.getCanvas();
63
66
 
64
67
  // --------------------------------------------------------------------------
65
68
  // remote handing
@@ -194,7 +197,8 @@ const DEFAULT_VALUES = {
194
197
  stillRatio: 1,
195
198
  rpcMouseEvent: 'viewport.mouse.interaction',
196
199
  rpcGestureEvent: null,
197
- rpcWheelEvent: null
200
+ rpcWheelEvent: null,
201
+ canvasElement: null
198
202
  };
199
203
 
200
204
  // ----------------------------------------------------------------------------
@@ -203,7 +207,7 @@ function extend(publicAPI, model) {
203
207
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
204
208
  Object.assign(model, DEFAULT_VALUES, initialValues);
205
209
  macro.obj(publicAPI, model, initialValues);
206
- macro.get(publicAPI, model, ['container', 'viewStream', 'canvasView', 'interactor', 'interactorStyle', 'interactiveQuality', 'interactiveRatio', 'stillQuality', 'stillRatio']);
210
+ macro.get(publicAPI, model, ['container', 'viewStream', 'canvasView', 'interactor', 'interactorStyle', 'interactiveQuality', 'interactiveRatio', 'stillQuality', 'stillRatio', 'canvasElement']);
207
211
  macro.setGet(publicAPI, model, ['session', 'rpcMouseEvent', 'rpcGestureEvent', 'rpcWheelEvent']);
208
212
 
209
213
  // Object methods
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Even when the EXT_texture_norm16 extension is present, linear filtering
3
+ * might not be supported for normalized fixed point textures.
4
+ *
5
+ * This is a driver bug. See https://github.com/KhronosGroup/WebGL/issues/3706
6
+ * @return {boolean}
7
+ */
8
+ function supportsNorm16Linear() {
9
+ try {
10
+ const canvasSize = 4;
11
+ const texWidth = 2;
12
+ const texHeight = 1;
13
+ const texData = new Int16Array([0, 2 ** 15 - 1]);
14
+ const pixelToCheck = [1, 1];
15
+ const canvas = document.createElement('canvas');
16
+ canvas.width = canvasSize;
17
+ canvas.height = canvasSize;
18
+ const gl = canvas.getContext('webgl2');
19
+ if (!gl) {
20
+ return false;
21
+ }
22
+ const ext = gl.getExtension('EXT_texture_norm16');
23
+ if (!ext) {
24
+ return false;
25
+ }
26
+ const vs = `#version 300 es
27
+ void main() {
28
+ gl_PointSize = ${canvasSize.toFixed(1)};
29
+ gl_Position = vec4(0, 0, 0, 1);
30
+ }
31
+ `;
32
+ const fs = `#version 300 es
33
+ precision highp float;
34
+ precision highp int;
35
+ precision highp sampler2D;
36
+
37
+ uniform sampler2D u_image;
38
+
39
+ out vec4 color;
40
+
41
+ void main() {
42
+ vec4 intColor = texture(u_image, gl_PointCoord.xy);
43
+ color = vec4(vec3(intColor.rrr), 1);
44
+ }
45
+ `;
46
+ const vertexShader = gl.createShader(gl.VERTEX_SHADER);
47
+ gl.shaderSource(vertexShader, vs);
48
+ gl.compileShader(vertexShader);
49
+ if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
50
+ return false;
51
+ }
52
+ const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
53
+ gl.shaderSource(fragmentShader, fs);
54
+ gl.compileShader(fragmentShader);
55
+ if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
56
+ return false;
57
+ }
58
+ const program = gl.createProgram();
59
+ gl.attachShader(program, vertexShader);
60
+ gl.attachShader(program, fragmentShader);
61
+ gl.linkProgram(program);
62
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
63
+ return false;
64
+ }
65
+ const tex = gl.createTexture();
66
+ gl.bindTexture(gl.TEXTURE_2D, tex);
67
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.R16_SNORM_EXT, texWidth, texHeight, 0, gl.RED, gl.SHORT, texData);
68
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
69
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
70
+ gl.useProgram(program);
71
+ gl.drawArrays(gl.POINTS, 0, 1);
72
+ const pixel = new Uint8Array(4);
73
+ gl.readPixels(pixelToCheck[0], pixelToCheck[1], 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
74
+ const [r, g, b] = pixel;
75
+ const webglLoseContext = gl.getExtension('WEBGL_lose_context');
76
+ if (webglLoseContext) {
77
+ webglLoseContext.loseContext();
78
+ }
79
+ return r === g && g === b && r !== 0;
80
+ } catch (e) {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * @type {boolean | undefined}
87
+ */
88
+ let supportsNorm16LinearCache;
89
+ function supportsNorm16LinearCached() {
90
+ // Only create a canvas+texture+shaders the first time
91
+ if (supportsNorm16LinearCache === undefined) {
92
+ supportsNorm16LinearCache = supportsNorm16Linear();
93
+ }
94
+ return supportsNorm16LinearCache;
95
+ }
96
+
97
+ export { supportsNorm16LinearCached as default };
@@ -5,6 +5,7 @@ import vtkDataArray from '../../Common/Core/DataArray.js';
5
5
  import { V as isPowerOfTwo, R as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
6
6
  import vtkViewNode from '../SceneGraph/ViewNode.js';
7
7
  import { registerOverride } from './ViewNodeFactory.js';
8
+ import supportsNorm16LinearCached from './Texture/supportsNorm16Linear.js';
8
9
 
9
10
  const {
10
11
  Wrap,
@@ -133,6 +134,12 @@ function vtkOpenGLTexture(publicAPI, model) {
133
134
  publicAPI.activate();
134
135
  }
135
136
  };
137
+ const getNorm16Ext = () => {
138
+ if ((model.minificationFilter === Filter.LINEAR || model.magnificationFilter === Filter.LINEAR) && !supportsNorm16LinearCached()) {
139
+ return undefined;
140
+ }
141
+ return model.oglNorm16Ext;
142
+ };
136
143
 
137
144
  //----------------------------------------------------------------------------
138
145
  publicAPI.destroyTexture = () => {
@@ -285,7 +292,7 @@ function vtkOpenGLTexture(publicAPI, model) {
285
292
  publicAPI.getDefaultInternalFormat = (vtktype, numComps) => {
286
293
  let result = 0;
287
294
  // try default next
288
- result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, model.oglNorm16Ext, publicAPI.useHalfFloat());
295
+ result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, getNorm16Ext(), publicAPI.useHalfFloat());
289
296
  if (result) {
290
297
  return result;
291
298
  }
@@ -364,9 +371,9 @@ function vtkOpenGLTexture(publicAPI, model) {
364
371
  return model.context.UNSIGNED_BYTE;
365
372
  // prefer norm16 since that is accurate compared to
366
373
  // half float which is not
367
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.SHORT:
374
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.SHORT:
368
375
  return model.context.SHORT;
369
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
376
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
370
377
  return model.context.UNSIGNED_SHORT;
371
378
  // use half float type
372
379
  case useHalfFloat && VtkDataTypes.SHORT:
@@ -659,7 +666,7 @@ function vtkOpenGLTexture(publicAPI, model) {
659
666
  }
660
667
  if (model._openGLRenderWindow.getWebgl2()) {
661
668
  const webGLInfo = model._openGLRenderWindow.getGLInformations();
662
- if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && model.oglNorm16Ext && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
669
+ if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && getNorm16Ext() && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
663
670
  // Cannot use texStorage with EXT_texture_norm16 textures on Mac M1 GPU.
664
671
  // No errors reported but the texture is unusable.
665
672
  return false;
@@ -717,7 +724,7 @@ function vtkOpenGLTexture(publicAPI, model) {
717
724
  if (flip) {
718
725
  model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
719
726
  }
720
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
727
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
721
728
  publicAPI.deactivate();
722
729
  return true;
723
730
  };
@@ -795,7 +802,7 @@ function vtkOpenGLTexture(publicAPI, model) {
795
802
  h /= 2;
796
803
  }
797
804
  }
798
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
805
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
799
806
  // generateMipmap must not be called here because we manually upload all levels
800
807
  // if it is called, all levels will be overwritten
801
808
 
@@ -845,7 +852,7 @@ function vtkOpenGLTexture(publicAPI, model) {
845
852
  if (model.generateMipmap) {
846
853
  model.context.generateMipmap(model.target);
847
854
  }
848
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
855
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
849
856
  publicAPI.deactivate();
850
857
  return true;
851
858
  };
@@ -895,7 +902,7 @@ function vtkOpenGLTexture(publicAPI, model) {
895
902
  if (model.generateMipmap) {
896
903
  model.context.generateMipmap(model.target);
897
904
  }
898
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, publicAPI.useHalfFloat());
905
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, getNorm16Ext(), publicAPI.useHalfFloat());
899
906
  publicAPI.deactivate();
900
907
  return true;
901
908
  };
@@ -1013,7 +1020,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1013
1020
  }
1014
1021
 
1015
1022
  // Handle SHORT data type with EXT_texture_norm16 extension
1016
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1023
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1017
1024
  for (let c = 0; c < numComps; ++c) {
1018
1025
  model.volumeInfo.scale[c] = 32767.0; // Scale to [-1, 1] range
1019
1026
  }
@@ -1022,7 +1029,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1022
1029
  }
1023
1030
 
1024
1031
  // Handle UNSIGNED_SHORT data type with EXT_texture_norm16 extension
1025
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1032
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1026
1033
  for (let c = 0; c < numComps; ++c) {
1027
1034
  model.volumeInfo.scale[c] = 65535.0; // Scale to [0, 1] range
1028
1035
  }
@@ -1112,7 +1119,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1112
1119
  if (model.generateMipmap) {
1113
1120
  model.context.generateMipmap(model.target);
1114
1121
  }
1115
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, model.oglNorm16Ext, publicAPI.useHalfFloat());
1122
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, getNorm16Ext(), publicAPI.useHalfFloat());
1116
1123
  publicAPI.deactivate();
1117
1124
  return true;
1118
1125
  };
package/index.d.ts CHANGED
@@ -54,6 +54,7 @@
54
54
  /// <reference path="./Common/DataModel/Triangle.d.ts" />
55
55
  /// <reference path="./Common/Transform/LandmarkTransform.d.ts" />
56
56
  /// <reference path="./Common/Transform/Transform.d.ts" />
57
+ /// <reference path="./Filters/Core/ThresholdPoints.d.ts" />
57
58
  /// <reference path="./Filters/General/AppendPolyData.d.ts" />
58
59
  /// <reference path="./Filters/General/ClipClosedSurface.d.ts" />
59
60
  /// <reference path="./Filters/General/ContourLoopExtraction.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "32.8.1",
3
+ "version": "32.9.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",