Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a camera matrix (compatible with OpenGL ES 2.0):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f,
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a camera matrix (compatible with OpenGL ES 2.0):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
float(m_renderbufferWidth)/float(m_renderbufferHeight), // Screen width/height
                        0.01f, 2.0f,
2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a camera matrix (compatible with OpenGL ES 2.0):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight), // Screen width/height
float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a camera matrix (compatible with OpenGL ES 2.0):2.0 and higher):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible with OpenGL ES 2.0 and higher):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible with OpenGL ES 2.0 and higher):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

OpenGL 4x4 camera matrix, OpenCV ?x? camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible with OpenGL ES 2.0 and higher):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

... and the vertex and fragment shaders are:

// vertex shader
attribute vec3 position;
attribute vec2 tex_coord;
uniform mat4 mvp_matrix;
varying vec2 frag_tex_coord;

void main()
{
    frag_tex_coord = tex_coord;
    gl_Position = mvp_matrix*vec4(position, 1);
}

// fragment shader
uniform sampler2D tex;
varying mediump vec2 frag_tex_coord;

void main()
{
    gl_FragColor = texture2D(tex, frag_tex_coord);
}

OpenGL 4x4 camera matrix, OpenCV ?x? camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible with OpenGL ES 2.0 and higher):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, //Near, // Z near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

... and the vertex and fragment shaders are:

// vertex shader
attribute vec3 position;
attribute vec2 tex_coord;
uniform mat4 mvp_matrix;
varying vec2 frag_tex_coord;

void main()
{
    frag_tex_coord = tex_coord;
    gl_Position = mvp_matrix*vec4(position, 1);
}

// fragment shader
uniform sampler2D tex;
varying mediump vec2 frag_tex_coord;

void main()
{
    gl_FragColor = texture2D(tex, frag_tex_coord);
}

OpenGL 4x4 camera matrix, OpenCV ?x? camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible with OpenGL ES 2.0 and higher):higher, see the camera matrix applied in the code https://github.com/sjhalayka/blind_poker):

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, // Z near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

... and the vertex and fragment shaders are:

// vertex shader
attribute vec3 position;
attribute vec2 tex_coord;
uniform mat4 mvp_matrix;
varying vec2 frag_tex_coord;

void main()
{
    frag_tex_coord = tex_coord;
    gl_Position = mvp_matrix*vec4(position, 1);
}

// fragment shader
uniform sampler2D tex;
varying mediump vec2 frag_tex_coord;

void main()
{
    gl_FragColor = texture2D(tex, frag_tex_coord);
}

