gpt4 book ai didi

java - OpenGL 透视图在 z 轴上的场景扭曲程度远超预期

转载 作者:行者123 更新时间:2023-12-04 04:54:47 25 4
gpt4 key购买 nike

我在 LWJGL 工作,并且一直在努力编写一个允许简单 3d 查看场景的程序。我遇到的主要问题是,每当我应用透视时,我的场景在 z 轴上被拉伸(stretch)得非常非常远。 Not good

中间的正方形是用正交投影绘制的立方体(这里立方体的意思是“所有边都相等”)。从左下角到中心的形状也是一个立方体,但是用透视投影绘制的!

显然,这看起来不像一个立方体。这是我的代码(它有点像一堵墙,所以我把它拆了):

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();
}
}
}

这些都在另一个类中,每秒被调用 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,但到目前为止我尝试过的值都没有导致正确的投影。

具体问题是:为什么第二个立方体看起来如此可怕地扭曲,我能做些什么来纠正它?

最佳答案

矩阵使用剪切平面从 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,因此未经测试。它在我的代码中工作,所以应该没问题。

关于java - OpenGL 透视图在 z 轴上的场景扭曲程度远超预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16904578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com