2
\$\begingroup\$

I'm trying to improve my Camera. This camera owns a target (vec3 _at), a position (vec3 _eye) and a view mat4. When I move the mouse, I perform a rotation to the view matrix, according to 2 angles (_angleY, _angleZ), so that it gives the feeling the world is turning and not the cam.

Here is what I have, which works :

// Called each frame
void Camera::look(bool rotation)
{
    // Computes view Matrix
    _view.lookAt(_eye.X,_eye.Y,_eye.Z,
                 _at.X, _at.Y, _at.Z,
                 0, 0, 1);

    // Apply rotation to the matrix, according to angles
    if(rotation) {
        _view.rotate(_angleY, 0, 1, 0, _at);
        _view.rotate(_angleZ, 0, 0, 1, _at);
    }
}

This perfectly works. I'm able to make my world rotating around a selected target (vec3). My problem is that my eye position is not updated each frame since I update my angles which apply a new rotation. Then my eye position is wrong and I need it to be updated each frame for another calculation.

Then, I'm trying to extract the eye position after the rotation, update it, and set angles to 0 (hoping it's the best solution...)

Therefore, I need to extract the eye position of my camera, from my modelview matrix. Here is what I'm trying to do, according to what I read here , in the last comment :

void Camera::look(bool rotation)
{
    // Computes view Matrix
    _view.lookAt(_eye.X,_eye.Y,_eye.Z,
                 _at.X, _at.Y, _at.Z,
                 0, 0, 1);
    if(_angleY != 0 || _angleZ !=0)
    {
        if(rotation) {
            _view.rotate(_angleY, 0, 1, 0, _at);
            _view.rotate(_angleZ, 0, 0, 1, _at);
        }

        Vector3D d;
        d.X = _view[3];
        d.Y = _view[7];
        d.Z = _view[11];
        // This creates a vector by multiplying -d by the mat3 part of the view matrix.
        Vector3D retVec = _view.mul3(-d);
        _eye = retVec;
    }
}

few things which might be need :

void Matrix4::lookAt(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ)
{
    Vector3D axe (upX, upY, upZ);
    Vector3D forward(targetX - eyeX, targetY - eyeY, targetZ - eyeZ);
    Vector3D normal = Vector3D::crossProduct(forward, axe);   // normal = regard x Axe
    Vector3D newAxe = Vector3D::crossProduct(normal, forward); // newAxe = normal x regard

    // Normalize new vectors
    forward.normalize();
    normal.normalize();
    newAxe.normalize();

    // lookAt matrix
    Matrix4 Matrix4;
    Matrix4.values_[0] = (float)normal[0];
    Matrix4.values_[1] = (float)normal[1];
    Matrix4.values_[2] = (float)normal[2];
    Matrix4.values_[4] = (float)newAxe[0];
    Matrix4.values_[5] = (float)newAxe[1];
    Matrix4.values_[6] = (float)newAxe[2];
    Matrix4.values_[8] = (float)-forward[0];
    Matrix4.values_[9] = (float)-forward[1];
    Matrix4.values_[10] = (float)-forward[2];
    Matrix4.values_[15] = 1.0f;

    *this *= Matrix4;

    // translation is part of the lookAt function
    translate(-eyeX, -eyeY, -eyeZ);
}

If someone understands what I'm doing wrong, it might help a lot, I spent a while with this problem... Thanks,

\$\endgroup\$
2
\$\begingroup\$

The lookAt matrix is like this:

RightX      RightY      RightZ      0
UpX         UpY         UpZ         0
LookX       LookY       LookZ       0
PosX        PosY        PosZ        1

Or in your code

normal[0]   normal[1]   normal[2]     0
newAxe[0]   newAxe[1]   newAxe[2]     0
-forward[0] -forward[1] -forward[2]   0
eyeX        eyeY       eyeZ           1

With the indexes in the matrix as follows:

0           1           2             3
4           5           6             7
8           9           10            11
12          13          14            15

As you can see, you should be reading the indexes 12, 13 and 14:

d.X = _view[12];
d.Y = _view[13];
d.Z = _view[14];

This is quote from the OpenGL FAQ on Transformations:

For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 as described in section 2.11.2 of the OpenGL 2.1 Specification.

Of course, we are using 0 based indexes, so the 13th, 14th, and 15th elements are the indexes 12, 13 and 14.

\$\endgroup\$
  • \$\begingroup\$ It seems that I've much more : normal[0] normal[1] normal[2] eyeX newAxe[0] newAxe[1] newAxe[2] eyeY -forward[0] -forward[1] -forward[2] eyeZ ` 0 0 0 1` Is that possible ? :/ It's actually working well exect for eye position extraction. \$\endgroup\$ – Quentin Tealrod Mar 5 '17 at 12:42
  • \$\begingroup\$ void Matrix4::translate(float X, float Y, float Z) { Matrix4 translation; translation.loadIdentity(); translation.values_[3] = X; translation.values_[7] = Y; translation.values_[11] = Z; *this *= translation; } \$\endgroup\$ – Quentin Tealrod Mar 5 '17 at 12:45
  • \$\begingroup\$ @QuentinTealrod the four vectors should be oriented in the matrix in the same way. Edit: Based on that I would say that the translation is wrong, I would review the multiplication also. \$\endgroup\$ – Theraot Mar 5 '17 at 14:56

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.