We have a view that inspects components and enables the user to rotate them on two axes, yaw and pitch. The axis inputs are from keys or buttons. Everything works as expected but it is getting gimbal lock sometimes.
Any suggestions on converting this to use quaternions? Should be straightforward but I never use them.
// get component rotation and add yaw if (_axisInputRight != 0) // axis input is -1, 0, or 1 { FRotator newRotation = _sceneComponent->GetComponentRotation(); newRotation.Yaw += _axisInputRight * ROTATION_RATE * deltaTime; newRotation.Normalize(); _sceneComponent->SetWorldRotation(newRotation); }
if (FMath::Abs(_axisInputRight) > 0.01)
{
auto oldQuat = _sceneComponent->GetComponentQuat();
auto newQuat = ( _axisInputRight * deltaTime * ROTATION_RATE ) * FRotator(.0f, 1.0f, .0f).Quaternion();
_sceneComponent->SetWorldRotation(newQuat * oldQuat);
}
Note that you can use AddWorldRotation() instead of SetWorldRotation()which will simplify things. Also both AddWorldRotation() and SetWorldRotation() have a template variant that takes FRotator so if you you are not going to do some interpolation or heavy math with those, going for FQuat is pointless and your code will become this:
if (FMath::Abs(_axisInputRight) > 0.01)
{
auto yaw = _axisInputRight * deltaTime * ROTATION_RATE;
_sceneComponent->AddWorldRotation(FRotator(.0f, yaw, .0f));
}
(Both are not tested so please excuse me if I made some mistakes.)