After further testing...
The applyTorqueImpulse does indeed Gimbal Lock, however, I found a solution that may be useful to others.
Reverse multiplication order.
This will prevent the locking, but will reverse rotation directions if pitch exceeds -90 or 90 degrees.
Additionally, there is no slerp between rotations so the changes are rough.
Behaves as expected.
Code: Select all
btTransform transform = mRigidBody->getWorldTransform();
btQuaternion rotation = mRigidBody->getOrientation();
transform.setRotation( rotation * btQuaternion( btScalar(mAngularSpeedY), btScalar(mAngularSpeedX), btScalar(0) )); // reverse multiplication
mRigidBody->setWorldTransform( transform );
Additionally, I have found that many people have questions about how to create a camera.
I hope the following will be useful for those that really want a smooth camera using Bullet Physics.
* Sorry. No perspective or view transform given. That goes into another realm. *
Code: Select all
// Move in a direction. Should be getting orientation matrix Right, Up, and Forward.
mRigidBody->applyCentralImpulse( btVector3( impulse.x, impulse.y, impulse.z ) * mSpeed );
// Rotate using interpolated quaternions.
btTransform transform = mRigidBody->getWorldTransform();
btQuaternion qCurrent = transform.getRotation();
static btQuaternion qFinal = qCurrent;
// btVector3 diff => rotation vector (i.e. Euler)
if( diff.length2() > 0 )
{
static btVector3 rot;
rot += diff * DEGREES_TO_RADIANS;
qFinal = btQuaternion( rot.x, rot.y, rot.z );
}
// For some reason, the slerp likes to call an assert. The if statement prevents it from being called.
// clamp => clamp value to between 0 and 1 (in this case)
if( qCurrent.length2() > 0 && qFinal.length2() > 0 )
transform.setRotation( slerp( qCurrent, qFinal, clamp( deltaTime * mAngularSpeed, 0.0f, 1.0f )));
mRigidBody->setWorldTransform( transform );