2013-09-14 3 views
1

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

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

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

лопнул, матрица версия.

Пожалуйста, обратите внимание, что снимок экрана только часть фактического экрана. Эти кнопки, которые вы видите в обоих, накладываются с использованием 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 
} 

ответ

0

OpenGL использует столбцы матрицы. Кажется, вы заполняете свою матрицу по строкам, это действительно работает в Direct3D (row-major) FYI.

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

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

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

+0

Спасибо за ответ. Я попробовал транспонирование, но он все еще искажает, но на этот раз вместо того, чтобы приближаться к неправильному пути, он растягивается довольно интересным образом. – DiscoStu

Смежные вопросы