1

I've been experimenting with using matrix manipulation instead of using the euler or quaternion based functions that come with Open GL ES (and the ulti lib).

I can get most stuff working, however I can't recreate the gluLookAt function quite right, as you will be able to see from the screen shots below:

The correct gluLookAt version.

The busted, matrix version.

Please note, the screen shot is just a portion of the actual screen. Those buttons you see in both are overlays done using 2D orthographic, and they help show the difference because they're in the same spot in both images.

I took my information from here: http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml

Which I recreated in my java code in below (some details omitted):

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
}
DiscoStu
  • 559
  • 6
  • 15

1 Answers1

0

OpenGL uses column-major matrices. You appear to be filling your matrix row-by-row, this would actually work in Direct3D (row-major) FYI.

The simplest solution would be to call mLookatMx.transpose (...) (if you were using a proper matrix class); this would flip the rows and columns for you.

However, since you are using a plain old FloatBuffer, you need to put (...) the contents of your matrix one column at a time instead of one row at a time.

By the way, at its core OpenGL always uses matrices for transformations. Those Euler angle and quaternion helper utilities really just create transformation matrices for OpenGL. You can implement non-matrix based transformations in vertex shaders, but that is more advanced than you should be thinking right now :)

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Thanks for the reply. I tried a transpose but it still distorts, but this time instead of zooming about in the wrong way, it stretches in a pretty interesting way. – DiscoStu Sep 15 '13 at 14:09