Search code examples
c++camerarotationconstraintsbulletphysics

Clamp rotatation angle of a rigid body


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?


Solution

  • 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.