Skip to content

Commit 90c06b6

Browse files
committed
fix(SphereMapper): shift+scale for large coords
1 parent d27f4e4 commit 90c06b6

File tree

3 files changed

+87
-41
lines changed

3 files changed

+87
-41
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
export 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+
9+
const delta = range[1] - range[0];
10+
diagSq += delta * delta;
11+
12+
const distShift = 0.5 * (range[1] + range[0]);
13+
distSq += distShift * distShift;
14+
}
15+
16+
const useShiftAndScale =
17+
diagSq > 0 &&
18+
(Math.abs(distSq) / diagSq > 1.0e6 || // If data is far from the origin relative to its size
19+
Math.abs(Math.log10(diagSq)) > 3.0 || // If the size is huge when not far from the origin
20+
(diagSq === 0 && distSq > 1.0e6)); // If data is a point, but far from the origin
21+
22+
if (useShiftAndScale) {
23+
// Compute shift and scale vectors
24+
const coordShift = new Float64Array(3);
25+
const coordScale = new Float64Array(3);
26+
for (let i = 0; i < 3; ++i) {
27+
const range = points.getRange(i);
28+
const delta = range[1] - range[0];
29+
30+
coordShift[i] = 0.5 * (range[1] + range[0]);
31+
coordScale[i] = delta > 0 ? 1.0 / delta : 1.0;
32+
}
33+
34+
return { useShiftAndScale, coordShift, coordScale };
35+
}
36+
37+
return {
38+
useShiftAndScale,
39+
coordShift: new Float32Array([0, 0, 0]),
40+
coordScale: new Float32Array([1, 1, 1]),
41+
};
42+
}
43+
44+
export default { computeCoordShiftAndScale };

Sources/Rendering/OpenGL/CellArrayBufferObject/index.js

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import macro from 'vtk.js/Sources/macros';
44
import vtkBufferObject from 'vtk.js/Sources/Rendering/OpenGL/BufferObject';
55
import { ObjectType } from 'vtk.js/Sources/Rendering/OpenGL/BufferObject/Constants';
66
import { Representation } from 'vtk.js/Sources/Rendering/Core/Property/Constants';
7+
import { computeCoordShiftAndScale } from 'vtk.js/Sources/Rendering/OpenGL/CellArrayBufferObject/helpers';
78

89
const { vtkErrorMacro } = macro;
910

@@ -250,36 +251,10 @@ function vtkOpenGLCellArrayBufferObject(publicAPI, model) {
250251
let ucidx = 0;
251252

252253
// Find out if shift scale should be used
253-
// Compute squares of diagonal size and distance from the origin
254-
let diagSq = 0.0;
255-
let distSq = 0.0;
256-
for (let i = 0; i < 3; ++i) {
257-
const range = options.points.getRange(i);
258-
259-
const delta = range[1] - range[0];
260-
diagSq += delta * delta;
261-
262-
const distShift = 0.5 * (range[1] + range[0]);
263-
distSq += distShift * distShift;
264-
}
265-
266-
const useShiftAndScale =
267-
diagSq > 0 &&
268-
(Math.abs(distSq) / diagSq > 1.0e6 || // If data is far from the origin relative to its size
269-
Math.abs(Math.log10(diagSq)) > 3.0 || // If the size is huge when not far from the origin
270-
(diagSq === 0 && distSq > 1.0e6)); // If data is a point, but far from the origin
254+
const { useShiftAndScale, coordShift, coordScale } =
255+
computeCoordShiftAndScale(options.points);
271256

272257
if (useShiftAndScale) {
273-
// Compute shift and scale vectors
274-
const coordShift = new Float64Array(3);
275-
const coordScale = new Float64Array(3);
276-
for (let i = 0; i < 3; ++i) {
277-
const range = options.points.getRange(i);
278-
const delta = range[1] - range[0];
279-
280-
coordShift[i] = 0.5 * (range[1] + range[0]);
281-
coordScale[i] = delta > 0 ? 1.0 / delta : 1.0;
282-
}
283258
publicAPI.setCoordShiftAndScale(coordShift, coordScale);
284259
} else if (model.coordShiftAndScaleEnabled === true) {
285260
// Make sure to reset

Sources/Rendering/OpenGL/SphereMapper/index.js

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import vtkSphereMapperVS from 'vtk.js/Sources/Rendering/OpenGL/glsl/vtkSphereMap
1313
import vtkPolyDataFS from 'vtk.js/Sources/Rendering/OpenGL/glsl/vtkPolyDataFS.glsl';
1414

1515
import { registerOverride } from 'vtk.js/Sources/Rendering/OpenGL/ViewNodeFactory';
16+
import { computeCoordShiftAndScale } from 'vtk.js/Sources/Rendering/OpenGL/CellArrayBufferObject/helpers';
1617

1718
const { vtkErrorMacro } = macro;
1819

@@ -202,14 +203,32 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
202203
program.setUniformMatrix('VCPCMatrix', keyMats.vcpc);
203204
}
204205

206+
// mat4.create() defaults to Float32Array b/c of gl-matrix's settings.
207+
// We need Float64Array to avoid loss of precision with large coordinates.
208+
const tmp4 = new Float64Array(16);
209+
205210
if (program.isUniformUsed('MCVCMatrix')) {
206211
if (!actor.getIsIdentity()) {
207212
const actMats = model.openGLActor.getKeyMatrices();
208-
const tmp4 = new Float64Array(16);
209213
mat4.multiply(tmp4, keyMats.wcvc, actMats.mcwc);
214+
if (cellBO.getCABO().getCoordShiftAndScaleEnabled()) {
215+
mat4.multiply(
216+
tmp4,
217+
tmp4,
218+
cellBO.getCABO().getInverseShiftAndScaleMatrix()
219+
);
220+
}
210221
program.setUniformMatrix('MCVCMatrix', tmp4);
211222
} else {
212-
program.setUniformMatrix('MCVCMatrix', keyMats.wcvc);
223+
mat4.copy(tmp4, keyMats.wcvc);
224+
if (cellBO.getCABO().getCoordShiftAndScaleEnabled()) {
225+
mat4.multiply(
226+
tmp4,
227+
tmp4,
228+
cellBO.getCABO().getInverseShiftAndScaleMatrix()
229+
);
230+
}
231+
program.setUniformMatrix('MCVCMatrix', tmp4);
213232
}
214233
}
215234

@@ -275,6 +294,12 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
275294
let pointIdx = 0;
276295
let colorIdx = 0;
277296

297+
const { useShiftAndScale, coordShift, coordScale } =
298+
computeCoordShiftAndScale(points);
299+
if (useShiftAndScale) {
300+
vbo.setCoordShiftAndScale(coordShift, coordScale);
301+
}
302+
278303
//
279304
// Generate points and point data for sides
280305
//
@@ -287,9 +312,13 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
287312
}
288313

289314
pointIdx = i * 3;
290-
packedVBO[vboIdx++] = pointArray[pointIdx++];
291-
packedVBO[vboIdx++] = pointArray[pointIdx++];
292-
packedVBO[vboIdx++] = pointArray[pointIdx++];
315+
const ptX = (pointArray[pointIdx++] - coordShift[0]) * coordScale[0];
316+
const ptY = (pointArray[pointIdx++] - coordShift[1]) * coordScale[1];
317+
const ptZ = (pointArray[pointIdx++] - coordShift[2]) * coordScale[2];
318+
319+
packedVBO[vboIdx++] = ptX;
320+
packedVBO[vboIdx++] = ptY;
321+
packedVBO[vboIdx++] = ptZ;
293322
packedVBO[vboIdx++] = -2.0 * radius * cos30;
294323
packedVBO[vboIdx++] = -radius;
295324
if (colorData) {
@@ -300,10 +329,9 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
300329
packedUCVBO[ucIdx++] = colorData[colorIdx + 3];
301330
}
302331

303-
pointIdx = i * 3;
304-
packedVBO[vboIdx++] = pointArray[pointIdx++];
305-
packedVBO[vboIdx++] = pointArray[pointIdx++];
306-
packedVBO[vboIdx++] = pointArray[pointIdx++];
332+
packedVBO[vboIdx++] = ptX;
333+
packedVBO[vboIdx++] = ptY;
334+
packedVBO[vboIdx++] = ptZ;
307335
packedVBO[vboIdx++] = 2.0 * radius * cos30;
308336
packedVBO[vboIdx++] = -radius;
309337
if (colorData) {
@@ -313,10 +341,9 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
313341
packedUCVBO[ucIdx++] = colorData[colorIdx + 3];
314342
}
315343

316-
pointIdx = i * 3;
317-
packedVBO[vboIdx++] = pointArray[pointIdx++];
318-
packedVBO[vboIdx++] = pointArray[pointIdx++];
319-
packedVBO[vboIdx++] = pointArray[pointIdx++];
344+
packedVBO[vboIdx++] = ptX;
345+
packedVBO[vboIdx++] = ptY;
346+
packedVBO[vboIdx++] = ptZ;
320347
packedVBO[vboIdx++] = 0.0;
321348
packedVBO[vboIdx++] = 2.0 * radius;
322349
if (colorData) {

0 commit comments

Comments
 (0)