Skip to content

Commit 8b2131e

Browse files
PaulHaxfinetjul
authored andcommitted
fix(SphereMapper): clear stale VBO shift scale
When `useShiftAndScale` flips from true to false, the mapper previously left the VBO holding the previous frame's shift/scale state. The freshly packed VBO data then used identity coordinates while the inverse shift/scale matrix still applied -- a coordinate mismatch. Pass `null, null` to `setCoordShiftAndScale` when shift/scale is no longer needed so the VBO state is cleared.
1 parent 13014d7 commit 8b2131e

2 files changed

Lines changed: 89 additions & 3 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import test from 'tape';
2+
import testUtils from 'vtk.js/Sources/Testing/testUtils';
3+
4+
import 'vtk.js/Sources/Rendering/Misc/RenderingAPIs';
5+
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
6+
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
7+
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';
8+
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
9+
import vtkSphereMapper from 'vtk.js/Sources/Rendering/Core/SphereMapper';
10+
11+
function makePolyDataFromPoints(coords) {
12+
const polyData = vtkPolyData.newInstance();
13+
polyData.getPoints().setData(Float32Array.from(coords), 3);
14+
return polyData;
15+
}
16+
17+
function updatePoints(polyData, coords) {
18+
polyData.getPoints().setData(Float32Array.from(coords), 3);
19+
polyData.getPoints().modified();
20+
polyData.modified();
21+
}
22+
23+
function getActivePrimitiveCABOs(openGLRenderWindow, mapper) {
24+
const openGLMapper = openGLRenderWindow.getViewNodeFor(mapper);
25+
const primitives = openGLMapper.getReferenceByName('primitives');
26+
return primitives
27+
.map((primitive) => primitive.getCABO())
28+
.filter((cabo) => cabo.getElementCount() > 0);
29+
}
30+
31+
test.onlyIfWebGL(
32+
'Test vtkSphereMapper clears VBO shift/scale after shifted points',
33+
(t) => {
34+
const gc = testUtils.createGarbageCollector(t);
35+
36+
const container = document.querySelector('body');
37+
const renderWindowContainer = gc.registerDOMElement(
38+
document.createElement('div')
39+
);
40+
container.appendChild(renderWindowContainer);
41+
42+
const renderWindow = gc.registerResource(vtkRenderWindow.newInstance());
43+
const renderer = gc.registerResource(vtkRenderer.newInstance());
44+
renderWindow.addRenderer(renderer);
45+
46+
const polyData = gc.registerResource(
47+
makePolyDataFromPoints([10000000, 0, 0, 10000001, 0, 0])
48+
);
49+
const mapper = gc.registerResource(vtkSphereMapper.newInstance());
50+
const actor = gc.registerResource(vtkActor.newInstance());
51+
52+
mapper.setInputData(polyData);
53+
mapper.setScalarVisibility(false);
54+
55+
actor.setMapper(mapper);
56+
renderer.addActor(actor);
57+
58+
const openGLRenderWindow = gc.registerResource(
59+
renderWindow.newAPISpecificView()
60+
);
61+
openGLRenderWindow.setContainer(renderWindowContainer);
62+
renderWindow.addView(openGLRenderWindow);
63+
openGLRenderWindow.setSize(1, 1);
64+
65+
renderWindow.render();
66+
67+
const shiftedCABOs = getActivePrimitiveCABOs(openGLRenderWindow, mapper);
68+
t.ok(shiftedCABOs.length > 0, 'sphere VBOs were built');
69+
t.ok(
70+
shiftedCABOs.some((cabo) => cabo.getCoordShiftAndScaleEnabled()),
71+
'far points enable shift/scale on VBOs'
72+
);
73+
74+
updatePoints(polyData, [-0.5, 0, 0, 0.5, 0, 0]);
75+
renderWindow.render();
76+
77+
const unshiftedCABOs = getActivePrimitiveCABOs(openGLRenderWindow, mapper);
78+
t.ok(
79+
unshiftedCABOs.every((cabo) => !cabo.getCoordShiftAndScaleEnabled()),
80+
'VBO shift/scale is cleared once points no longer use it'
81+
);
82+
83+
gc.releaseResources();
84+
}
85+
);

Sources/Rendering/OpenGL/SphereMapper/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,10 @@ function vtkOpenGLSphereMapper(publicAPI, model) {
296296

297297
const { useShiftAndScale, coordShift, coordScale } =
298298
computeCoordShiftAndScale(points);
299-
if (useShiftAndScale) {
300-
vbo.setCoordShiftAndScale(coordShift, coordScale);
301-
}
299+
vbo.setCoordShiftAndScale(
300+
useShiftAndScale ? coordShift : null,
301+
useShiftAndScale ? coordScale : null
302+
);
302303

303304
//
304305
// Generate points and point data for sides

0 commit comments

Comments
 (0)