1
1
import macro from 'vtk.js/Sources/macros' ;
2
2
import { MouseButton } from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor/Constants' ;
3
3
import vtkInteractorStyle from 'vtk.js/Sources/Rendering/Core/InteractorStyle' ;
4
- import { mat4 , vec3 , vec4 } from 'gl-matrix' ;
4
+ import { mat4 , vec3 } from 'gl-matrix' ;
5
5
6
6
const { vtkDebugMacro } = macro ;
7
7
const { States } = vtkInteractorStyle ;
@@ -135,45 +135,79 @@ function dollyByFactor(interactor, renderer, factor) {
135
135
}
136
136
}
137
137
138
- function getCameraMatrix ( renderer ) {
138
+ function getCameraMatrix ( renderer , tempMatrix ) {
139
139
const cam = renderer . getActiveCamera ( ) ;
140
140
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 ;
144
143
}
145
144
return null ;
146
145
}
147
146
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 ;
153
163
154
164
// The view matrix from vtk.js is row-major, but gl-matrix expects column-major.
155
165
// We need to transpose them before use.
156
- const beforeMatrix = mat4 . create ( ) ;
157
- mat4 . transpose ( beforeMatrix , beforeM ) ;
166
+ mat4 . transpose ( matrixA , beforeMatrix ) ;
158
167
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 ) ;
162
170
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 ) ;
166
173
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
+ }
170
181
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 ;
175
202
}
176
- return oldCenterOfRotation ;
203
+ const afterMatrixRowMajor = cam . getViewMatrix ( ) ;
204
+
205
+ return transformVectorByTransformation (
206
+ tempObjects ,
207
+ beforeCameraMatrix ,
208
+ afterMatrixRowMajor ,
209
+ oldCenterOfRotation
210
+ ) ;
177
211
}
178
212
179
213
// ----------------------------------------------------------------------------
@@ -194,6 +228,15 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
194
228
// Set our className
195
229
model . classHierarchy . push ( 'vtkInteractorStyleManipulator' ) ;
196
230
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
+
197
240
model . currentVRManipulators = new Map ( ) ;
198
241
model . mouseManipulators = [ ] ;
199
242
model . keyboardManipulators = [ ] ;
@@ -547,7 +590,7 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
547
590
model . cachedMousePosition = callData . position ;
548
591
if ( model . currentManipulator && model . currentManipulator . onMouseMove ) {
549
592
const renderer = model . getRenderer ( callData ) ;
550
- const beforeM = getCameraMatrix ( renderer ) ;
593
+ const beforeCameraMatrix = getCameraMatrix ( renderer , tempCameraMatrix ) ;
551
594
552
595
model . currentManipulator . onMouseMove (
553
596
model . _interactor ,
@@ -556,14 +599,12 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
556
599
) ;
557
600
558
601
const newCenter = computeNewCenterOfRotation (
559
- beforeM ,
602
+ tempComputeObjects ,
560
603
renderer ,
604
+ beforeCameraMatrix ,
561
605
model . centerOfRotation
562
606
) ;
563
-
564
- if ( ! vec3 . equals ( model . centerOfRotation , newCenter ) ) {
565
- publicAPI . setCenterOfRotation ( newCenter ) ;
566
- }
607
+ publicAPI . setCenterOfRotation ( newCenter ) ;
567
608
568
609
publicAPI . invokeInteractionEvent ( INTERACTION_EVENT ) ;
569
610
}
@@ -729,31 +770,26 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
729
770
//----------------------------------------------------------------------------
730
771
publicAPI . handlePan = ( callData ) => {
731
772
const renderer = model . getRenderer ( callData ) ;
732
- const beforeM = getCameraMatrix ( renderer ) ;
773
+ const beforeCameraMatrix = getCameraMatrix ( renderer , tempCameraMatrix ) ;
733
774
734
775
let count = model . gestureManipulators . length ;
735
776
let actionCount = 0 ;
736
777
while ( count -- ) {
737
778
const manipulator = model . gestureManipulators [ count ] ;
738
779
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 ) ;
744
781
actionCount ++ ;
745
782
}
746
783
}
747
784
if ( actionCount ) {
748
785
const newCenter = computeNewCenterOfRotation (
749
- beforeM ,
786
+ tempComputeObjects ,
750
787
renderer ,
788
+ beforeCameraMatrix ,
751
789
model . centerOfRotation
752
790
) ;
791
+ publicAPI . setCenterOfRotation ( newCenter ) ;
753
792
754
- if ( ! vec3 . equals ( model . centerOfRotation , newCenter ) ) {
755
- publicAPI . setCenterOfRotation ( newCenter ) ;
756
- }
757
793
publicAPI . invokeInteractionEvent ( INTERACTION_EVENT ) ;
758
794
}
759
795
} ;
0 commit comments