简体   繁体   中英

Calculating The Camera View Matrix

I have an issue where my camera seems to orbit the origin. It makes me think that I have my matrix multiplication backwards. However it seems correct to me, and if I reverse it it sorts out the orbit issue, but I get an other issue where I think my translation is backwards.

glm::mat4 Camera::updateDelta(const float *positionVec3, const float *rotationVec3)
{
    // Rotation Axis
    const glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
    const glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
    const glm::vec3 zAxis(0.0f, 0.0f, 1.0f); // Should this be -1?

    // Accumulate Rotations
    m_rotation.x += rotationVec3[0]; // pitch
    m_rotation.y += rotationVec3[1]; // yaw
    m_rotation.z += rotationVec3[2]; // roll

    // Calculate Rotation
    glm::mat4 rotViewMat;
    rotViewMat = glm::rotate(rotViewMat, m_rotation.x, xAxis);
    rotViewMat = glm::rotate(rotViewMat, m_rotation.y, yAxis);
    rotViewMat = glm::rotate(rotViewMat, m_rotation.z, zAxis);

    // Updated direction vectors
    m_forward = glm::vec3(rotViewMat[0][2], rotViewMat[1][2], rotViewMat[2][2]);
    m_up      = glm::vec3(rotViewMat[0][1], rotViewMat[1][1], rotViewMat[2][1]);
    m_right   = glm::vec3(rotViewMat[0][0], rotViewMat[1][0], rotViewMat[2][0]);

    m_forward = glm::normalize(m_forward);
    m_up      = glm::normalize(m_up);
    m_right   = glm::normalize(m_right);

    // Calculate Position
    m_position += (m_forward * positionVec3[2]);
    m_position += (m_up * positionVec3[1]);
    m_position += (m_right * positionVec3[0]);

    m_position += glm::vec3(positionVec3[0], positionVec3[1], positionVec3[2]);

    glm::mat4 translateViewMat;
    translateViewMat = glm::translate(translateViewMat, m_position);

    // Calculate view matrix.
    //m_viewMat = rotViewMat * translateViewMat;
    m_viewMat = translateViewMat * rotViewMat;

    // Return View Proj
    return m_projMat * m_viewMat;
}

Everywhere else I do the matrix multiplication in reverse which gives me the correct answer, but this function seems to want the reverse.

When calculating an objects position in 3D space I do this

m_worldMat = transMat * rotMat * scale;

Which works as expected.

There seem to be a few wrong things with the code.

One: rotViewMat is used in the first rotate call before it is initialized. What value does it get initially? Is it a unit matrix?

Two: Rotation does not have the mathematical properties you seem to assume. Rotating around x, then around y, then around z (each at a constant velocity) is not the same as rotating around any axis ("orbiting"), it is a weird wobble. Because of subsequent rotations, your accumulated x rotation ("pitch") for example may actually be causing a movement in an entirely different direction (consider what happens to x when the accumulated y rotation is close to 90 deg). Another way of saying that is rotation is non-commutative, see: https://physics.stackexchange.com/questions/48345/non-commutative-property-of-rotation and https://physics.stackexchange.com/questions/10362/how-does-non-commutativity-lead-to-uncertainty/10368#10368 .

See also: http://en.wikipedia.org/wiki/Rotation_matrix#Sequential_angles and http://en.wikipedia.org/wiki/Euler_angles . Since Euler angles (roll-pitch-yaw) are not vectors, it doesn't make sense to add to them a velocity vector.

What you probably want is this:

glm::mat4 Camera::updateDelta(const float *positionVec3, const float *axisVec3, const float angularVelocity)
{
...
    glm::mat4 rotViewMat; // initialize to unit matrix
    rotViewMat = glm::rotate(rotViewMat, angularVelocity, axisVec3);
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM