@kitware/vtk.js 33.0.0 → 33.0.2
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.
|
@@ -13,7 +13,19 @@ interface IPLYReaderOptions {
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
export interface IPLYReaderInitialValues {
|
|
16
|
+
export interface IPLYReaderInitialValues {
|
|
17
|
+
/**
|
|
18
|
+
* Controls whether points are duplicated for face-texture mapping.
|
|
19
|
+
* Default is true.
|
|
20
|
+
*/
|
|
21
|
+
duplicatePointsForFaceTexture?: boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The tolerance used to determine if two points are the same.
|
|
25
|
+
* Default is 0.000001.
|
|
26
|
+
*/
|
|
27
|
+
faceTextureTolerance?: number;
|
|
28
|
+
}
|
|
17
29
|
|
|
18
30
|
type vtkPLYReaderBase = vtkObject &
|
|
19
31
|
Omit<
|
|
@@ -41,6 +53,16 @@ export interface vtkPLYReader extends vtkPLYReaderBase {
|
|
|
41
53
|
| JSZipDataAccessHelper
|
|
42
54
|
| LiteHttpDataAccessHelper;
|
|
43
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Controls whether points are duplicated for face-texture mapping.
|
|
58
|
+
*/
|
|
59
|
+
getDuplicatePointsForFaceTexture(): boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the tolerance used to determine if two points are the same.
|
|
63
|
+
*/
|
|
64
|
+
getFaceTextureTolerance(): number;
|
|
65
|
+
|
|
44
66
|
/**
|
|
45
67
|
* Get the url of the object to load.
|
|
46
68
|
*/
|
package/IO/Geometry/PLYReader.js
CHANGED
|
@@ -95,7 +95,7 @@ function parseHeader(data) {
|
|
|
95
95
|
}
|
|
96
96
|
return header;
|
|
97
97
|
}
|
|
98
|
-
function postProcess(buffer, elements) {
|
|
98
|
+
function postProcess(buffer, elements, faceTextureTolerance, duplicatePointsForFaceTexture) {
|
|
99
99
|
const vertElement = elements.find(element => element.name === 'vertex');
|
|
100
100
|
const faceElement = elements.find(element => element.name === 'face');
|
|
101
101
|
let nbVerts = 0;
|
|
@@ -106,14 +106,20 @@ function postProcess(buffer, elements) {
|
|
|
106
106
|
if (faceElement) {
|
|
107
107
|
nbFaces = faceElement.count;
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
let pointValues = new Float32Array(nbVerts * 3);
|
|
110
|
+
let colorArray = new Uint8Array(nbVerts * 3);
|
|
111
|
+
let tcoordsArray = new Float32Array(nbVerts * 2);
|
|
112
|
+
let normalsArray = new Float32Array(nbVerts * 3);
|
|
113
113
|
const hasColor = buffer.colors.length > 0;
|
|
114
114
|
const hasVertTCoords = buffer.uvs.length > 0;
|
|
115
115
|
const hasNorms = buffer.normals.length > 0;
|
|
116
116
|
const hasFaceTCoords = buffer.faceVertexUvs.length > 0;
|
|
117
|
+
|
|
118
|
+
// For duplicate point handling
|
|
119
|
+
const pointIds = new Map(); // Maps texture coords to arrays of point IDs
|
|
120
|
+
let nextPointId = nbVerts;
|
|
121
|
+
|
|
122
|
+
// Initialize base points
|
|
117
123
|
for (let vertIdx = 0; vertIdx < nbVerts; vertIdx++) {
|
|
118
124
|
let a = vertIdx * 3 + 0;
|
|
119
125
|
let b = vertIdx * 3 + 1;
|
|
@@ -131,6 +137,10 @@ function postProcess(buffer, elements) {
|
|
|
131
137
|
b = vertIdx * 2 + 1;
|
|
132
138
|
tcoordsArray[a] = buffer.uvs[a];
|
|
133
139
|
tcoordsArray[b] = buffer.uvs[b];
|
|
140
|
+
} else {
|
|
141
|
+
// Initialize with sentinel value
|
|
142
|
+
tcoordsArray[vertIdx * 2] = -1;
|
|
143
|
+
tcoordsArray[vertIdx * 2 + 1] = -1;
|
|
134
144
|
}
|
|
135
145
|
if (hasNorms) {
|
|
136
146
|
normalsArray[a] = buffer.normals[a];
|
|
@@ -138,33 +148,153 @@ function postProcess(buffer, elements) {
|
|
|
138
148
|
normalsArray[c] = buffer.normals[c];
|
|
139
149
|
}
|
|
140
150
|
}
|
|
141
|
-
|
|
151
|
+
|
|
152
|
+
// Process face texture coordinates
|
|
153
|
+
if (hasFaceTCoords && !hasVertTCoords && nbFaces > 0) {
|
|
142
154
|
// don't use array.shift, because buffer.indices will be used later
|
|
143
155
|
let idxVerts = 0;
|
|
144
156
|
let idxCoord = 0;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
if (duplicatePointsForFaceTexture) {
|
|
158
|
+
// Arrays to store duplicated point data
|
|
159
|
+
const extraPoints = [];
|
|
160
|
+
const extraColors = [];
|
|
161
|
+
const extraNormals = [];
|
|
162
|
+
const extraTCoords = [];
|
|
163
|
+
for (let faceIdx = 0; faceIdx < nbFaces; ++faceIdx) {
|
|
164
|
+
const nbFaceVerts = buffer.indices[idxVerts++];
|
|
165
|
+
const texcoords = buffer.faceVertexUvs[idxCoord++];
|
|
166
|
+
if (texcoords && nbFaceVerts * 2 === texcoords.length) {
|
|
167
|
+
for (let vertIdx = 0; vertIdx < nbFaceVerts; ++vertIdx) {
|
|
168
|
+
const vertId = buffer.indices[idxVerts + vertIdx];
|
|
169
|
+
const newTex = [texcoords[vertIdx * 2], texcoords[vertIdx * 2 + 1]];
|
|
170
|
+
const currentTex = [tcoordsArray[vertId * 2], tcoordsArray[vertId * 2 + 1]];
|
|
171
|
+
if (currentTex[0] === -1) {
|
|
172
|
+
// First time seeing texture coordinates for this vertex
|
|
173
|
+
tcoordsArray[vertId * 2] = newTex[0];
|
|
174
|
+
tcoordsArray[vertId * 2 + 1] = newTex[1];
|
|
175
|
+
const key = `${newTex[0]},${newTex[1]}`;
|
|
176
|
+
if (!pointIds.has(key)) {
|
|
177
|
+
pointIds.set(key, []);
|
|
178
|
+
}
|
|
179
|
+
pointIds.get(key).push(vertId);
|
|
180
|
+
} else {
|
|
181
|
+
// Check if we need to duplicate the vertex
|
|
182
|
+
const needsDuplication = Math.abs(currentTex[0] - newTex[0]) > faceTextureTolerance || Math.abs(currentTex[1] - newTex[1]) > faceTextureTolerance;
|
|
183
|
+
if (needsDuplication) {
|
|
184
|
+
const key = `${newTex[0]},${newTex[1]}`;
|
|
185
|
+
let existingPointId = -1;
|
|
186
|
+
|
|
187
|
+
// Check if we already have a point with these texture coordinates
|
|
188
|
+
if (pointIds.has(key)) {
|
|
189
|
+
const candidates = pointIds.get(key);
|
|
190
|
+
for (let i = 0, len = candidates.length; i < len; i++) {
|
|
191
|
+
const candidateId = candidates[i];
|
|
192
|
+
const samePosition = Math.abs(pointValues[candidateId * 3] - pointValues[vertId * 3]) <= faceTextureTolerance && Math.abs(pointValues[candidateId * 3 + 1] - pointValues[vertId * 3 + 1]) <= faceTextureTolerance && Math.abs(pointValues[candidateId * 3 + 2] - pointValues[vertId * 3 + 2]) <= faceTextureTolerance;
|
|
193
|
+
if (samePosition) {
|
|
194
|
+
existingPointId = candidateId;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (existingPointId === -1) {
|
|
200
|
+
// Create new point
|
|
201
|
+
extraPoints.push(pointValues[vertId * 3], pointValues[vertId * 3 + 1], pointValues[vertId * 3 + 2]);
|
|
202
|
+
if (hasColor) {
|
|
203
|
+
extraColors.push(colorArray[vertId * 3], colorArray[vertId * 3 + 1], colorArray[vertId * 3 + 2]);
|
|
204
|
+
}
|
|
205
|
+
if (hasNorms) {
|
|
206
|
+
extraNormals.push(normalsArray[vertId * 3], normalsArray[vertId * 3 + 1], normalsArray[vertId * 3 + 2]);
|
|
207
|
+
}
|
|
208
|
+
extraTCoords.push(newTex[0], newTex[1]);
|
|
209
|
+
if (!pointIds.has(key)) {
|
|
210
|
+
pointIds.set(key, []);
|
|
211
|
+
}
|
|
212
|
+
pointIds.get(key).push(nextPointId);
|
|
213
|
+
buffer.indices[idxVerts + vertIdx] = nextPointId;
|
|
214
|
+
nextPointId++;
|
|
215
|
+
} else {
|
|
216
|
+
buffer.indices[idxVerts + vertIdx] = existingPointId;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
155
221
|
}
|
|
156
|
-
} else {
|
|
157
222
|
idxVerts += nbFaceVerts;
|
|
158
223
|
}
|
|
224
|
+
|
|
225
|
+
// Extend arrays with duplicated points if needed
|
|
226
|
+
if (extraPoints.length > 0) {
|
|
227
|
+
const newPointCount = nbVerts + extraPoints.length / 3;
|
|
228
|
+
const newPointValues = new Float32Array(newPointCount * 3);
|
|
229
|
+
const newTcoordsArray = new Float32Array(newPointCount * 2);
|
|
230
|
+
const newColorArray = hasColor ? new Uint8Array(newPointCount * 3) : null;
|
|
231
|
+
const newNormalsArray = hasNorms ? new Float32Array(newPointCount * 3) : null;
|
|
232
|
+
|
|
233
|
+
// Copy existing data
|
|
234
|
+
newPointValues.set(pointValues);
|
|
235
|
+
newTcoordsArray.set(tcoordsArray);
|
|
236
|
+
if (hasColor && newColorArray) {
|
|
237
|
+
newColorArray.set(colorArray);
|
|
238
|
+
}
|
|
239
|
+
if (hasNorms && newNormalsArray) {
|
|
240
|
+
newNormalsArray.set(normalsArray);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Add new data
|
|
244
|
+
newPointValues.set(extraPoints, nbVerts * 3);
|
|
245
|
+
newTcoordsArray.set(extraTCoords, nbVerts * 2);
|
|
246
|
+
if (hasColor && newColorArray) {
|
|
247
|
+
newColorArray.set(extraColors, nbVerts * 3);
|
|
248
|
+
}
|
|
249
|
+
if (hasNorms && newNormalsArray) {
|
|
250
|
+
newNormalsArray.set(extraNormals, nbVerts * 3);
|
|
251
|
+
}
|
|
252
|
+
pointValues = newPointValues;
|
|
253
|
+
tcoordsArray = newTcoordsArray;
|
|
254
|
+
if (hasColor) {
|
|
255
|
+
colorArray = newColorArray;
|
|
256
|
+
}
|
|
257
|
+
if (hasNorms) {
|
|
258
|
+
normalsArray = newNormalsArray;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
for (let faceIdx = 0; faceIdx < nbFaces; ++faceIdx) {
|
|
263
|
+
const nbFaceVerts = buffer.indices[idxVerts++];
|
|
264
|
+
const texcoords = buffer.faceVertexUvs[idxCoord++];
|
|
265
|
+
if (texcoords && nbFaceVerts * 2 === texcoords.length) {
|
|
266
|
+
for (let vertIdx = 0; vertIdx < nbFaceVerts; ++vertIdx) {
|
|
267
|
+
const vert = buffer.indices[idxVerts++];
|
|
268
|
+
tcoordsArray[vert * 2] = texcoords[vertIdx * 2];
|
|
269
|
+
tcoordsArray[vert * 2 + 1] = texcoords[vertIdx * 2 + 1];
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
idxVerts += nbFaceVerts;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
159
275
|
}
|
|
160
276
|
}
|
|
161
277
|
const polydata = vtkPolyData.newInstance();
|
|
162
278
|
polydata.getPoints().setData(pointValues, 3);
|
|
279
|
+
|
|
280
|
+
// If we have faces, add them as polys
|
|
281
|
+
if (nbFaces > 0) {
|
|
282
|
+
polydata.getPolys().setData(Uint32Array.from(buffer.indices));
|
|
283
|
+
} else {
|
|
284
|
+
// Point cloud - create a vertex list containing all points
|
|
285
|
+
const verts = new Uint32Array(nbVerts * 2);
|
|
286
|
+
for (let i = 0; i < nbVerts; i++) {
|
|
287
|
+
verts[i * 2] = 1; // number of points in vertex cell (always 1)
|
|
288
|
+
verts[i * 2 + 1] = i; // point index
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
polydata.getVerts().setData(verts);
|
|
292
|
+
}
|
|
163
293
|
if (hasColor) {
|
|
164
294
|
polydata.getPointData().setScalars(vtkDataArray.newInstance({
|
|
165
295
|
numberOfComponents: 3,
|
|
166
296
|
values: colorArray,
|
|
167
|
-
name: '
|
|
297
|
+
name: 'RGB'
|
|
168
298
|
}));
|
|
169
299
|
}
|
|
170
300
|
if (hasVertTCoords || hasFaceTCoords) {
|
|
@@ -184,7 +314,6 @@ function postProcess(buffer, elements) {
|
|
|
184
314
|
values: normalsArray
|
|
185
315
|
}));
|
|
186
316
|
}
|
|
187
|
-
polydata.getPolys().setData(Uint32Array.from(buffer.indices));
|
|
188
317
|
return polydata;
|
|
189
318
|
}
|
|
190
319
|
function parseNumber(n, type) {
|
|
@@ -410,7 +539,10 @@ function vtkPLYReader(publicAPI, model) {
|
|
|
410
539
|
}
|
|
411
540
|
|
|
412
541
|
// Header
|
|
413
|
-
|
|
542
|
+
let text = content;
|
|
543
|
+
if (content instanceof ArrayBuffer) {
|
|
544
|
+
text = BinaryHelper.arrayBufferToString(content);
|
|
545
|
+
}
|
|
414
546
|
const header = parseHeader(text);
|
|
415
547
|
|
|
416
548
|
// ascii/binary detection
|
|
@@ -418,7 +550,7 @@ function vtkPLYReader(publicAPI, model) {
|
|
|
418
550
|
|
|
419
551
|
// Check if ascii format
|
|
420
552
|
if (!isBinary) {
|
|
421
|
-
publicAPI.parseAsText(
|
|
553
|
+
publicAPI.parseAsText(text);
|
|
422
554
|
return;
|
|
423
555
|
}
|
|
424
556
|
model.parseData = content;
|
|
@@ -445,7 +577,7 @@ function vtkPLYReader(publicAPI, model) {
|
|
|
445
577
|
handleElement(buffer, header.elements[elem].name, element);
|
|
446
578
|
}
|
|
447
579
|
}
|
|
448
|
-
const polydata = postProcess(buffer, header.elements);
|
|
580
|
+
const polydata = postProcess(buffer, header.elements, model.faceTextureTolerance, model.duplicatePointsForFaceTexture);
|
|
449
581
|
|
|
450
582
|
// Add new output
|
|
451
583
|
model.output[0] = polydata;
|
|
@@ -462,7 +594,10 @@ function vtkPLYReader(publicAPI, model) {
|
|
|
462
594
|
model.parseData = content;
|
|
463
595
|
|
|
464
596
|
// Header
|
|
465
|
-
|
|
597
|
+
let text = content;
|
|
598
|
+
if (content instanceof ArrayBuffer) {
|
|
599
|
+
text = BinaryHelper.arrayBufferToString(content);
|
|
600
|
+
}
|
|
466
601
|
const header = parseHeader(text);
|
|
467
602
|
|
|
468
603
|
// ascii/binary detection
|
|
@@ -504,7 +639,7 @@ function vtkPLYReader(publicAPI, model) {
|
|
|
504
639
|
idx++;
|
|
505
640
|
}
|
|
506
641
|
}
|
|
507
|
-
const polydata = postProcess(buffer, header.elements);
|
|
642
|
+
const polydata = postProcess(buffer, header.elements, model.faceTextureTolerance, model.duplicatePointsForFaceTexture);
|
|
508
643
|
|
|
509
644
|
// Add new output
|
|
510
645
|
model.output[0] = polydata;
|
|
@@ -522,6 +657,8 @@ const DEFAULT_VALUES = {
|
|
|
522
657
|
// baseURL: null,
|
|
523
658
|
// dataAccessHelper: null,
|
|
524
659
|
// url: null,
|
|
660
|
+
faceTextureTolerance: 1e-6,
|
|
661
|
+
duplicatePointsForFaceTexture: true
|
|
525
662
|
};
|
|
526
663
|
|
|
527
664
|
// ----------------------------------------------------------------------------
|
|
@@ -532,7 +669,7 @@ function extend(publicAPI, model) {
|
|
|
532
669
|
|
|
533
670
|
// Build VTK API
|
|
534
671
|
macro.obj(publicAPI, model);
|
|
535
|
-
macro.get(publicAPI, model, ['url', 'baseURL']);
|
|
672
|
+
macro.get(publicAPI, model, ['url', 'baseURL', 'duplicatePointsForFaceTexture', 'faceTextureTolerance']);
|
|
536
673
|
macro.setGet(publicAPI, model, ['dataAccessHelper']);
|
|
537
674
|
macro.algo(publicAPI, model, 0, 1);
|
|
538
675
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function computeCoordShiftAndScale(points) {
|
|
2
|
+
// Find out if shift scale should be used
|
|
3
|
+
// Compute squares of diagonal size and distance from the origin
|
|
4
|
+
let diagSq = 0.0;
|
|
5
|
+
let distSq = 0.0;
|
|
6
|
+
for (let i = 0; i < 3; ++i) {
|
|
7
|
+
const range = points.getRange(i);
|
|
8
|
+
const delta = range[1] - range[0];
|
|
9
|
+
diagSq += delta * delta;
|
|
10
|
+
const distShift = 0.5 * (range[1] + range[0]);
|
|
11
|
+
distSq += distShift * distShift;
|
|
12
|
+
}
|
|
13
|
+
const useShiftAndScale = diagSq > 0 && (Math.abs(distSq) / diagSq > 1.0e6 ||
|
|
14
|
+
// If data is far from the origin relative to its size
|
|
15
|
+
Math.abs(Math.log10(diagSq)) > 3.0 ||
|
|
16
|
+
// If the size is huge when not far from the origin
|
|
17
|
+
diagSq === 0 && distSq > 1.0e6); // If data is a point, but far from the origin
|
|
18
|
+
|
|
19
|
+
if (useShiftAndScale) {
|
|
20
|
+
// Compute shift and scale vectors
|
|
21
|
+
const coordShift = new Float64Array(3);
|
|
22
|
+
const coordScale = new Float64Array(3);
|
|
23
|
+
for (let i = 0; i < 3; ++i) {
|
|
24
|
+
const range = points.getRange(i);
|
|
25
|
+
const delta = range[1] - range[0];
|
|
26
|
+
coordShift[i] = 0.5 * (range[1] + range[0]);
|
|
27
|
+
coordScale[i] = delta > 0 ? 1.0 / delta : 1.0;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
useShiftAndScale,
|
|
31
|
+
coordShift,
|
|
32
|
+
coordScale
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
useShiftAndScale,
|
|
37
|
+
coordShift: new Float32Array([0, 0, 0]),
|
|
38
|
+
coordScale: new Float32Array([1, 1, 1])
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
var helpers = {
|
|
42
|
+
computeCoordShiftAndScale
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { computeCoordShiftAndScale, helpers as default };
|
|
@@ -3,6 +3,7 @@ import { m as macro } from '../../macros2.js';
|
|
|
3
3
|
import vtkBufferObject from './BufferObject.js';
|
|
4
4
|
import { ObjectType } from './BufferObject/Constants.js';
|
|
5
5
|
import { Representation } from '../Core/Property/Constants.js';
|
|
6
|
+
import { computeCoordShiftAndScale } from './CellArrayBufferObject/helpers.js';
|
|
6
7
|
|
|
7
8
|
const {
|
|
8
9
|
vtkErrorMacro
|
|
@@ -217,32 +218,12 @@ function vtkOpenGLCellArrayBufferObject(publicAPI, model) {
|
|
|
217
218
|
let ucidx = 0;
|
|
218
219
|
|
|
219
220
|
// Find out if shift scale should be used
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const delta = range[1] - range[0];
|
|
226
|
-
diagSq += delta * delta;
|
|
227
|
-
const distShift = 0.5 * (range[1] + range[0]);
|
|
228
|
-
distSq += distShift * distShift;
|
|
229
|
-
}
|
|
230
|
-
const useShiftAndScale = diagSq > 0 && (Math.abs(distSq) / diagSq > 1.0e6 ||
|
|
231
|
-
// If data is far from the origin relative to its size
|
|
232
|
-
Math.abs(Math.log10(diagSq)) > 3.0 ||
|
|
233
|
-
// If the size is huge when not far from the origin
|
|
234
|
-
diagSq === 0 && distSq > 1.0e6); // If data is a point, but far from the origin
|
|
235
|
-
|
|
221
|
+
const {
|
|
222
|
+
useShiftAndScale,
|
|
223
|
+
coordShift,
|
|
224
|
+
coordScale
|
|
225
|
+
} = computeCoordShiftAndScale(options.points);
|
|
236
226
|
if (useShiftAndScale) {
|
|
237
|
-
// Compute shift and scale vectors
|
|
238
|
-
const coordShift = new Float64Array(3);
|
|
239
|
-
const coordScale = new Float64Array(3);
|
|
240
|
-
for (let i = 0; i < 3; ++i) {
|
|
241
|
-
const range = options.points.getRange(i);
|
|
242
|
-
const delta = range[1] - range[0];
|
|
243
|
-
coordShift[i] = 0.5 * (range[1] + range[0]);
|
|
244
|
-
coordScale[i] = delta > 0 ? 1.0 / delta : 1.0;
|
|
245
|
-
}
|
|
246
227
|
publicAPI.setCoordShiftAndScale(coordShift, coordScale);
|
|
247
228
|
} else if (model.coordShiftAndScaleEnabled === true) {
|
|
248
229
|
// Make sure to reset
|
|
@@ -8,6 +8,7 @@ import vtkOpenGLPolyDataMapper from './PolyDataMapper.js';
|
|
|
8
8
|
import { v as vtkSphereMapperVS } from './glsl/vtkSphereMapperVS.glsl.js';
|
|
9
9
|
import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
|
|
10
10
|
import { registerOverride } from './ViewNodeFactory.js';
|
|
11
|
+
import { computeCoordShiftAndScale } from './CellArrayBufferObject/helpers.js';
|
|
11
12
|
|
|
12
13
|
const {
|
|
13
14
|
vtkErrorMacro
|
|
@@ -112,14 +113,24 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
|
|
|
112
113
|
if (program.isUniformUsed('VCPCMatrix')) {
|
|
113
114
|
program.setUniformMatrix('VCPCMatrix', keyMats.vcpc);
|
|
114
115
|
}
|
|
116
|
+
|
|
117
|
+
// mat4.create() defaults to Float32Array b/c of gl-matrix's settings.
|
|
118
|
+
// We need Float64Array to avoid loss of precision with large coordinates.
|
|
119
|
+
const tmp4 = new Float64Array(16);
|
|
115
120
|
if (program.isUniformUsed('MCVCMatrix')) {
|
|
116
121
|
if (!actor.getIsIdentity()) {
|
|
117
122
|
const actMats = model.openGLActor.getKeyMatrices();
|
|
118
|
-
const tmp4 = new Float64Array(16);
|
|
119
123
|
mat4.multiply(tmp4, keyMats.wcvc, actMats.mcwc);
|
|
124
|
+
if (cellBO.getCABO().getCoordShiftAndScaleEnabled()) {
|
|
125
|
+
mat4.multiply(tmp4, tmp4, cellBO.getCABO().getInverseShiftAndScaleMatrix());
|
|
126
|
+
}
|
|
120
127
|
program.setUniformMatrix('MCVCMatrix', tmp4);
|
|
121
128
|
} else {
|
|
122
|
-
|
|
129
|
+
mat4.copy(tmp4, keyMats.wcvc);
|
|
130
|
+
if (cellBO.getCABO().getCoordShiftAndScaleEnabled()) {
|
|
131
|
+
mat4.multiply(tmp4, tmp4, cellBO.getCABO().getInverseShiftAndScaleMatrix());
|
|
132
|
+
}
|
|
133
|
+
program.setUniformMatrix('MCVCMatrix', tmp4);
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
136
|
if (program.isUniformUsed('cameraParallel')) {
|
|
@@ -166,6 +177,14 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
|
|
|
166
177
|
const cos30 = Math.cos(radiansFromDegrees(30.0));
|
|
167
178
|
let pointIdx = 0;
|
|
168
179
|
let colorIdx = 0;
|
|
180
|
+
const {
|
|
181
|
+
useShiftAndScale,
|
|
182
|
+
coordShift,
|
|
183
|
+
coordScale
|
|
184
|
+
} = computeCoordShiftAndScale(points);
|
|
185
|
+
if (useShiftAndScale) {
|
|
186
|
+
vbo.setCoordShiftAndScale(coordShift, coordScale);
|
|
187
|
+
}
|
|
169
188
|
|
|
170
189
|
//
|
|
171
190
|
// Generate points and point data for sides
|
|
@@ -178,9 +197,12 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
|
|
|
178
197
|
radius = scales[i];
|
|
179
198
|
}
|
|
180
199
|
pointIdx = i * 3;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
200
|
+
const ptX = (pointArray[pointIdx++] - coordShift[0]) * coordScale[0];
|
|
201
|
+
const ptY = (pointArray[pointIdx++] - coordShift[1]) * coordScale[1];
|
|
202
|
+
const ptZ = (pointArray[pointIdx++] - coordShift[2]) * coordScale[2];
|
|
203
|
+
packedVBO[vboIdx++] = ptX;
|
|
204
|
+
packedVBO[vboIdx++] = ptY;
|
|
205
|
+
packedVBO[vboIdx++] = ptZ;
|
|
184
206
|
packedVBO[vboIdx++] = -2.0 * radius * cos30;
|
|
185
207
|
packedVBO[vboIdx++] = -radius;
|
|
186
208
|
if (colorData) {
|
|
@@ -190,10 +212,9 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
|
|
|
190
212
|
packedUCVBO[ucIdx++] = colorData[colorIdx + 2];
|
|
191
213
|
packedUCVBO[ucIdx++] = colorData[colorIdx + 3];
|
|
192
214
|
}
|
|
193
|
-
|
|
194
|
-
packedVBO[vboIdx++] =
|
|
195
|
-
packedVBO[vboIdx++] =
|
|
196
|
-
packedVBO[vboIdx++] = pointArray[pointIdx++];
|
|
215
|
+
packedVBO[vboIdx++] = ptX;
|
|
216
|
+
packedVBO[vboIdx++] = ptY;
|
|
217
|
+
packedVBO[vboIdx++] = ptZ;
|
|
197
218
|
packedVBO[vboIdx++] = 2.0 * radius * cos30;
|
|
198
219
|
packedVBO[vboIdx++] = -radius;
|
|
199
220
|
if (colorData) {
|
|
@@ -202,10 +223,9 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
|
|
|
202
223
|
packedUCVBO[ucIdx++] = colorData[colorIdx + 2];
|
|
203
224
|
packedUCVBO[ucIdx++] = colorData[colorIdx + 3];
|
|
204
225
|
}
|
|
205
|
-
|
|
206
|
-
packedVBO[vboIdx++] =
|
|
207
|
-
packedVBO[vboIdx++] =
|
|
208
|
-
packedVBO[vboIdx++] = pointArray[pointIdx++];
|
|
226
|
+
packedVBO[vboIdx++] = ptX;
|
|
227
|
+
packedVBO[vboIdx++] = ptY;
|
|
228
|
+
packedVBO[vboIdx++] = ptZ;
|
|
209
229
|
packedVBO[vboIdx++] = 0.0;
|
|
210
230
|
packedVBO[vboIdx++] = 2.0 * radius;
|
|
211
231
|
if (colorData) {
|