Skip to content

Commit 6b2617c

Browse files
PaulHaxfloryst
authored andcommitted
perf(InteractorStyleManipulator): use temp mat4s to reduce garbage collection
1 parent 5523179 commit 6b2617c

File tree

1 file changed

+78
-42
lines changed
  • Sources/Interaction/Style/InteractorStyleManipulator

1 file changed

+78
-42
lines changed

Sources/Interaction/Style/InteractorStyleManipulator/index.js

Lines changed: 78 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import macro from 'vtk.js/Sources/macros';
22
import { MouseButton } from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor/Constants';
33
import vtkInteractorStyle from 'vtk.js/Sources/Rendering/Core/InteractorStyle';
4-
import { mat4, vec3, vec4 } from 'gl-matrix';
4+
import { mat4, vec3 } from 'gl-matrix';
55

66
const { vtkDebugMacro } = macro;
77
const { States } = vtkInteractorStyle;
@@ -135,45 +135,79 @@ function dollyByFactor(interactor, renderer, factor) {
135135
}
136136
}
137137

138-
function getCameraMatrix(renderer) {
138+
function getCameraMatrix(renderer, tempMatrix) {
139139
const cam = renderer.getActiveCamera();
140140
if (cam) {
141-
const M = mat4.create();
142-
mat4.copy(M, cam.getViewMatrix());
143-
return M;
141+
mat4.copy(tempMatrix, cam.getViewMatrix());
142+
return tempMatrix;
144143
}
145144
return null;
146145
}
147146

148-
function computeNewCenterOfRotation(beforeM, renderer, oldCenterOfRotation) {
149-
const cam = renderer.getActiveCamera();
150-
if (!cam || !beforeM) {
151-
return oldCenterOfRotation;
152-
}
147+
/**
148+
* Transforms a vector by the transformation delta between two matrices.
149+
*
150+
* @param {Object} tempObjects - Temporary matrices/vectors for computation
151+
* @param {mat4} beforeMatrix - Matrix before transformation
152+
* @param {mat4} afterMatrix - Matrix after transformation
153+
* @param {Array} vector - Vector to transform [x, y, z]
154+
* @returns {Array} Transformed vector [x, y, z]
155+
*/
156+
function transformVectorByTransformation(
157+
tempObjects,
158+
beforeMatrix,
159+
afterMatrix,
160+
vector
161+
) {
162+
const { matrixA, matrixB, identityMatrix, newCenter } = tempObjects;
153163

154164
// The view matrix from vtk.js is row-major, but gl-matrix expects column-major.
155165
// We need to transpose them before use.
156-
const beforeMatrix = mat4.create();
157-
mat4.transpose(beforeMatrix, beforeM);
166+
mat4.transpose(matrixA, beforeMatrix);
158167

159-
const afterMatrixRowMajor = cam.getViewMatrix();
160-
const afterMatrix = mat4.create();
161-
mat4.transpose(afterMatrix, afterMatrixRowMajor);
168+
mat4.transpose(matrixB, afterMatrix);
169+
mat4.invert(matrixB, matrixB);
162170

163-
// Now we can proceed with column-major matrices.
164-
const invAfterM = mat4.create();
165-
mat4.invert(invAfterM, afterMatrix);
171+
// Compute delta transformation matrix
172+
mat4.multiply(matrixA, matrixB, matrixA);
166173

167-
const deltaM = mat4.create();
168-
// deltaM = inv(afterM) * beforeM
169-
mat4.multiply(deltaM, invAfterM, beforeMatrix);
174+
// Apply transformation if matrix changed
175+
if (!mat4.equals(matrixA, identityMatrix)) {
176+
vec3.transformMat4(newCenter, vector, matrixA);
177+
return newCenter;
178+
}
179+
return vector;
180+
}
170181

171-
if (!mat4.equals(deltaM, mat4.identity(mat4.create()))) {
172-
const center = vec4.fromValues(...oldCenterOfRotation, 1);
173-
vec4.transformMat4(center, center, deltaM);
174-
return vec3.fromValues(center[0], center[1], center[2]);
182+
/**
183+
* Computes the new center of rotation based on camera movement.
184+
* When the camera moves (pan), the center of rotation should move
185+
* by the same transformation to maintain consistent rotation behavior.
186+
*
187+
* @param {Object} tempObjects - Temporary matrices/vectors for computation
188+
* @param {Object} renderer - VTK renderer
189+
* @param {mat4} beforeCameraMatrix - Camera view matrix before movement
190+
* @param {Array} oldCenterOfRotation - Previous center of rotation [x, y, z]
191+
* @returns {Array} New center of rotation [x, y, z]
192+
*/
193+
function computeNewCenterOfRotation(
194+
tempObjects,
195+
renderer,
196+
beforeCameraMatrix,
197+
oldCenterOfRotation
198+
) {
199+
const cam = renderer.getActiveCamera();
200+
if (!cam || !beforeCameraMatrix) {
201+
return oldCenterOfRotation;
175202
}
176-
return oldCenterOfRotation;
203+
const afterMatrixRowMajor = cam.getViewMatrix();
204+
205+
return transformVectorByTransformation(
206+
tempObjects,
207+
beforeCameraMatrix,
208+
afterMatrixRowMajor,
209+
oldCenterOfRotation
210+
);
177211
}
178212

179213
// ----------------------------------------------------------------------------
@@ -194,6 +228,15 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
194228
// Set our className
195229
model.classHierarchy.push('vtkInteractorStyleManipulator');
196230

231+
// Initialize temporary objects to reduce garbage collection
232+
const tempCameraMatrix = mat4.create();
233+
const tempComputeObjects = {
234+
matrixA: mat4.create(),
235+
matrixB: mat4.create(),
236+
identityMatrix: mat4.identity(mat4.create()),
237+
newCenter: vec3.create(),
238+
};
239+
197240
model.currentVRManipulators = new Map();
198241
model.mouseManipulators = [];
199242
model.keyboardManipulators = [];
@@ -547,7 +590,7 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
547590
model.cachedMousePosition = callData.position;
548591
if (model.currentManipulator && model.currentManipulator.onMouseMove) {
549592
const renderer = model.getRenderer(callData);
550-
const beforeM = getCameraMatrix(renderer);
593+
const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
551594

552595
model.currentManipulator.onMouseMove(
553596
model._interactor,
@@ -556,14 +599,12 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
556599
);
557600

558601
const newCenter = computeNewCenterOfRotation(
559-
beforeM,
602+
tempComputeObjects,
560603
renderer,
604+
beforeCameraMatrix,
561605
model.centerOfRotation
562606
);
563-
564-
if (!vec3.equals(model.centerOfRotation, newCenter)) {
565-
publicAPI.setCenterOfRotation(newCenter);
566-
}
607+
publicAPI.setCenterOfRotation(newCenter);
567608

568609
publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
569610
}
@@ -729,31 +770,26 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
729770
//----------------------------------------------------------------------------
730771
publicAPI.handlePan = (callData) => {
731772
const renderer = model.getRenderer(callData);
732-
const beforeM = getCameraMatrix(renderer);
773+
const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
733774

734775
let count = model.gestureManipulators.length;
735776
let actionCount = 0;
736777
while (count--) {
737778
const manipulator = model.gestureManipulators[count];
738779
if (manipulator && manipulator.isPanEnabled()) {
739-
manipulator.onPan(
740-
model._interactor,
741-
model.getRenderer(callData),
742-
callData.translation
743-
);
780+
manipulator.onPan(model._interactor, renderer, callData.translation);
744781
actionCount++;
745782
}
746783
}
747784
if (actionCount) {
748785
const newCenter = computeNewCenterOfRotation(
749-
beforeM,
786+
tempComputeObjects,
750787
renderer,
788+
beforeCameraMatrix,
751789
model.centerOfRotation
752790
);
791+
publicAPI.setCenterOfRotation(newCenter);
753792

754-
if (!vec3.equals(model.centerOfRotation, newCenter)) {
755-
publicAPI.setCenterOfRotation(newCenter);
756-
}
757793
publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
758794
}
759795
};

0 commit comments

Comments
 (0)