4
\$\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\$
0

1 Answer 1

5
\$\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\$
3
  • \$\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\$ Mar 5, 2017 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\$ Mar 5, 2017 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, 2017 at 14:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .