如何将modelview矩阵转换为gluLookAt参数?

时间:2013-09-07 06:24:32

标签: glulookat

我在子弹物理学中要求使用Opengl,其中我有模型视图矩阵,但需要通过调用gluLookAt获得相同的矩阵。提前谢谢。

1 个答案:

答案 0 :(得分:1)

从任何4x4矩阵我们都可以获得gluLookAt参数,即CameraPos,CameraTarget,UpVector。 以下是从ModelView矩阵中获取CameraPos,CameraTarget,UpVector的代码。

float modelViewMat[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMat);

// Here instead of model view matrix we can pass any 4x4 matrix.
float params[9];
GetGluLookAtParameters(modelViewMat, params);

CameraPos.x = params[0];
CameraPos.y = params[1];
CameraPos.z = params[2];

CameraTarget.x = params[3];
CameraTarget.y = params[4];
CameraTarget.z = params[5];

UpVector.x = params[6];
UpVector.y = params[7];
UpVector.z = params[8];


void GetGluLookAtParameters(float* m, float* gluLookAtParams)
{
    VECTOR3D sideVector(m[0], m[4], m[8]);
    VECTOR3D upVector(m[1], m[5], m[9]);
    VECTOR3D forwardVector(-m[2], -m[6], -m[10]);

    sideVector.Normalize();
    upVector.Normalize();
    forwardVector.Normalize();

    float rotMat[16];
    memcpy(rotMat, m, 16*sizeof(float));
    rotMat[12] = rotMat[13] = rotMat[14] = rotMat[3] = rotMat[7] = rotMat[11] = 0.0f;
    rotMat[15] = 1.0f;
    float rotInvert[16];
    __gluInvertMatrixd(rotMat, rotInvert);

    float transMat[16];
    memset(transMat, 0, 16*sizeof(float));
    transMat[0] = transMat[5] = transMat[10] = transMat[15] = 1.0f;
    MultMat(rotInvert, m, transMat);

    gluLookAtParams[0] = -transMat[12];
    gluLookAtParams[1] = -transMat[13];
    gluLookAtParams[2] = -transMat[14];

    gluLookAtParams[3] = -transMat[12] + forwardVector.x;
    gluLookAtParams[4] = -transMat[13] + forwardVector.y;
    gluLookAtParams[5] = -transMat[14] + forwardVector.z;

    gluLookAtParams[6] = upVector.x;
    gluLookAtParams[7] = upVector.y;
    gluLookAtParams[8] = upVector.z;
}


void MultMat(float* a, float* b, float* result)
{
    result[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
    result[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
    result[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
    result[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];

    result[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
    result[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
    result[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
    result[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];

    result[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
    result[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
    result[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
    result[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];

    result[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
    result[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
    result[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
    result[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
}


int __gluInvertMatrixd(const float src[16], float inverse[16])
{
    int i, j, k, swap;
    float t;
    GLfloat temp[4][4];

    for (i=0; i<4; i++)
        for (j=0; j<4; j++)
            temp[i][j] = src[i*4+j];

    for(int i=0;i<16;i++)
        inverse[i] = 0;
    inverse[0] = inverse[5] = inverse[10] = inverse[15] = 1.0f;

    for(i=0; i<4; i++)
    {
        swap = i;
        for (j = i + 1; j < 4; j++)
            if (fabs(temp[j][i]) > fabs(temp[i][i]))
                swap = j;

        if (swap != i) {
            //Swap rows.
            for (k = 0; k < 4; k++) {
                t = temp[i][k];
                temp[i][k] = temp[swap][k];
                temp[swap][k] = t;

                t = inverse[i*4+k];
                inverse[i*4+k] = inverse[swap*4+k];
                inverse[swap*4+k] = t;
            }
        }

        if (temp[i][i] == 0)
            return 0;

        t = temp[i][i];
        for (k = 0; k < 4; k++) {
            temp[i][k] /= t;
            inverse[i*4+k] /= t;
        }

        for (j = 0; j < 4; j++) {
            if (j != i) {
                t = temp[j][i];
                for (k = 0; k < 4; k++) {
                    temp[j][k] -= temp[i][k]*t;
                    inverse[j*4+k] -= inverse[i*4+k]*t;
                }
            }
        }
    }

    return 1;
}