2

私は LWJGL で作業しており、シーンの単純な 3D 表示を可能にするプログラムを作成するのにしばらく苦労しています。私が直面している主な問題は、パースペクティブを適用するたびに、シーンが z 軸で非常に遠くまで引き伸ばされることです。良くない

真ん中の四角は正射影で描いた立方体です(ここでの立方体は「すべての辺が等しい」という意味です)。左下から中央に向かって垂れ下がった形も立方体ですが、透視投影で描きました!

明らかに、これは立方体のようには見えません。これが私のコードです(これは少し壁なので、分割しました):

public class OpenGL
{
    //width and height of the screen, plus the depth of the 3d space
    public static final int WIDTH = 800, HEIGHT = 600, DEPTH = 1000;

    //called once at startup
    private static void initGl()
    {
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glEnable(GL11.GL_DEPTH_TEST);

        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glViewport(0,0,WIDTH,HEIGHT);
        GL11.glDepthFunc(GL11.GL_LESS);
        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
        GL11.glClearColor(0,0,0,0);
        GL11.glShadeModel(GL11.GL_SMOOTH);

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, WIDTH, HEIGHT, 0, DEPTH, -DEPTH);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        DEFAULT_FONT.addAsciiGlyphs();
        DEFAULT_FONT.addGlyphs(400, 600);
        DEFAULT_FONT.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
        try
        {
            DEFAULT_FONT.loadGlyphs();
        }
        catch (SlickException e)
        {
            e.printStackTrace();
        }
    }
}

これらはすべて別のクラスにあり、1 秒間に 30 回呼び出されます。

//main rendering function.
public void render()
{   
        //these two just input values for different variables, allowing for 
        //movement of the camera and testing different values of znear and zfar.  
        //nothing OpenGL-related is changed.
        update();
        updatePerspectiveTest();

        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        p.render(); //draws the normal cube, the "player"

        if (perspective)
        {
            perspective();
        }

        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        loadRotationalMatrix(yaw,pitch,roll);
        loadPositionalMatrix(-y,-x,-z);

        env.render(); //draws the distorted cube, the "environment"

        GL11.glLoadIdentity();

        ortho();

        //render debug data
}


//resets to orthographic projection
public static void ortho()
{
        int i = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(-OpenGL.WIDTH/2, OpenGL.WIDTH/2, 
                OpenGL.HEIGHT/2, -OpenGL.HEIGHT/2, OpenGL.DEPTH/2, -OpenGL.DEPTH/2);
        GL11.glMatrixMode(i);
}

パースペクティブをオンにする機能です。これがおそらく問題の場所です。

//activate perspective projection. Maybe something wrong here?
public static void perspective()
{
    int i = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glFrustum(-OpenGL.WIDTH/2, OpenGL.WIDTH/2, 
                OpenGL.HEIGHT/2, -OpenGL.HEIGHT/2, 
                pzNear, pzFar);
    GL11.glMatrixMode(i);
}

これらの関数は変換に使用されます。関係ないかもしれませんが、入れて良かったと思います。

//translates the camera via matrix multiplication.
public static void loadPositionalMatrix(float x, float y, float z)
{
    FloatBuffer m = BufferUtils.createFloatBuffer(16);

    m.put(new float[]
            {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            x, y, z, 1
            });

    m.flip();

    GL11.glMultMatrix(m);
}

    //sets yaw, pitch and roll using rotational matrices. Not really being used now.
public static void loadRotationalMatrix(double pitch, double yaw, double roll)
{
        FloatBuffer Ry = BufferUtils.createFloatBuffer(16);
        FloatBuffer Rx = BufferUtils.createFloatBuffer(16);
        FloatBuffer Rz = BufferUtils.createFloatBuffer(16);

        Rx.put(new float[]
                {
                1, 0, 0, 0,
                0, (float) cos(pitch), (float) sin(pitch), 0,
                0, (float) -sin(pitch), (float) cos(pitch), 0,
                0, 0, 0, 1
                });
        Ry.put(new float[]
                {
                (float) cos(yaw), 0, (float) -sin(yaw),  0,
                0, 1, 0, 0,
                (float) sin(yaw), 0, (float) cos(yaw), 0,
                0, 0, 0, 1
                });
        Rz.put(new float[]
                {
                (float) cos(roll), (float) sin(roll), 0, 0,
                (float) -sin(roll), (float) cos(roll), 0, 0, 
                0, 0, 1, 0,
                0, 0, 0, 1
                });

        Rx.flip();
        Ry.flip();
        Rz.flip();

        GL11.glMultMatrix(Rz);
        GL11.glMultMatrix(Ry);
        GL11.glMultMatrix(Rx);
    }

zNear と zFar をいじってみましたが、これまでに試した値では正しい投影が得られませんでした。

具体的な質問は次のとおりです: 2 番目の立方体がひどく歪んで見えるのはなぜですか? また、それを修正するにはどうすればよいでしょうか?

4

1 に答える 1

3

クリッピング プレーンは、マトリックスが 3D 環境から画面に投影するために使用されます。したがって、x および y クリッピング プレーンは、ウィンドウのアスペクト比と FOV を考慮する必要があります。したがって、次のようなものが必要です。

...
double fovyInDegrees = 50; // Change this if you want.
double ymax, xmax, aspectRatio;
aspectRatio = OpenGL.WIDTH / OpenGL.HEIGHT;
ymax = znear * Math.tan(fovyInDegrees * Math.PI / 360);
xmax = ymax * aspectRatio;
GL11.glFrustum(-xmax, xmax, -ymax, ymax, znear, zfar);
...

C++ コードの一部を Java に変更したばかりなので、これはテストされていないことに注意してください。ただし、私のコードでは機能するので、問題ないはずです。

于 2013-06-03T20:30:58.460 に答える