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
}