Java中的OpenGL,gluLookAt矩阵的手动创建
我一直在尝试使用矩阵操作,而不是使用OpenGL ES和ulti库附带的基于euler或四元数的函数 我可以让大多数东西正常工作,但是我不能完全正确地重新创建gluLookAt函数,正如您可以从下面的屏幕截图中看到的: 正确的gluLookAt版本 被破坏的矩阵版本 请注意,屏幕截图只是实际屏幕的一部分。在两幅图像中看到的按钮都是使用二维正交法完成的重叠,它们有助于显示差异,因为它们在两幅图像中位于同一位置 我从这里获取了我的信息: 我在下面的java代码中重新创建了它,省略了一些细节:Java中的OpenGL,gluLookAt矩阵的手动创建,java,opengl-es,glulookat,Java,Opengl Es,Glulookat,我一直在尝试使用矩阵操作,而不是使用OpenGL ES和ulti库附带的基于euler或四元数的函数 我可以让大多数东西正常工作,但是我不能完全正确地重新创建gluLookAt函数,正如您可以从下面的屏幕截图中看到的: 正确的gluLookAt版本 被破坏的矩阵版本 请注意,屏幕截图只是实际屏幕的一部分。在两幅图像中看到的按钮都是使用二维正交法完成的重叠,它们有助于显示差异,因为它们在两幅图像中位于同一位置 我从这里获取了我的信息: 我在下面的java代码中重新创建了它,省略了一些细节: cl
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
}
OpenGL使用列主矩阵。您似乎正在逐行填充矩阵,这实际上在Direct3D行中有效,仅供参考 最简单的解决方案是调用mLookatMx.transpose。。。如果您使用的是适当的矩阵类;这将为您翻转行和列 但是,由于您使用的是一个普通的旧FloatBuffer,因此需要将。。。矩阵的内容一次只显示一列,而不是一次显示一行
顺便说一下,OpenGL的核心总是使用矩阵进行转换。那些Euler角度和四元数辅助工具工具实际上只是为OpenGL创建变换矩阵。您可以在顶点着色器中实现非基于矩阵的变换,但这比您现在想象的更高级:谢谢您的回复。我尝试了转置,但它仍然扭曲,但这次不是以错误的方式缩放,而是以一种非常有趣的方式拉伸。