OpenGL 4x4 camera matrix, OpenCV ?x? camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix (compatible matrix. Compatible with OpenGL ES 2.0 and higher, see higher. See the camera matrix applied in the full code https://github.com/sjhalayka/blind_poker):https://github.com/sjhalayka/blind_poker:

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
                        0.01f, 2.0f, // Z near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

... and the vertex and fragment shaders are:

// vertex shader
attribute vec3 position;
attribute vec2 tex_coord;
uniform mat4 mvp_matrix;
varying vec2 frag_tex_coord;

void main()
{
    frag_tex_coord = tex_coord;
    gl_Position = mvp_matrix*vec4(position, 1);
}

// fragment shader
uniform sampler2D tex;
varying mediump vec2 frag_tex_coord;

void main()
{
    gl_FragColor = texture2D(tex, frag_tex_coord);
}

OpenGL 4x4 camera matrix, OpenCV ?x? camera matrix

In OpenGL, the camera matrix is a 4x4 matrix. Is the camera matrix in OpenCV a 4x4 matrix as well?

The following is the code needed to make a very simple camera matrix. Compatible with OpenGL ES 2.0 and higher. See the camera matrix applied in the full code https://github.com/sjhalayka/blind_poker:

float projection_modelview_mat[16];

init_perspective_camera(y_fov_degrees,
                        float(m_renderbufferWidth)/float(m_renderbufferHeight),
static_cast<float>(screen_width)/static_cast<float>(screen_height),
                        0.01f, 2.0f, // Z near, far distances.
                        0, 0, 1, // Camera position.
                        0, 0, 0, // Look at position.
                        0, 1, 0, // Up direction vector.
                        projection_modelview_mat);

... where ...

void get_perspective_matrix(float fovy, float aspect, float znear, float zfar, float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
    const float pi = 4.0f*atanf(1.0);

    // Convert fovy to radians, then divide by 2
    float       f = 1.0f / tan(fovy/360.0*pi);

    mat[0] = f/aspect; mat[4] = 0; mat[8] = 0;                              mat[12] = 0;
    mat[1] = 0;        mat[5] = f; mat[9] = 0;                              mat[13] = 0;
    mat[2] = 0;        mat[6] = 0; mat[10] = (zfar + znear)/(znear - zfar); mat[14] = (2.0f*zfar*znear)/(znear - zfar);
    mat[3] = 0;        mat[7] = 0; mat[11] = -1;                            mat[15] = 0;
}

void get_look_at_matrix(float eyex, float eyey, float eyez,
                        float centrex, float centrey, float centrez,
                        float upx, float upy, float upz,
                        float (&mat)[16])
{
    // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
    vertex_3 f, up, s, u;

    f.x = centrex - eyex;
    f.y = centrey - eyey;
    f.z = centrez - eyez;
    f.normalize();

    up.x = upx;
    up.y = upy;
    up.z = upz;
    up.normalize();

    s = f.cross(up);
    s.normalize();

    u = s.cross(f);
    u.normalize();

    mat[0] = s.x;  mat[4] = s.y;  mat[8] = s.z;   mat[12] = 0;
    mat[1] = u.x;  mat[5] = u.y;  mat[9] = u.z;   mat[13] = 0;
    mat[2] = -f.x; mat[6] = -f.y; mat[10] = -f.z; mat[14] = 0;
    mat[3] = 0;    mat[7] = 0;    mat[11] = 0;    mat[15] = 1;

    float translate[16];
    translate[0] = 1; translate[4] = 0; translate[8] = 0;  translate[12] = -eyex;
    translate[1] = 0; translate[5] = 1; translate[9] = 0;  translate[13] = -eyey;
    translate[2] = 0; translate[6] = 0; translate[10] = 1; translate[14] = -eyez;
    translate[3] = 0; translate[7] = 0; translate[11] = 0; translate[15] = 1;

    float temp[16];
    multiply_4x4_matrices(mat, translate, temp);

    for(size_t i = 0; i < 16; i++)
        mat[i] = temp[i];
}


void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    /*
    matrix layout:

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

    out[0] =  in_a[0] * in_b[0] +  in_a[4] * in_b[1] +  in_a[8] *  in_b[2] +  in_a[12] * in_b[3];
    out[1] =  in_a[1] * in_b[0] +  in_a[5] * in_b[1] +  in_a[9] *  in_b[2] +  in_a[13] * in_b[3];
    out[2] =  in_a[2] * in_b[0] +  in_a[6] * in_b[1] +  in_a[10] * in_b[2] +  in_a[14] * in_b[3];
    out[3] =  in_a[3] * in_b[0] +  in_a[7] * in_b[1] +  in_a[11] * in_b[2] +  in_a[15] * in_b[3];
    out[4] =  in_a[0] * in_b[4] +  in_a[4] * in_b[5] +  in_a[8] *  in_b[6] +  in_a[12] * in_b[7];
    out[5] =  in_a[1] * in_b[4] +  in_a[5] * in_b[5] +  in_a[9] *  in_b[6] +  in_a[13] * in_b[7];
    out[6] =  in_a[2] * in_b[4] +  in_a[6] * in_b[5] +  in_a[10] * in_b[6] +  in_a[14] * in_b[7];
    out[7] =  in_a[3] * in_b[4] +  in_a[7] * in_b[5] +  in_a[11] * in_b[6] +  in_a[15] * in_b[7];
    out[8] =  in_a[0] * in_b[8] +  in_a[4] * in_b[9] +  in_a[8] *  in_b[10] + in_a[12] * in_b[11];
    out[9] =  in_a[1] * in_b[8] +  in_a[5] * in_b[9] +  in_a[9] *  in_b[10] + in_a[13] * in_b[11];
    out[10] = in_a[2] * in_b[8] +  in_a[6] * in_b[9] +  in_a[10] * in_b[10] + in_a[14] * in_b[11];
    out[11] = in_a[3] * in_b[8] +  in_a[7] * in_b[9] +  in_a[11] * in_b[10] + in_a[15] * in_b[11];
    out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] *  in_b[14] + in_a[12] * in_b[15];
    out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] *  in_b[14] + in_a[13] * in_b[15];
    out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
    out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}

/*
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            out[4*i + j] = 0;

            for (int k = 0; k < 4; k++)
                out[4*i + j] += in_a[4*k + j] * in_b[4*i + k];
        }
    }
}
*/


void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
                             float eyex, float eyey, float eyez, float centrex, float centrey,
                             float centrez, float upx, float upy, float upz,
                             float (&projection_modelview_mat)[16])
{
    float projection_mat[16];
    get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);

    float modelview_mat[16];
    get_look_at_matrix(eyex, eyey, eyez, // Eye position.
                       centrex, centrey, centrez, // Look at position (not direction).
                       upx, upy, upz,  // Up direction vector.
                       modelview_mat);

    multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}

... and the vertex and fragment shaders are:

// vertex shader
attribute vec3 position;
attribute vec2 tex_coord;
uniform mat4 mvp_matrix;
varying vec2 frag_tex_coord;

void main()
{
    frag_tex_coord = tex_coord;
    gl_Position = mvp_matrix*vec4(position, 1);
}

// fragment shader
uniform sampler2D tex;
varying mediump vec2 frag_tex_coord;

void main()
{
    gl_FragColor = texture2D(tex, frag_tex_coord);
}