Question

I've been trying to emulate gluLookAt functionality, but with Quaternions. Each of my game object have a TranslationComponent. This component stores the object's position (glm::vec3), rotation (glm::quat) and scale (glm::vec3). The camera calculates its position each tick doing the following:

// UP = glm::vec3(0,1,0); 
//FORWARD = glm::vec3(0,0,1);
cameraPosition = playerPosition - (UP * distanceUP) - (FORWARD * distanceAway);

This position code works as expexted, the camera is place 3 metres behind the player and 1 metre up. Now, the camera's Quaternion is set to the follow:

//Looking at the player's feet  
cameraRotation = quatFromToRotation(FORWARD, playerPosition); 

The rendering engine now takes these values and generates the ViewMatrix (camera) and the ModelMatrix (player) and then renders the scene. The code looks like this:

 glm::mat4 viewTranslationMatrix = 
         glm::translate(glm::mat4(1.0f), cameraTransform->getPosition());
 glm::mat4 viewScaleMatrix = 
         glm::scale(glm::mat4(1.0f), cameraTransform->getScale());
 glm::mat4 viewRotationMatrix = 
         glm::mat4_cast(cameraTransform->getRotation());

 viewMatrix = viewTranslationMatrix * viewRotationMatrix * viewScaleMatrix;

quatFromToRotation(glm::vec3 from, glm::vec3 to) is defined as the following:

glm::quat quatFromToRotation(glm::vec3 from, glm::vec3 to)
{
    from = glm::normalize(from); to = glm::normalize(to);

    float cosTheta = glm::dot(from, to);
    glm::vec3 rotationAxis;

    if (cosTheta < -1 + 0.001f)
    {
        rotationAxis = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), from);
        if (glm::length2(rotationAxis) < 0.01f)
            rotationAxis = glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), from);

        rotationAxis = glm::normalize(rotationAxis);
        return glm::angleAxis(180.0f, rotationAxis);
    }

    rotationAxis = glm::cross(from, to);

    float s = sqrt((1.0f + cosTheta) * 2.0f);
    float invis = 1.0f / s;

    return glm::quat(
            s * 0.5f,
            rotationAxis.x * invis,
            rotationAxis.y * invis,
            rotationAxis.z * invis
        );
}

What I'm having troubles with is the fact the cameraRotation isn't being set correctly. No matter where the player is, the camera's forward is always (0,0,-1)

Was it helpful?

Solution

Your problem is in the line

//Looking at the player's feet  
cameraRotation = quatToFromRotation(FORWARD, playerPosition);

You need to look from the camera position to the player's feet - not from "one meter above the player" (assuming the player is at (0,0,0) when you initially do this). Replace FORWARD with cameraPosition:

cameraRotation = quatToFromRotation(cameraPosition, playerPosition);

EDIT I believe you have an error in your quatToFromRotation function as well. See https://stackoverflow.com/a/11741520/1967396 for a very nice explanation (and some pseudo code) of quaternion rotation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top