I am making a 3D space shooter game using OpenGL and Bullet Physics. I am having a hard time with the 3rd person Camera though. If you take a look at the video above you can see that the camera follows the spaceship rotating on the X axis without a problem and rotating on Z axis also without a problem when the spaceship is is oriented towards the horizon and parallel to the ground. When I roll to the right and move the spaceship up I am totally losing it from the camera. The code for my camera is as follows:

float CalculateHorizontalDistance() {
    if (!mpPlayer) return 0.f;

    return distanceFromPlayer * glm::cos(glm::radians(-UpAngle));

float CalculateVerticalDistance() {
    if (!mpPlayer) return 0.f;

    return distanceFromPlayer * glm::sin(glm::radians(-UpAngle));

void calculateCameraPosition(float horizDistance, float verticDistance)
    if (!mpPlayer) return;

    glm::vec3 playerFront = mpPlayer->GetFront();
    glm::vec3 playerPos = mpPlayer->GetPosition();

    Position = playerPos + ((-playerFront) * distanceFromPlayer);

    UpAngle = 180.f - mpPlayer->GetRoll();
    //RightAngle = -mpPlayer->GetPitch();
    RollAngle =  mpPlayer->GetYaw() - 180.f;

    //float theta = mpPlayer->GetRotationY() + angleAroundPlayer;
    //float offsetX = horizDistance * glm::sin(glm::radians(theta));
    //float offsetZ = horizDistance * glm::cos(glm::radians(theta));

    //Position.x = mpPlayer->GetPosition().x - offsetX;
    //Position.y = mpPlayer->GetPosition().y + verticDistance;
    //Position.z = mpPlayer->GetPosition().z - offsetZ;

The above code is used to calculate the position and rotation of the camera. The commented out code was used to calculate the position based on trigonometrical calculations for the x and z sides of the triangle created from the camera position to the player position. This didn't work right because I could never set the camera behind the spaceship, only the position worked well.

On the non-commented out code I use as a camera position the player position - back vector * offset. This works fine for the simple purpose that the camera is always on the back side of the spaceship. I also update pitch and roll which works almost fine and here is where I need help mostly to get this right. I also never update the yaw of the camera.

This is how I get yaw, pitch and roll from Bullet Physics rigid body of the player (spaceship):

btScalar yaw;
btScalar pitch;
btScalar roll;
body->getCenterOfMassTransform().getBasis().getEulerZYX(yaw, pitch, roll, 1);

The following code is how the orientation of the camera is calculated :

void updateCameraVectors()
    // Yaw
    glm::quat aroundY = glm::angleAxis(glm::radians(-RightAngle), glm::vec3(0, 1, 0));

    // Pitch
    glm::quat aroundX = glm::angleAxis(glm::radians(UpAngle), glm::vec3(1, 0, 0));

    // Roll
    glm::quat aroundZ = glm::angleAxis(glm::radians(RollAngle), glm::vec3(0, 0, 1));

    Orientation = aroundY * aroundX * aroundZ;

    glm::quat qF = Orientation * glm::quat(0, 0, 0, -1) * glm::conjugate(Orientation);
    Front = { qF.x, qF.y, qF.z };
    Right = glm::normalize(glm::cross(Front, WorldUp));
    Up = glm::normalize(glm::cross(Right, Front));

and lastly how the view matrix of the camera is calculated:

glm::mat4 GetViewMatrix()
    // You should know the camera move reversely relative to the user input.
    // That's the point of Graphics Camera

    glm::quat reverseOrient = glm::conjugate(Orientation);
    glm::mat4 rot = glm::mat4_cast(reverseOrient);
    glm::mat4 translation = glm::translate(glm::mat4(1.0), -Position);

    return rot * translation;

Can someone help me fix the rotational problems that I am facing? I am open to modify also the Camera Class to make it work better with Bullet's quaternions instead of the Euler's angles that I am trying to use. Any code or ideas are very welcomed. Thank you for reading through.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.