Skip to content

Commit f5cd99d

Browse files
jcfrallemangD
andcommitted
BUG: Fix Computation of Interaction Transform Used in PositionProp
This commit fixes the incorrect and unnecessary conversion from axis-angle to quaternion inadvertently introduced in 503ef1d ("ENH: Add VR interactor style class for transforming objects in MRML", 2018-08-31). The additional conversion, introduced in the mentioned commit, was redundant since the event orientations (internally set using `vtkVRRenderWindowInteractor::ConvertPoseToWorldCoordinates`, itself introduced in kitware/803d3a327d, "ENH: Use pose matrices instead of camera parameters for VR controllers", 2018-09-25) are already in quaternion format. The redundant conversion was leading to an invalid transformation of the selected object. Reported-by: Lucas Gandel <[email protected]> Co-authored-by: David Allemang <[email protected]>
1 parent 881f850 commit f5cd99d

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.cxx

+25-11
Original file line numberDiff line numberDiff line change
@@ -281,36 +281,50 @@ void vtkVirtualRealityViewInteractorStyle::PositionProp(vtkEventData* ed, double
281281
return;
282282
}
283283

284-
// Get positions and orientations
285284
vtkRenderWindowInteractor3D* rwi = static_cast<vtkRenderWindowInteractor3D*>(this->Interactor);
285+
286+
// Retrieve the last and current event positions in world coordinates
286287
double worldPos[3] = {0.0};
287288
edd->GetWorldPosition(worldPos);
288289
double* lastWorldPos = rwi->GetLastWorldEventPosition(rwi->GetPointerIndex());
290+
291+
// Retrieve the last and current event orientation quaternions
289292
double* worldOrientation = rwi->GetWorldEventOrientation(rwi->GetPointerIndex());
290293
double* lastWorldOrientation = rwi->GetLastWorldEventOrientation(rwi->GetPointerIndex());
291294

292-
// Calculate transform
293-
vtkNew<vtkTransform> interactionTransform;
294-
interactionTransform->PreMultiply();
295-
295+
// Compute the translation vector
296296
double translation[3] = {0.0};
297297
for (int i = 0; i < 3; i++)
298298
{
299299
translation[i] = worldPos[i] - lastWorldPos[i];
300300
}
301-
vtkQuaternion<double> q1;
302-
q1.SetRotationAngleAndAxis(vtkMath::RadiansFromDegrees(
303-
lastWorldOrientation[0]), lastWorldOrientation[1], lastWorldOrientation[2], lastWorldOrientation[3]);
304-
vtkQuaternion<double> q2;
305-
q2.SetRotationAngleAndAxis(vtkMath::RadiansFromDegrees(
306-
worldOrientation[0]), worldOrientation[1], worldOrientation[2], worldOrientation[3]);
301+
302+
// Calculate the relative quaternion rotation between the last and
303+
// current orientations (q2 * q1')
304+
vtkQuaternion<double> q1(lastWorldOrientation);
305+
vtkQuaternion<double> q2(worldOrientation);
307306
q1.Conjugate();
308307
q2 = q2*q1;
308+
309+
// Convert from quaternion to angle-axis representation
309310
double axis[4] = {0.0};
310311
axis[0] = vtkMath::DegreesFromRadians(q2.GetRotationAngleAndAxis(axis+1));
312+
313+
// Apply the calculated relative orientation and translation vector to the
314+
// interaction transform
315+
vtkNew<vtkTransform> interactionTransform;
316+
interactionTransform->PreMultiply();
317+
318+
// Step 1: Translate to the current world position
311319
interactionTransform->Translate(worldPos[0], worldPos[1], worldPos[2]);
320+
321+
// Step 2: Apply relative rotation
312322
interactionTransform->RotateWXYZ(axis[0], axis[1], axis[2], axis[3]);
323+
324+
// Step 3: Translate back to the origin
313325
interactionTransform->Translate(-worldPos[0], -worldPos[1], -worldPos[2]);
326+
327+
// Step 4: Final translation based on the computed translation vector
314328
interactionTransform->Translate(translation[0], translation[1], translation[2]);
315329

316330
// Make sure that the topmost parent transform is the VR interaction transform

0 commit comments

Comments
 (0)