From 2bf37029d46f7ef71f8d14a0c36ba7a272ceb8cb Mon Sep 17 00:00:00 2001 From: Forrest Date: Thu, 31 Jul 2025 13:20:41 -0400 Subject: [PATCH] fix(Glyph3DMapper): shift+scale for large coords --- .../Rendering/OpenGL/Glyph3DMapper/index.js | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/Sources/Rendering/OpenGL/Glyph3DMapper/index.js b/Sources/Rendering/OpenGL/Glyph3DMapper/index.js index 967f13f7c03..9fb0d8b6540 100644 --- a/Sources/Rendering/OpenGL/Glyph3DMapper/index.js +++ b/Sources/Rendering/OpenGL/Glyph3DMapper/index.js @@ -7,8 +7,10 @@ import vtkHardwareSelector from 'vtk.js/Sources/Rendering/OpenGL/HardwareSelecto import vtkProperty from 'vtk.js/Sources/Rendering/Core/Property'; import vtkOpenGLPolyDataMapper from 'vtk.js/Sources/Rendering/OpenGL/PolyDataMapper'; import vtkShaderProgram from 'vtk.js/Sources/Rendering/OpenGL/ShaderProgram'; +import { computeCoordShiftAndScale } from 'vtk.js/Sources/Rendering/OpenGL/CellArrayBufferObject/helpers'; import { registerOverride } from 'vtk.js/Sources/Rendering/OpenGL/ViewNodeFactory'; +import { primTypes } from '../Helper'; const { vtkErrorMacro } = macro; const { Representation } = vtkProperty; @@ -18,6 +20,19 @@ const { PassTypes } = vtkHardwareSelector; const StartEvent = { type: 'StartEvent' }; const EndEvent = { type: 'EndEvent' }; +const MAT4_BYTE_SIZE = 64; +const MAT4_ELEMENT_COUNT = 16; + +function applyShiftScaleToMat(mat, shift, scale) { + // the translation component of a 4x4 column-major matrix + mat[12] = (mat[12] - shift[0]) * scale[0]; + mat[13] = (mat[13] - shift[1]) * scale[1]; + mat[14] = (mat[14] - shift[2]) * scale[2]; + mat[0] *= scale[0]; + mat[5] *= scale[1]; + mat[10] *= scale[2]; +} + // ---------------------------------------------------------------------------- // vtkOpenGLSphereMapper methods // ---------------------------------------------------------------------------- @@ -630,9 +645,14 @@ function vtkOpenGLGlyph3DMapper(publicAPI, model) { }; publicAPI.buildBufferObjects = (ren, actor) => { + const garray = model.renderable.getMatrixArray(); + + const pts = model.renderable.getInputData(0).getPoints(); + const { useShiftAndScale, coordShift, coordScale } = + computeCoordShiftAndScale(pts); + if (model.hardwareSupport) { // update the buffer objects if needed - const garray = model.renderable.getMatrixArray(); const narray = model.renderable.getNormalArray(); const carray = model.renderable.getColorArray(); if (!model.matrixBuffer) { @@ -645,6 +665,19 @@ function vtkOpenGLGlyph3DMapper(publicAPI, model) { model.pickBuffer = vtkBufferObject.newInstance(); model.pickBuffer.setOpenGLRenderWindow(model._openGLRenderWindow); } + + if (useShiftAndScale) { + const buf = garray.buffer; + for ( + let ptIdx = 0; + ptIdx < garray.byteLength; + ptIdx += MAT4_BYTE_SIZE + ) { + const mat = new Float32Array(buf, ptIdx, MAT4_ELEMENT_COUNT); + applyShiftScaleToMat(mat, coordShift, coordScale); + } + } + if ( model.renderable.getBuildTime().getMTime() > model.glyphBOBuildTime.getMTime() @@ -674,7 +707,18 @@ function vtkOpenGLGlyph3DMapper(publicAPI, model) { model.glyphBOBuildTime.modified(); } } - return superClass.buildBufferObjects(ren, actor); + + superClass.buildBufferObjects(ren, actor); + + // apply shift + scale to primitives AFTER vtkOpenGLPolyDataMapper.buildBufferObjects + // so that the Glyph3DMapper gets the last say in the shift + scale + if (useShiftAndScale) { + for (let i = primTypes.Start; i < primTypes.End; i++) { + model.primitives[i] + .getCABO() + .setCoordShiftAndScale(coordShift, coordScale); + } + } }; }