OpenGL на Java, ручное создание матрицы gluLookAt

Я экспериментировал с использованием матричной манипуляции вместо использования функций на основе эйлера или кватерниона, которые поставляются с Open GL ES (и ulti lib).

Я могу заставить большинство вещей работать, но я не могу воссоздать функцию gluLookAt совершенно правильно, как вы сможете увидеть на скриншотах ниже:

Правильная версия gluLookAt.

Busted, матричная версия.

Обратите внимание, что снимок экрана - это только часть реального экрана. Эти кнопки, которые вы видите в обеих, являются наложениями, выполненными с использованием 2D-орфографии, и они помогают показать разницу, потому что они находятся в одном месте на обоих изображениях.

Я взял мою информацию отсюда: http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml

Который я воссоздал в своем коде Java ниже (некоторые детали опущены):

class point3D {
    public double mX, mY, mZ;
}

double scaler(point3D pt){
    return Math.pow(
        Math.pow(pt.mX, 2.0) + Math.pow(pt.mY, 2.0) + Math.pow(pt.mZ, 2.0),
        1.0/3.0
    );
}

void cross(point3D A, point3D B, point3D output){
    output.mX = (A.mY*B.mZ) - (A.mZ*B.mY);
    output.mY = (A.mZ*B.mX) - (A.mX*B.mZ);
    output.mZ = (A.mX*B.mY) - (A.mY*B.mX);
}

void normalise(point3D normMe, point3D output){
    double s = scaler(normMe);
    output.mX = normMe.mX / s;
    output.mY = normMe.mY / s;
    output.mZ = normMe.mZ / s;
}

float mx, my, mz, mfx, mfy, mfz;
private FloatBuffer mLookatMx; //- All setup and stuff elsewhere

void myLookAt(){
    point3D ptTmpA, ptTmpB, ptTmpC, ptTmpD;

    //- 'forward' F part
    ptTmpA.mX = mfx - mx;
    ptTmpA.mY = mfy - my;
    ptTmpA.mZ = mfz - mz;
    normalise(ptTmpA, ptTmpA);

    //- 'up' part
    ptTmpB.mX = 0;
    ptTmpB.mY = 1.0;
    ptTmpB.mZ = 0;

    cross(ptTmpB, ptTmpA, ptTmpC);  //- S
    normalise(ptTmpC, ptTmpC);

    cross(ptTmpA, ptTmpC, ptTmpD);  //- U
    normalise(ptTmpD, ptTmpD);

    //- the 4x4 matrix. Not including the transformation this time for simplicity.
    //- m = {
    //-        s1,  s2,  s3, -x
    //-        u1,  u2,  u3, -y
    //-       -f1, -f2, -f3, -z
    //-         0,   0,   0,  1
    //- }

    //- 0
    mLookatMx.put((float)ptTmpC.mX);            
    mLookatMx.put((float)ptTmpC.mY);            
    mLookatMx.put((float)ptTmpC.mZ);            
    mLookatMx.put(0);

    //- 4
    mLookatMx.put((float)ptTmpD.mX);            
    mLookatMx.put((float)ptTmpD.mY);            
    mLookatMx.put((float)ptTmpD.mZ);            
    mLookatMx.put(0);

    //- 12
    mLookatMx.put((float)ptTmpA.mX *-1.0f); 
    mLookatMx.put((float)ptTmpA.mY *-1.0f); 
    mLookatMx.put((float)ptTmpA.mZ *-1.0f); 
    mLookatMx.put(0);

    //- 16
    mLookatMx.put(0);                           
    mLookatMx.put(0);                           
    mLookatMx.put(0);                           
    mLookatMx.put(1.0f);
    mLookatMx.position(0);
}

void myDraw(){
    glDisable(GL_DEPTH_BITS);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(mGL, 90.0, mScreen.mX / mScreen.mY, 0.01, 10.0);

    //- This works
    //gluLookAt(mGL, 
    //    mx, my, mz, 
    //    mfx, mfy, mfz,
    //    0.0f, 1.0f, 0.0f
    //);

    //- This is distorted
    glMultMatrixf(mLookatMx);
    glTranslatef(mx * -1.0f, my * -1.0f, mz * -1.0f)

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //- draw models as seen in screen shot
}

1 ответ

OpenGL использует матрицы столбцов. Вы, кажется, заполняете свою матрицу построчно, это фактически будет работать в Direct3D (основной ряд).

Самое простое решение было бы позвонить mLookatMx.transpose (...) (если вы использовали правильный класс матрицы); это перевернет строки и столбцы для вас.

Тем не менее, так как вы используете простой старый FloatBuffer, вам нужно put (...) содержимое вашей матрицы по одному столбцу за раз вместо одной строки за раз.

Кстати, в своей основе OpenGL всегда использует матрицы для преобразований. Эти вспомогательные утилиты Euler angle и quaternion просто создают матрицы преобразования для OpenGL. Вы можете реализовать нематричные преобразования в вершинных шейдерах, но это намного сложнее, чем вы думаете сейчас:)

Другие вопросы по тегам