【问题标题】:OpenGL in Java, Manual creatation of gluLookAt matrixJava中的OpenGL,手动创建gluLookAt矩阵
【发布时间】:2013-09-14 13:31:54
【问题描述】:

我一直在尝试使用矩阵操作,而不是使用 Open GL ES(和 ulti lib)附带的基于欧拉或四元数的函数。

我可以让大多数东西正常工作,但是我无法完全正确地重新创建 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
}

【问题讨论】:

    标签: java opengl-es glulookat


    【解决方案1】:

    OpenGL 使用列优先矩阵。您似乎正在逐行填充矩阵,这实际上可以在 Direct3D(行主要)FYI 中工作。

    最简单的解决方案是调用mLookatMx.transpose (...)(如果您使用的是适当的矩阵类);这将为您翻转行和列。

    但是,由于您使用的是普通的旧 FloatBuffer,因此您需要 put (...) 矩阵的内容一次一列,而不是一次一行。

    顺便说一句,OpenGL 的核心始终使用矩阵进行转换。那些欧拉角和四元数辅助实用程序实际上只是为 OpenGL 创建变换矩阵。您可以在顶点着色器中实现基于非矩阵的转换,但这比您现在应该考虑的要先进 :)

    【讨论】:

    • 感谢您的回复。我尝试了转置,但它仍然变形,但这一次不是以错误的方式放大,而是以一种非常有趣的方式拉伸。
    猜你喜欢
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2018-03-07
    相关资源
    最近更新 更多