I recently attached a rigid body to the camera in my 3d game, so that it can collide with the environment. By now mouse movement directly rotates the rigid body.
#include <BULLET/btBulletDynamicsCommon.h>
void Rotate(float Pitch, float Yaw, float Roll, float Speed)
{
// get current rotation
btTransform transform = body->getWorldTransform();
btQuaternion rotation = transform.getRotation();
// create orientation vectors
btVector3 up(0, 1, 0);
btVector3 lookat = quatRotate(rotation, btVector3(0, 0, 1));
btVector3 forward = btVector3(lookat.getX(), 0, lookat.getZ()).normalize();
btVector3 side = btCross(up, forward);
// rotate camera with quaternions created from axis and angle
rotation = btQuaternion(up, Amount.getY()) * rotation;
rotation = btQuaternion(side, Amount.getX()) * rotation;
rotation = btQuaternion(forward, Amount.getZ()) * rotation;
// set new rotation
transform.setRotation(rotation);
body->setWorldTransform(transform);
}
I would like to clamp the pitch of the camera in the range of -80°
to 80°
. That helps the player to stay oriented. Otherwise he would be able to rotate the camera higher over his head and see the world behind himself upside down. In contrast a real person trying this would break his neck.
I let Bullet Physics store rotations for me in quaternions, thus pitch isn't stored directly. How can I clamp the pitch of a rigid body?
I came up with a solution. Instead of clamping the rotation of the camera's rigid body, I clamp how much rotation is applied before. Therefore, I keep track of the total vertical mouse movement. Actually, I store the overall mouse movement with applied sensitivity.
float Overallpitch = 0.0f;
If applying the passed yaw value would result in the overall pitch to exceed or deceed a given limit, I just apply as much of it as needed to touch the limit.
#include <BULLET/btBulletDynamicsCommon.h>
void Rotate(float Pitch, float Yaw, float Roll, float Sensitivity)
{
// apply mouse sensitivity
Yaw *= Sensitivity;
Pitch *= Sensitivity;
Roll *= Sensitivity;
// clamp camera pitch
const float clamp = 1.0f;
if (Overallpitch + Pitch > clamp) Pitch = clamp - Overallpitch;
else if(Overallpitch + Pitch < -clamp) Pitch = -clamp - Overallpitch;
Overallpitch += Pitch;
// apply rotation to camera quaternion
// ...
}
You can find the further camera code in another answer to my own question.